Learning AI with Fuzzy Logic

Founder Lê Trần Đạt asked “Có lẽ đã đến lúc lập trình viên nên học AI/ML”. AI/ML learning is individual and depends on the learner’s abstract imagination. E.g.: AI with fuzzy logic.

First of all: Human intelligence (HI) is fuzzy. This means that we recognize things analogously, while computers work digitally and AI is based on computers. Or in other words, HI is continuous or fuzzy and AI is discrete (click HERE for more information on continuous and discrete). If you want to learn AI, you should first understand the state of an observed thing, which can be clear or fuzzy. Humans mostly think fuzzy, but humans can still draw a correct conclusion from the fuzzy state. For example, we can easily recognize a face with or without a beard. We can do it because we apply the face with certain similarity probability. Anyway, face recognition is a real challenge for AI and it can only be achieved using Fuzzy Logic (invented by Lotfi Zadeh).

I won’t go into detail about Fuzzy Logic or face recognition, but I will present you an example that will show you how Fuzzy Logic can be easily implemented for image recognition. Note: correction after @Stanley00 's hint.

    import java.awt.image.BufferedImage;
    import javax.imageio.ImageIO;
    import java.io.File;
    // Joe (C)
    public class Fuzzy {
      public static void main(String... argv) throws Exception {
        if (argv.length != 3) {
          System.out.println("Usage:   java Fuzzy image_file_1 image_file_2 Probability\n"+
                             "Example: java Fuzzy cat_1.jpg cat_2.jpg 0.2");
          System.exit(0);
        }
        System.out.println("Discrete:"+discreteEqual(argv[0], argv[1])+
        "\nFuzzy   :"+fuzzyEqual(argv[0], argv[1], Float.parseFloat(argv[2])));
      }
      /*
        Parameter p is the probability (0.0 .. 1.0) that a match will yield
        if 2 images are similar: 2 images only deviate from each other in p percent
      */
  public static boolean fuzzyEqual(String fImg1, String fImg2, float p) throws Exception {
    BufferedImage img1 = ImageIO.read(new File(fImg1));
    BufferedImage img2 = ImageIO.read(new File(fImg2));
    int w1 = img1.getWidth(), h1 = img1.getHeight();
    //
    int s = 0, t = 0;
    for (int x, y = 0; y < h1; ++y) for (x = 0; x < w1; ++x) { 
      if (img1.getRGB(x, y) == img2.getRGB(x, y)) ++s;
      ++t;
    }
    float m = (float)s/t;
    if (p == 0 && m != 1) return false;
    if (p == 1 && m >= 0  || p == 0 && m == 0) return true;
    return (p >= m || p >= (1-m));
  }    
      /*
      Absolute compare or discrete compare
      */
      public static boolean discreteEqual(String fImg1, String fImg2) throws Exception {
        BufferedImage img1 = ImageIO.read(new File(fImg1));
        BufferedImage img2 = ImageIO.read(new File(fImg2));
        int w1 = img1.getWidth(), h1 = img1.getHeight();
        if (w1 != img2.getWidth() || h1 != img2.getHeight()) return false;
        for (int x, y = 0; y < h1; ++y) for (x = 0; x < w1; ++x) {     
          if (img1.getRGB(x, y) != img2.getRGB(x, y)) return false;
        }
        return true;
      }  
    }

and the results with 3 similar images (the right eye of cat_3.jpg has a different hue) are:
Cat_1.jpg
Cat_1
Cat_2.jpg (blurred Cat_1)
Cat_2
Cat_3.jpg (slightly different hue of right eye)
Cat_3

With 10% (0.1) and 20% (0.2) dissimilarity

C:\JFX\image\Test>java Fuzzy cat_1.jpg cat_1.jpg 0.1
Discrete:true
Fuzzy   :true

C:\JFX\image\Test>java Fuzzy cat_1.jpg cat_2.jpg 0.1
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_1.jpg cat_2.jpg 0.2
Discrete:false
Fuzzy   :true

C:\JFX\image\Test>java Fuzzy cat_3.jpg cat_2.jpg 0.2
Discrete:false
Fuzzy   :true

C:\JFX\image\Test>java Fuzzy cat_3.jpg cat_2.jpg 0.1
Discrete:false
Fuzzy   :false

With p = 0.5, this statement literally translated as m>=0 && m<=1, which mean, whatever two images you provided, the output is always True:upside_down_face:

2 Likes

@Stanley00
You’re right. My typing and calculation error. The last line of fuzzyEqual must be

  public static boolean fuzzyEqual(String fImg1, String fImg2, float p) throws Exception {
    BufferedImage img1 = ImageIO.read(new File(fImg1));
    BufferedImage img2 = ImageIO.read(new File(fImg2));
    int w1 = img1.getWidth(), h1 = img1.getHeight();
    //
    int s = 0, t = 0;
    for (int x, y = 0; y < h1; ++y) for (x = 0; x < w1; ++x) { 
      if (img1.getRGB(x, y) == img2.getRGB(x, y)) ++s;
      ++t;
    }
    float P = 1f-p;    
    float m = (float)s/t;
    if (m == 1f) return true;
    //return P >= (m-p) && P <= (m+p);
    return P <= (1-m) && P >= m;
 }

Are we doing online debugger now? This statement is like return m<=p && m<=P;, which mean return True if 2 images match less than min(p, P), which will never greater than 50%
So I believe you will get surprised result if you run java Fuzzy cat_3.jpg cat_1.jpg 0.2 or java Fuzzy cat_3.jpg cat_1.jpg 0.1

1 Like

@Stanley_00
Thank you for your interest and checking. You know, I just want to emphasize the fuzzy technique that can be applied in AI (like IBM chess computer Deep Blue), not the 100% correctness of the codes. Reason: as I said, it’s about FUZZY - and that means that the result does not have to be 100% like “CRISP/DISCRETE”… However, if someone like you is interested in this topic, he could complement the given example that I wrote down spontaneously. I checked the example again and must acknowledge that you have good insights :heart_eyes:

For the sake of completeness:

  public static boolean fuzzyEqual(String fImg1, String fImg2, float p) throws Exception {
    BufferedImage img1 = ImageIO.read(new File(fImg1));
    BufferedImage img2 = ImageIO.read(new File(fImg2));
    int w1 = img1.getWidth(), h1 = img1.getHeight();
    //
    int s = 0, t = 0;
    for (int x, y = 0; y < h1; ++y) for (x = 0; x < w1; ++x) { 
      if (img1.getRGB(x, y) == img2.getRGB(x, y)) ++s;
      ++t;
    }
    float m = (float)s/t;
    if (p == 0 && m != 1) return false;
    if (p == 1 && m >= 0  || p == 0 && m == 0) return true;
    return (p >= m || p >= (1-m));
  }  

And:

So I believe you will get surprised result if you run java Fuzzy cat_3.jpg cat_1.jpg 0.2 or java Fuzzy cat_3.jpg cat_1.jpg 0.1

C:\JFX\image\Test>java Fuzzy cat_3.jpg cat_1.jpg 0.0
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_3.jpg cat_1.jpg 0.01
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_3.jpg cat_1.jpg 0.05
Discrete:false
Fuzzy   :true

C:\JFX\image\Test>java Fuzzy cat_2.jpg cat_1.jpg 0
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_2.jpg cat_1.jpg 0.1
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_2.jpg cat_1.jpg 0.15
Discrete:false
Fuzzy   :true

C:\JFX\image\Test>java Fuzzy cat_2.jpg cat_3.jpg 0.01
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_2.jpg cat_3.jpg 0.05
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_2.jpg cat_3.jpg 0.1
Discrete:false
Fuzzy   :false

C:\JFX\image\Test>java Fuzzy cat_2.jpg cat_3.jpg 0.2
Discrete:false
Fuzzy   :true

4 following video sequences (gif format) show you how to apply Fuzzy Logic AI as drone for logistic purpose: delivery and pickup.

1)PICK UP without obstacle

2) PICK UP with obstacle on the way

3) DELIVERY without obstacle

4) DELIVERY with obstacle on the way

…and the Fuzzy Logic Script:

    // FuzzyVariables and their corresponding FuzzyData and FuzzyParm
    <!Distance[tooFarAhead(-620,-520,-420,-320), veryFarAhead(-330,-230,-130,-30), farAhead(-130,-14,-10,1),target(-1,0,1), farBehind(1,10,14,130),veryFarBehind(30,130,230,330),tooFarBehind(320,420,520,620)]!>
    //
    <!Height[tooHigh(-620,-520,-420,-320),veryHigh(-330,-230,-130,-50),high(-130,-24,-16,1),goal(-1,0,1),low(1,16,24,130),veryLow(50,130,230,330), tooLow(320,420,520,620)]!>
    //
    <!Obstacle[inFront(-100,-80,-20,-1),hit(-1,0,1),ahead(1,20,80,100)]!>
    <!Maneuver[right(20,30,40),left(-20, -15, -10)]!>
    //
    <!Speed[speedBACK(-3,-2.5,-2),slowBACK(-2,-1.5,-1),back(-1,-0.5,-0.1),standing(-0.1,0,0.1),fore(0.1,0.5,1),slowFORE(1,1.5,2),speedFORE(2,2.5,3)]!>
    //
    double x = 0
    //
    while x < 3 && x >= 0
      // checck to obstacle
      Obstacle = this.checkObstacle()
      if (Obstacle is inFront) then Maneuver is right
      if (Obstacle is ahead) then Maneuver is left
      this:obstacle = Maneuver
      //
      this.computeDelta()
      Height = this:deltaY
      Distance = this:deltaX
      //-------------------------------------AHEAD------------------------------------------------------
      if ((Distance is tooFarAhead || Distance is veryFarAhead) && Height is tooHigh) then Speed is speedFORE
      if ((Distance is tooFarAhead || Distance is veryFarAhead) && Height is veryHigh) then Speed is slowFORE
      if ((Distance is tooFarAhead || Distance is veryFarAhead) && Height is high) then Speed is slowFORE
      //
      if ((Distance is tooFarAhead || Distance is veryFarAhead) && Height is tooLow) then Speed is speedFORE
      if ((Distance is tooFarAhead || Distance is veryFarAhead) && Height is veryLow) then Speed is slowFORE
      if ((Distance is tooFarAhead || Distance is veryFarAhead) && Height is low) then Speed is slowFORE
      //
      if (Distance is farAhead && Height is tooHigh) then Speed is speedFORE
      if (Distance is farAhead && Height is veryHigh) then Speed is slowFORE
      if (Distance is farAhead && Height is high) then Speed is fore
      //
      if (Distance is farAhead && Height is tooLow) then Speed is slowFORE
      if (Distance is farAhead && Height is veryLow) then Speed is slowFORE
      if (Distance is farAhead && Height is low) then Speed is fore
      //------------------------------BEHIND-------------------------------------------------------------
      if ((Distance is tooFarBehind || Distance is veryFarBehind) && Height is tooHigh) then Speed is speedBACK
      if ((Distance is tooFarBehind || Distance is veryFarBehind) && Height is veryHigh) then Speed is slowBACK
      if ((Distance is tooFarBehind || Distance is veryFarBehind) && Height is high) then Speed is slowBACK
      //
      if ((Distance is tooFarBehind || Distance is veryFarBehind) && Height is tooLow) then Speed is speedBACK
      if ((Distance is tooFarBehind || Distance is veryFarBehind) && Height is veryLow) then Speed is slowBACK
      if ((Distance is tooFarBehind || Distance is veryFarBehind) && Height is low) then Speed is slowBACK
      //
      if (Distance is farBehind && Height is tooHigh) then Speed is speedBACK
      if (Distance is farBehind && Height is veryHigh) then Speed is slowBACK
      if (Distance is farBehind && Height is high) then Speed is back
      //
      if (Distance is farBehind && Height is tooLow) then Speed is speedBACK
      if (Distance is farBehind && Height is veryLow) then Speed is slowBACK
      if (Distance is farBehind && Height is low) then Speed is back
      //----------------------------AT TARGET------------------------------------------------------------
      if (Distance is target && (Height is tooHigh || Height is veryHigh)) then Speed is slowFORE
      if (Distance is target && Height is high) then Speed is fore
      //
      if (Distance is target && (Height is tooLow || Height is veryLow)) then Speed is slowBACK
      if (Distance is target && Height is low) then Speed is back
      // ------------------------------------------------------------------------------------------------
      if (Height is goal && (Distance is tooFarBehind || Distance is veryFarBehind)) then Speed is slowFORE
      if (Height is goal && Distance is farBehind) then Speed is fore
      if (Height is goal && (Distance is tooFarAhead || Distance is veryFarAhead)) then Speed is slowBACK
      if (Height is goal && Distance is farAhead) then Speed is back
      // ------------------------------------------------------------------------------------------------
      if (Distance is target && Height is goal) then Speed is standing
      //
      // interact with Java Owner
      //
      this:speed = Speed
      x = this:home
    endwhile

Okay, now it looks more like Fuzzy Logic to me. The problem with your fuzzyEqual code is that the only line that feels as Fuzzy is the return statement, and I feel sorry saying this, but it’s terribly wrong. Anyway, it’s better with new drone code.

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?