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

  • 6 Replies
  • 1642 Views
  • Publish
    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.

    *

    Online reyalp

    • ******
    • 9803
  • Publish
    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
  • Publish
    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
  • Publish
    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
  • Publish
    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
  • Publish
    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
  • Publish
    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