decoding yuv-->rgb in motion_detector.c is likely wrong - General Discussion and Assistance - CHDK Forum

decoding yuv-->rgb in motion_detector.c is likely wrong

  • 6 Replies
  • 5615 Views
decoding yuv-->rgb in motion_detector.c is likely wrong
« on: 02 / February / 2011, 08:50:11 »
Advertisements

Decoding yuv-->rgb in motion_detector.c is likely wrong. ( at least on my sx210 )

I've tried to find out correct decoding coefficients, but it did not ended as
good as I thought.
The archive contains all sample images and results and couple of ruby scripts,
that are computing new coefficients from sample images.

http://www.uloz.to/7673619/frame-buffer-yuv-quest-tbz

I'm out of ideas, on this one. I'd be very pleased, for someone else to crack it...

v.

*

Offline reyalp

  • ******
  • 14126
Re: decoding yuv-->rgb in motion_detector.c is likely wrong
« Reply #1 on: 08 / February / 2011, 13:48:24 »
By wrong, do you mean the colors are a bit off, or completely wrong ? I found the output of yuvconvert  (which was based on chdk live view code) to be reasonable considering there is no real calibration.
Don't forget what the H stands for.

*

Offline ewavr

  • ****
  • 1057
  • A710IS
Re: decoding yuv-->rgb in motion_detector.c is likely wrong
« Reply #2 on: 08 / February / 2011, 14:58:41 »
BTW, in motion_detector.c we have 'switch' statement without 'case' (lines 481-482 etc.).  :o

*

Offline Lebeau

  • ***
  • 187
Re: decoding yuv-->rgb in motion_detector.c is likely wrong
« Reply #3 on: 08 / February / 2011, 15:19:53 »
Bonjour v3as4k,

here is the formulas I used in motion detection. In fact, only 5742 replace 5743 in the original code and I commented where these values are comming from.

Code: [Select]
switch( motion_detector->pixel_measure_mode )
 {
 case MD_MEASURE_MODE_U: val = cb; break;
 case MD_MEASURE_MODE_V: val = cr; break;
 yc = val << 12;
 cb = ( cb > 127 ? cb - 256 : cb ); // Cb value
 cr = ( cr > 127 ? cr - 256 : cr ); // Cr value
 case MD_MEASURE_MODE_R: val = clip ( ( yc + ( 5742 * cr ) + 2048 ) >> 12 ); break;
 case MD_MEASURE_MODE_G: val = clip ( ( yc - ( 1410 * cb + 2925 * cr ) + 2048 ) >> 12 ); break;
 case MD_MEASURE_MODE_B: val = clip ( ( yc + ( 7258 * cb ) + 2048 ) >> 12 ); break;
 default : val = yc; break;
 }
; // end of switch
/*
Lebeau : also http://en.wikipedia.org/wiki/YCbCr
upon TIFF-EP specs
R = Cr * ( 2 - 2 * LumaRed ) + Y = Y + 2 * Cr * ( 1 - LumaRed )
G = ( Y - LumaBlue * B - LumaRed * R ) / LumaGreen = ( Y - ( B*LumaBlue + R*LumaRed ) ) / LumaGreen
B = Cb * ( 2 - 2 * LumaBlue ) + Y = Y + 2 * Cb * ( 1 - LumaBlue )

The values coded by this field will typically reflect the transformation specified by a standard for YCbCr encoding.

The following table contains examples of commonly used values.
Standard LumaRed LumaGreen LumaBlue
CCIR Recommendation 601-1 299 / 1000 587 / 1000 114 / 1000
CCIR Recommendation 709 2125 / 10000 7154 / 10000 721 / 10000

Motion Detection 601-1 based 1225 / 4096 2404 / 4096 467 / 4096

#define LUMA_RED 1225
#define LUMA_RED_COEF1 5742 // 2 * ( 1 - luma_red )
#define LUMA_RED_COEF2 2925 // 2 * ( luma_red - luma_red2 ) / luma_green
#define LUMA_GREEN 2404
#define LUMA_BLUE 467
#define LUMA_BLUE_COEF1 7258 // 2 * ( 1 - luma_blue )
#define LUMA_BLUE_COEF2 1410 // 2 * ( luma_blue - luma_blue2 ) / luma_green
#define HALF_SCALE 2048 // 4096 / 2
*/

When you are detecting motion in R, G or B from the viewport, these values are well computed but your point is probably regarding the volatily of the accuracy of the viewport.

The viewport has the property, within the limit of my knowledge, to automaticaly adjust the luminance and the white balance (on my A650, I am sure) and therefore could impair the precision of some chromas since the viewport could adjust his display upon the object in motion and consequently indicates motion all over the targetted area. Humm.

In my motion detection code, I submitted to CHDK (http://chdk.setepontos.com/index.php?topic=650.msg61021#msg61021), I integrated "wait-stability" (parameters = 16) which wait for some viewport stability (after msecs before trigger expired) to be sure viewport will be stable before starting to check for motion.

P.S.: Tabarouette ewavr, you're right. How a compiler miss that ? I will fix it in my sbmitted code !!!
« Last Edit: 11 / February / 2011, 15:54:18 by Lebeau »

*

Offline Lebeau

  • ***
  • 187
Re: decoding yuv-->rgb in motion_detector.c is likely wrong
« Reply #4 on: 10 / February / 2011, 16:59:18 »
Bonjour v3as4k,
It seams that you are right.
I get a look to YPbPr to RGB conversion and found we have to reset relative scale and value before proceding to conversion.
( YCbCr = (16,128,128)+(219,224,224) * YPbPr )
I add add these change to my code.
Thanks

*

Offline Lebeau

  • ***
  • 187
Re: decoding yuv-->rgb in motion_detector.c is likely wrong
« Reply #5 on: 11 / February / 2011, 15:53:02 »
Forget the last post ! I have the solution and solve the mistery

Here is the transformation that should take place within the switch:
Code: [Select]
case MD_MEASURE_MODE_U: val = cb; break;
case MD_MEASURE_MODE_V: val = cr; break;
yc = val << 12;
cb = ( cb > 127 ? cb - 256 : cb ); // Cb value
cr = ( cr > 127 ? cr - 256 : cr ); // Cr value
case MD_MEASURE_MODE_R: val = clip ( ( yc + ( 5742 * cr ) + 2048 ) >> 12 ); break;
case MD_MEASURE_MODE_G: val = clip ( ( yc - ( 1410 * cb + 2925 * cr ) + 2048 ) >> 12 ); break;
case MD_MEASURE_MODE_B: val = clip ( ( yc + ( 7258 * cb ) + 2048 ) >> 12 ); break;
default : val = yc; break;

End of story!

The bug was with Cb and Cr where both shall be substracted to have the -128 to + 127 range. If someone find a better way to do so, he is welcome !

*

Offline Lebeau

  • ***
  • 187
Re: decoding yuv-->rgb in motion_detector.c is likely wrong
« Reply #6 on: 03 / May / 2011, 12:23:28 »
( signed char ) !!! Yes, ( signed char ) is the solution !

Code: [Select]
val = img [ triplets_in_bytes + 1 ]; // xYx xxx or xxx xYx
// lebeau : is not in Y measurement ?
if ( motion_detector->pixel_measure_mode != MD_MEASURE_MODE_Y )
{
// is first or second triplets ?
if ( ( x % 2 ) == 0 ) // is xYx xxx (which triplets ?)
{
cb = ( signed char ) img [ triplets_in_bytes ]; // Uxx xxx
cr = ( signed char ) img [ triplets_in_bytes + 2 ]; // xxV xxx
}
else // or xxx xYx
{
cb = ( signed char ) img [ triplets_in_bytes - 3 ]; // Uxx xxx
cr = ( signed char ) img [ triplets_in_bytes - 1 ]; // xxV xxx
}
;
// compute Cb, Cr, R, G or B upon user measure mode
switch( motion_detector->pixel_measure_mode )
{
case MD_MEASURE_MODE_U: val = cb; break;
case MD_MEASURE_MODE_V: val = cr; break;
yc = val << 12;
case MD_MEASURE_MODE_R: val = clip ( ( yc + ( 5742 * cr ) + 2048 ) >> 12 ); break;
case MD_MEASURE_MODE_G: val = clip ( ( yc - ( 1410 * cb + 2925 * cr ) + 2048 ) >> 12 ); break;
case MD_MEASURE_MODE_B: val = clip ( ( yc + ( 7258 * cb ) + 2048 ) >> 12 ); break;
default : val = yc; break;
}
; // end of switch
}
; // end of not Y mode
// in or out effective area, compute cumulative pixel values and count pixels

motion_detector->curr [ idx ] += val;
motion_detector->points [ idx ]++ ;

Excuse my poor C programming knowledge  ;)

 

Related Topics


SimplePortal © 2008-2014, SimplePortal