Optimizing color tracker

edited September 24 in Library Questions

Hello, I've made this color tracker based of the Simple Color Tracking code by Daniel Shiffman, although mine tracks quite a few neighboring pixels so the tracking is beter (see attachment)

this is my code:

import processing.video.*;
Capture cam;

boolean color_selected;
int cell_width = 21;
float diffrence;

int[] Baxis = new int[cell_width];
int[] Taxis = new int[cell_width];
int[] Xaxis = new int[cell_width];
int[] Yaxis = new int[cell_width];

void setup() {
  size(640, 480);
  String[] cameras = Capture.list();
  cam = new Capture(this, width, height, cameras[1]);
  cam.start();
}      

void draw() {
  if (cam.available() == true) {
    cam.read();
  }

  image(cam, 0, 0, width, height);

  if (color_selected == true) {
    int closestX = 0; 
    int closestY = 0; 
    float closestDiff = 1000000.0f; 
    for ( int x = cell_width / 2; x < cam.width - cell_width / 2; x++) { 
      for ( int y = cell_width / 2; y < cam.height - cell_width / 2; y++) { 

        for ( int i = 0; i < cell_width; i++) {
          int loc = x + (cell_width / 2 - i) + y * cam.width; 
          color currentColor = cam.pixels[loc]; 
          int stored_color = Xaxis[i];

          float g1 = green(currentColor);
          float b1 = blue(currentColor); 
          float r1 = red(currentColor);
          float g2 = green(stored_color); 
          float b2 = blue(stored_color);  
          float r2 = red(stored_color);   

          diffrence += dist(r1, g1, b1, r2, g2, b2);
        }

        for ( int i = 0; i < cell_width; i++) {
          int loc = x + (y + (cell_width / 2 - i)) * cam.width; 
          color current_color = cam.pixels[loc]; 
          int stored_color = Yaxis[i];

          float g1 = green(current_color);
          float b1 = blue(current_color); 
          float r1 = red(current_color);
          float g2 = green(stored_color); 
          float b2 = blue(stored_color);  
          float r2 = red(stored_color);    

          diffrence += dist(r1, g1, b1, r2, g2, b2);
        }

        for ( int i = 0; i < cell_width; i++) {
          int loc = (x + (cell_width / 2 - i)) + (y + (cell_width / 2 - i)) * cam.width; 
          color current_color = cam.pixels[loc]; 
          int stored_color = Taxis[i];

          float g1 = green(current_color);
          float b1 = blue(current_color); 
          float r1 = red(current_color);
          float g2 = green(stored_color); 
          float b2 = blue(stored_color);  
          float r2 = red(stored_color);    

          diffrence += dist(r1, g1, b1, r2, g2, b2);
        }

        for ( int i = 0; i < cell_width; i++) {
          int loc = (x + (cell_width / 2 - i)) + (y + (cell_width / 2 - (cell_width - (i + 1)))) * cam.width; 
          color current_color = cam.pixels[loc]; 
          int stored_color = Baxis[i];

          float g1 = green(current_color);
          float b1 = blue(current_color); 
          float r1 = red(current_color);
          float g2 = green(stored_color); 
          float b2 = blue(stored_color);  
          float r2 = red(stored_color);    

          diffrence += dist(r1, g1, b1, r2, g2, b2);
        }

        if (diffrence < closestDiff) { 
          closestDiff = diffrence; 
          closestX = x; 
          closestY = y;
        }
        diffrence = 0; 
      }
    } 

    fill(255);
    ellipse(closestX, closestY, 16, 16);
    drawColorThing();
  }
}

void drawColorThing() {
  pushMatrix();
  rectMode(CENTER);
  translate(height/2, height/2);
  rotate(PI);

  for (int i = 0; i < cell_width; i++) {
    fill(Xaxis[i]);
    int Xax = 10 * i;
    rect(Xax, cell_width/2 * 10, 10, 10);
  }

  for (int i = 0; i < cell_width; i++) {
    fill(Yaxis[i]);
    int Xax = 10 * i;
    rect(cell_width/2 * 10, Xax, 10, 10);
  }

  for (int i = 0; i < cell_width; i++) {
    int Xax = 10 * i;
    int Yax = 10 * i;
    fill(Taxis[i]);
    rect(Xax, Yax, 10, 10);
  }

  for (int i = 0; i < cell_width; i++) {
    int Xax = 10 * (i);
    int Yax = ( cell_width * 10) - 10 * (i + 1);
    fill(Baxis[i]);
    rect(Xax, Yax, 10, 10);
  }
  popMatrix();
}

void mousePressed() { 
  color_selected = true;
  for ( int i = 0; i < cell_width; i++) {
    int loc = mouseX + (cell_width / 2 - i) + mouseY * cam.width;
    Xaxis[i] = cam.pixels[loc];
  }

  for ( int i = 0; i < cell_width; i++) {
    int loc = mouseX + (mouseY + (cell_width / 2 - i)) * cam.width;
    Yaxis[i] = cam.pixels[loc];
  }

  for ( int i = 0; i < cell_width; i++) {
    int loc = (mouseX + (cell_width / 2 - i)) + (mouseY + (cell_width / 2 - i)) * cam.width;
    Taxis[i] = cam.pixels[loc];
  }

  for ( int i = 0; i < cell_width; i++) {
    int loc = (mouseX + (cell_width / 2 - i)) + (mouseY + (cell_width / 2 - (cell_width - (i + 1)))) * cam.width;
    Baxis[i] = cam.pixels[loc];
  }
} 

I works just fine altough very very slow expecialy when I increase the number of neighbor pixels that are being checked. So does anybody have some code optimaztions tips?Untitled

Answers

  • (see attachment)

    ???

    ahould line 122 be Yaxis?

    should line 82 be Baxis?

  • @koogs Sorry, attachment is now attached. Line 122 was indeed meant to be Yaxis and 82 should have been Baxis. I updated the post to correct it

  • There are much faster ways of extracting the red, green and blue values from the pixels using bit shifting.

    Also, dist uses a relatively expensive sqrt call which I don't think you need here, you can add the squares of the distances together and that'll serve just as well.

  • The image resize in draw is terrible too.

  • @koogs Thank you for the response, by the image resize you mean this line right?

    image(cam, 0, 0, width, height);

    You mentioned bit shifting how does this work exactly? I couldn't find any sources explaining it

  • edited September 26

    @schotsl-- re:

    koogs: There are much faster ways of extracting the red, green and blue values from the pixels using bit shifting.

    See:

    https://processing.org/reference/color_datatype.html

    To extract red, green, and blue values more quickly (for instance when analyzing an image or a frame of video), use bit shifting.

    https://processing.org/reference/rightshift.html

    int r = (argb >> 16) & 0xFF;  // Faster way of getting red(argb)
    int g = (argb >> 8) & 0xFF;   // Faster way of getting green(argb)
    int b = argb & 0xFF;          // Faster way of getting blue(argb)
    
  • edited September 30

    @jeremydouglass Thank you!

    You mentioned adding the squires of the distances together as an alternative to the dist function, would this be an appropriate way to do it?

    difference += sq((r2-r1) + (g2-g1) + (b2-b1));

  • edited September 30

    Are you asking about whether to square the sum of the differences, or to square the x, y, and z components and then sum them?

    difference += (sq(r2-r1) + sq(g2-g1) + sq(b2-b1));
    
  • in addition to what others has said the x loop should be the inner loop

Sign In or Register to comment.