From: Bob v. L. <lo...@xs...> - 2007-07-29 18:51:33
|
Hi Marcel, > What do you mean by not accurate ? > The algorithm I'm currently using calculates the average Y, U and V pixels from a given area of the screen, from those YUV values the RGB values are calculated using the following formula: R = 1.164(Y - 16) + 1.596(V - 128)*/ G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) B = 1.164(Y - 16) + 2.018(U - 128) Or in C: R = rintf((1.164 * ((float)(ambiY[0] - 16))) + (1.596 * ((float)(ambiV[0] - 128)))); G = rintf((1.164 * ((float)(ambiY[0] - 16))) - (0.813 * ((float)(ambiV[0] - 128))) - (0.391 * ((float)(ambiU[0] - 128)))); B = rintf((1.164 * ((float)(ambiY[0] - 16))) + (2.018 * ((float)(ambiU[0] - 128)))); Next the colors are increased, this looks a lot better since the average color of a given picture is usually a combination of red, green and blue and this can look a lot like gray. average = (R + G + B / 3; R = ((10 - color) * average + R * color) / 10; G = ((10 - color) * average + G * color) / 10; B = ((10 - color) * average + B * color) / 10; Now there is only one problem left, in dark scenes the RGB values are pretty low, so the lights aren't really doing anything, to fix this the color with the highest value is multiplied so it is always 255 (with a maximum multiplication of 10) and the other two values are multiplied with the same value. float max_multiply = 10.0; int highest = 0; if(R > highest) highest = R; if(G > highest) highest = G; if(B > highest) highest = B; if (highest != 0) { float multiply = 255.0 / (float)highest; if (multiply > max_multiply) multiply = max_multiply; R = (int)((float)R * multiply); G = (int)((float)G * multiply); B = (int)((float)B * multiply); } There is only one problem with this setup, when there is a scene which is dark gray or has some white pixels and a lot of black pixels, the lights turn dark green, I think the problem is in the YUV to RGB translation and is amplified by the multiplication. > I assume you use RGB LED's for you lighting. You will need to calibrate the > system, meaning that you need to know the colour point of the primaries of > both your screen and your LED's and their white point. Than you can do a > transformation (best in XYZ colour space using a 3x3 matrix I think) and > finally back to RGB for your LED's. You will also need to involve the gamma > curves in the transformation. > I'm using 80 red leds, 60 green leds and 60 blue leds. The red leds need 2 volts and the green and blue leds need 3,8 volts. The current through the leds is 50 mA. They're hooked up to a six channel pwm controller made with a 20 mhz PIC16F84A which is connected to the serial port. > In case you have a colorimeter, you could measure the primaries and gamma. In > case you don't have, you may just get the supplier data on those primary > colours (will be less accurate) > Check http://www.brucelindbloom.com for additional math and the earlier > mentioned transformations. I don't have a colorimeter, but controlling the leds with pwm makes them pretty linear. Bob. |