Converting to normalised RGB

edited February 2014 in How To...

How can I convert the video captured by the webcam to normalised RGB? Thanks

Tagged:

Answers

  • Define "normalized RGB".

    Once you do it, I guess half the program is done...

  • how do i go through each and every pixel in the video and convert it to normalized RGB by applying the formula: r = R/(R+G+B) g = G/(R+G+B) b = B/(R+G+B)

  • AFAIK, video images are available as regular images. You can call loadPixels() on them, then iterate on the pixels[] array.

  • edited February 2014

    Is this correct?

    for (int i = 0; i < video.width;i++) 
      {
        for (int j = 0; j < video.height;j++) 
        {
          int loc = i + j*width;
    
          int pixelColour = video.pixels[loc];
          float r = (pixelColour >> 16) & 0xff;
          float g = (pixelColour >> 8) & 0xff;
          float b = pixelColour & 0xff;
          r = (r/(r+g+b))*255;
          g = (g/(r+g+b))*255;
          b = (b/(r+g+b))*255;
          video.pixels[loc] =  color(r,g,b); 
        }
      }
    
  • edited February 2014

    Looks OK. Does it do the result you are expecting?

    EDIT: should be int loc = i + j * video.width;

  • no I don't think so because there is so much blue color in the video.

  • And black objects like hair turns out red

  • This code is flawed, because it recalculates r+g+b (which is a waste of resources), but more importantly does so each time with different values, because r and g are set in the meantime. To solve this problem AND save resources, you should calculate the cumulative of r + g + b ONCE and re-use that in all three normalization calculations.

  • Thanks, but is this what you meant?

      for (int i = 0; i < video.width;i++) 
      {
        for (int j = 0; j < video.height;j++) 
        {
          int loc = i + j*video.width;
    
          int pixelColour = video.pixels[loc];
          float r = (pixelColour >> 16) & 0xff;
          float g = (pixelColour >> 8) & 0xff;
          float b = pixelColour & 0xff;
    
          rgbTotal = r+g+b;
        }
      }
    
      for (int i = 0; i < video.width;i++) 
      {
        for (int j = 0; j < video.height;j++) 
        {
          int loc = i + j*video.width;
    
          int pixelColour = video.pixels[loc];
          float r = (pixelColour >> 16) & 0xff;
          float g = (pixelColour >> 8) & 0xff;
          float b = pixelColour & 0xff;
    
          // Normalised RGB
          r = (r/rgbTotal)*255;
          g = (g/rgbTotal)*255;
          b = (b/rgbTotal)*255;
          video.pixels[loc] =  color(r,g,b); 
    
  • According to the http://www.aishack.in/2010/01/normalized-rgb/ article, the first method is OK, ie. it must divide each channel by the sum of the channels for this given pixel.
    The "strange" colors are a consequence of this algorithm.

    There is a point left in the dark by the algorithm: what if r+g+b is zero?

  • first method is not OK as amnon points out - he's using r+g+b whilst changing r, g and b.

    in the second method he's calculating r+g+b for each pixel and then ignoring the result

    you need to copy line 12 to line 26 (define it as a float) and then delete lines 1-15.

    and, yes, there's a divide-by-zero bug in there...

  • edited March 2014

    Ah, oh, yes, I missed this point, and was confused by the second "solution", which probably results in all value at zero.

    To be explicit:

    for (int i = 0; i < video.width; i++)
    {
        for (int j = 0; j < video.height; j++)
        {
          int loc = i + j * video.width;
    
          int pixelColour = video.pixels[loc];
          float r = (pixelColour >> 16) & 0xff;
          float g = (pixelColour >> 8) & 0xff;
          float b = pixelColour & 0xff;
          float t = r + g + b;
          if (t == 0) continue; // Skip this one
          r = 255 * r / t;
          g = 255 * g / t;
          b = 255 * b / t;
          video.pixels[loc] =  color(r,g,b);
        }
    }
    
  • Thanks! This is what I have changed. How do I remove the divide-by-zero bug?

    for (int i = 0; i < video.width;i++) 
      {
        for (int j = 0; j < video.height;j++) 
        {
          int loc = i + j*video.width;
    
          int pixelColour = video.pixels[loc];
          float r = (pixelColour >> 16) & 0xff;
          float g = (pixelColour >> 8) & 0xff;
          float b = pixelColour & 0xff;
    
          float rgbTotal = r+g+b;
    
          // Normalised RGB
          r = (r/(rgbTotal))*255;
          g = (g/(rgbTotal))*255;
          b = (b/(rgbTotal  ))*255;
          video.pixels[loc] =  color(r,g,b); 
    
  • you could add a tiny number to each of r, g, b to ensure they aren't 0 (but not enough to skew the results). something like

      float r = .00001 + (pixelColour >> 16) & 0xff;
      float g = .00001 + (pixelColour >> 8) & 0xff;
      float b = .00001 + pixelColour & 0xff;
    
  • Thanks PhiLho, I have tried yours out, but there is no difference in the results. Black areas like hair is still distorted (weird bright red colour).

    Thanks Koogs, it doesn't allow me to add a float to an int.

  • doesn't allow me to add a float to an int.

    this would've been a problem with your original lines 8-10 too

    i think this'll work, but can't test it here

    float r = .00001 + float((pixelColour >> 16) & 0xff);

  • Thanks! But there is no difference in the result.

Sign In or Register to comment.