This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

VLIB - Connected Components Extra Info

Hi,


I am using  VLIB in order to do a lot of image processing in a dm6446 board.

As very well noted in the VLIB API connected components extraction is one of the most needed and used algorithms.

Therefore it is supplied in the VLIB. The problem is, while extracting the blobs, i want to treat each one differently, and erase for example only those that are below a specific threshold of area, drawing the ones that passed the test.

Unfortunately, it seems to me, VLIB does not give us access to individual components besides to extract info (never to change) or even to draw 1 component at the time, based on the info we extracted.

This is really a big handicap that just freezes my progress  in the development of my vision system.

My question is, how can i get around this problem, is there anything in VLIB that i am missing?

Is the way VLIB_createConnectedComponentsList stores info that is acessed by a VLIB_CCHandle available so i can access it like VLIB_createCCMap8Bit does?

 

Best Regards

 

Filipe Alves

 

 

 

 

 

 


  •  

    Hello Filipe,

    For erasing the blobs which are below a specific area threshold, there is a parameter called minBlobArea(Minimum Pixel Area of each Blob).

    Also the VLIB function VLIB_getCCFeatures returns the ROI of each blob (min_x,max_x,min_y,max_y) through which you can access and modify the blob in the image.

    Please let me know if you need more clarification.

    Regards

    Senthil

  • Hi Senthil,

    maybe i was not very clear in my approach, and the area example was definitively not a good example, since the  VLIB_createConnectedComponentsList allows you to insert that parameter has an input.

    Anyway, what i urgently need is a way to draw an extracted blob at a time.

    example:

     

    VLIB_createConnectedComponentsList(...)

    VLIB_getNumCCs(p_cc_handle,(int *) &numCCs);

    for(i=0;i<numCCs;i++){

           VLIB_getCCFeatures(handle, &vlibBlob, i);

              if(Some blob caracteristic){

                           DRAWBLOB(VLIB_CCHandle * p_cc_handle, blob id, unsigned char * image);

              }

    }

    end of example.

     

    VLIB give us VLIB_createCCMap8Bit to draw blobs, but this will draw them all, and i just want to draw a few among all the extracted ones. When i say draw i am not referring to draw a rectangle or something else, i mean the blob the real one like you get with VLIB_createCCMap8Bit.

    It just hit me, that VLIB_createCCMap8Bit  draws each blob with a different intensity, what allows me to threshold & create mask based on the blobs ID i want. This i think can "solve" my problem. Still it is a very ugly approach not to mention time consuming. Being an 8 bit output map, we can also have problems if our image has more than 256 blobs(what will happen in this case?). So this backup approach should be only a last resort. 

    Back to the beginning, what would really be appreciated is a way to access each blob at a time in order to draw each one individually. This is, a function like the DRAWBLOB . In case this isn't available from TI, if at least we could know how is the struct pointed by VLIB_CCHandle * p_cc_handle organized i could create one myself.


    P.S. I also need to test if a point belongs to an extracted blob. Obviously i can draw that blob ( if a function like DRAWBLOB is available) and then compare, but once again, if i had acess to the struct pointed by  VLIB_CCHandle * p_cc_handle and knew how the blobs information is stored i could test it much faster.

     

    Thanks in advance

     

    Filipe Alves

     


     

     

  •  

    Filipe,

    Thanks for the detailed explanation. I understand the issue better now.

     

    If the blobs are not overlapping (wrt bounding boxes), then you can extract the bounding box using VLIB_getCCfeatures and draw the blob. This is what I was suggesting before.

    I understand that this may not work always.

     

    Do you get all the information you need from VLIB_getCCfeatures to obtain the "Some blob characteristic" used to condition and prune the blobs?

    If you can share what exactly you are computing here, I can try to figure out a solution if possible.

     

    Regards

    Senthil

  • Hi Senthil,

     

    you are correct when you say we could use the bounding boxes to use as mask and so extract our blob, if  there are no "overlapps" ,  even  in that case we could work around it and get it. Still, this is a backup approach we are wasting processor time, in things we should not be, if the info i was talking about  was available.

    During my all algorithm i use the connected components a lot of times, till now i have been able to do workarounds has the ones we have been discussing till now. I dont know if in the next steps i will be able to. I will post in here if i dont.

    Anyway, the feature i was talking about should be a good upgrade to the VLIB connected components, so maybe TI could see it has a suggestion of improvement.

     

    Other Image related items:

    Is it my impression or in the IMGLIB some of the low level kernel function supplied have an error?

    Take for example IMG_not_8
    /*----------------------------------------------------------**
    ** This function performs bitwise NOT operation on a image **
    ** Each image consist of 8 bits per sample                  **
    **----------------------------------------------------------*/
    void IMG_not_8
    (
        unsigned char * restrict imgR, /* Image read pointer */
        unsigned char * restrict imgW, /* Image write pointer */
        int count                       /* Number of samples in image */
    )
    {
        int i;
        long long p7_p6_p5_p4_p3_p2_p1_p0;
        for (i = 0; i < count >> 4; i += 16) {
            p7_p6_p5_p4_p3_p2_p1_p0 = _amem8(imgR);
            imgR += 8;
            _amem8(imgW) = ~p7_p6_p5_p4_p3_p2_p1_p0;
            imgW += 8;
            p7_p6_p5_p4_p3_p2_p1_p0 = _amem8(imgR);
            imgR += 8;
            _amem8(imgW) = ~p7_p6_p5_p4_p3_p2_p1_p0;
            imgW += 8;
        }
    }

    We are processing 16 bytes at each iteration.  the 4 right shifts are diving our image length by 16, but then it is also incrementing the i by16.

    The correct expression should be  :

    for (i = 0; i < count >> 4; i ++) {

     

    Extracted from: TMS320C64x+ DSP Image/Video Processing Library (v2.0.1) Programmer's Guide SPRUF30A

     

    Getting back to VLIB.

    In : Vision Library (VLIB) Application Programming Interface Reference Guide SPRUG00C


    The VLIB_CC struct is said to be:

    typedef struct {
         int area;
         int xsum;
         int ysum;
         int xmin;
         int ymin;
         int xmax;
         int ymax;
         int seedx;
         int seedy;
    } VLIB_CC;

     

    Still in the VLIB_prototypes.h

    typedef struct {
        int area;
          int xsum; 
          int ysum;
     
          int xmin;
          int ymin;
          int xmax;
          int ymax;  
    } VLIB_CC;

     

    The seedx, seedy are missing. I havent tested if i override this definition with the first one if i can extract the seeds. But i will need them in the future

     

    I think that is all for now.

     

    Thanks Senthil.

     

    Best Regards

     

    Filipe Alves

     

     

     

     

  • Hi again,

     

    I can now confirm that seedx & seedy from the VLIB_CC struct are not working.

    I have overrided the struct in the VLIB_prototypes.h.

    But when i run the program the DSP crashes.

    Can you confirm it?

     

    Best Regards

     

     

  •  

    Filipe,

    First let me try to clarify the IMGLIB example.

    The loop processes 16 pixels per iteration. So the loop has to run count/16 times.

    The image pointers are independent of the loop counter. So they get incremented by 16 for each iteration.

    I think you expected the image pointers to be a function of the loop counter which led to the confusion.

    The reason for this type to implementation is to exploit the auto-increment feature of the DSP.

     

    Regarding seedx and seedy, you are right. There is an issue with this feature.

    Would an updated patch release work for you?

     

    Also we definitely appreciate your feedback and suggestions for improvement of the VLIB function.

     

    Regards

    Senthil

     

  • Hi,

         concerning the updated patch release for the VLIB i think it should work. But this one is only covering the seedx, seedy right?

      Has for the IMGLIB example i think there was a misunderstand when you read my "note" on that.

    Actually we said the same thing but took different conclusions.

    Filipe Alves said:

    Take for example IMG_not_8

    /*----------------------------------------------------------**
    ** This function performs bitwise NOT operation on a image **
    ** Each image consist of 8 bits per sample                  **
    **----------------------------------------------------------*/
    void IMG_not_8
    (
        unsigned char * restrict imgR, /* Image read pointer */
        unsigned char * restrict imgW, /* Image write pointer */
        int count                       /* Number of samples in image */
    )
    {
        int i;
        long long p7_p6_p5_p4_p3_p2_p1_p0;
        for (i = 0; i < count >> 4; i += 16) {
            p7_p6_p5_p4_p3_p2_p1_p0 = _amem8(imgR);
            imgR += 8;
            _amem8(imgW) = ~p7_p6_p5_p4_p3_p2_p1_p0;
            imgW += 8;
            p7_p6_p5_p4_p3_p2_p1_p0 = _amem8(imgR);
            imgR += 8;
            _amem8(imgW) = ~p7_p6_p5_p4_p3_p2_p1_p0;
            imgW += 8;
        }
    }

    We are processing 16 bytes at each iteration.  the 4 right shifts are diving our image length by 16, but then it is also incrementing the i by 16.

    The correct expression should be  :

    for (i = 0; i < count >> 4; i ++) {

     

    Extracted from: TMS320C64x+ DSP Image/Video Processing Library (v2.0.1) Programmer's Guide SPRUF30A

    Getting back to VLIB.

    In : Vision Library (VLIB) Application Programming Interface Reference Guide SPRUG00C

     

    Take for example an image of 320x240 pixels. This give us a total length of 76800 pixels.

    Since the function processes 16 bytes (pixels) per iteration we need to run it  76800/16 = 4800 times;

    Now lets look at our for expression:

    for (i = 0; i < count >> 4; i += 16) what happens is that we are running this not 4800 times but 4800/16.

    The problem is we are doing our division of the total number of pixels by 16 twice. One  in count >> 4 and another on the i += 16 .

    So, we have to stick with only on of those expressions. That is why i said the correct expression was:


    for (i = 0; i < count >> 4; i ++) .

     

    Please correct me if i am wrong.

     

    Best Regards.

     

    Filipe Alves


     

  • Hi again,

     

    Senthil, just o had more info related to the VLIB subject i have just realized that for example  VLIB_disparity_SAD8 has 10 inputs in the VLIB_API but in the source example and in VLIB_Prototypes.h it has only 9. And i got to be honest in here, the source example provided is in my opinion very hard to understand maybe someone could shed some light in it, since it has almost no comments to help.

    And i just remembered that i had to put in comment a lot of function headers in the VLIB_Prototypes.h since they were causing errors like for example:

     

    /*int VLIB_convertUYVYint_to_HSLpl
    (
    const unsigned char *yc,      
    int width,                    
    int pitch,                    
    int height,
    const short coeff[5],         
    const unsigned short div_table[510],
    unsigned short *restrict H,   
    unsigned char  *restrict S,   
    unsigned char  *restrict L    
    );*/

     

    "./VLIB_prototypes.h", line 798: error: expected a ")"

    Am i the only one facing this kind of strange problems?

     

    Best Regards

     

  •  

    Filipe Alves,

     

    Please provide your email id. I will send you the patch release correcting the seedx issue with CCL.

     

    You are right with your reasoning on IMGLIB.

    I am sorry for not understanding you the previous time.

     

    Also, you are right about the prototype errors too.

    I dont know how these errors went through the example projects in CCS and VC++.

    The API in the test code would be the best place to refer to in case of issues as the tests are sanity checked.

     

    Regarding the VLIB_disparity_SAD8 test code, I think your difficulty is with the block-based nature of implementation.

    It can also be called directly using the image pointers leftIm8 and rightIm8.

    'left' and 'rght' are small local buffers to which data from the image is copied to.

    The code segment updates these local buffers once they are consumed fully.

            rndx += 1;

            if (rndx + WS_BY_2 >= RBLINES)
            {
            readimage_rows8(left, leftIm8 , &rl,W, W,H, BLOCK_SIZE, WINDOW_SIZE);
            readimage_rows8(rght, rghtIm8 , &rr,W, W,H, BLOCK_SIZE, WINDOW_SIZE);
            rndx = WS_BY_2 + 1;
            }

    Please let me know if you need further clarification on the stereo code.

     

    We appreciate your feedback and patience with the errors.

     

    Regards

    Senthil

     

  • Hello again,

    please send to nelson.alves@ccg.pt .

     

    Thanks for your clarification in the stereo code. i had an idea of  the buffers you created, still it was a little confusing to understand the code. and for example the BLOCK_SIZE any constraint on that? why 8?  You are creating the buffers expecting they will decrease cache misses or something?

    I am having a hard time with VLIB by now, i am debugging it in my embedded dm6446 board, and it is  painful to debug in this conditions.

    I keep having strange errors, that i cant figure if it is my problem or VLIB.

    Getting back the Connected Components look at this strange behaviour.

    //Original Image

     

    // Background Subtraction

    //Connected Components

     

    Has you can see it only detects 1 component, i used the xmin, xmax, ymin, ymax to draw the bounding box. Still sometimes like this one i captured,  other small blobs (smaller than the MIN_AREA wich is defined has 100) appear in between the ymin and ymax of the blob. This extra pixels are actually the ones that are in the foreground mask but that should not appear in the CC.

    Besides this strange behaviour i am using theVLIB_createConnectedComponentsList  a lot of times, has i told in the past posts i had to change some algorithms of my own and i am not receiving the expected output. So i have some question i would like you to clear for me if it is possible, please.

    0- Can i used VLIB_createConnectedComponentsList multiple consecutive times in the same process call of the codec, only initializing it in the activate phase of the codec?

    0.1 - Can i  put a different min_area input parameter than the one i used to calculate the bytes required for VLIB_initConnectedComponentsList has long has this new value is bigger than the one used ofr theinit?

     

    I have now doubts about everything.

     

    So to be clear i am using Codec Engine with IUniversal to communicate between Arm and DSP. 

    In the Arm side i am declaring my Buffers has this :

     

    encBuf      = (unsigned char * )Memory_contigAlloc( encBufSize, 8 ); 1- The 8 in here is 8 bytes right? should this be another value? 128 Bytes the cache line?

     

    I am not doing any cache Invs or WB. 2-  the Codec Engine Iuniversal skeletons and Stubs are doing this for me right?

     

    Now, on the DSP side i declare the buffers throw memTab in the alloc phase:

     

    I am doing like this for the normal Buffers

     memTab[IMG_BUF].size        = (frame_size) * sizeof(XDAS_UInt8);
      memTab[IMG_BUF].alignment   = 8;
        memTab[IMG_BUF].space       = IALG_EXTERNAL;
        memTab[IMG_BUF].attrs       = IALG_PERSIST;

    3 - Once again note the 8 is it the correct value to be double word, i cant seem to find any information explamimg if that value is in bits or Bytes or whatever.

    For the packed Buffers i use

        memTab[BUF32].size        = (frame_size>>5) * sizeof(XDAS_UInt32);
        memTab[BUF32].alignment   = 8;
        memTab[BUF32].space       = IALG_EXTERNAL;
        memTab[BUF32].attrs       = IALG_PERSIST;

     

    For CC

           
        VLIB_calcConnectedComponentsMaxBufferSize(width,height,MINBLOBAREA,(int *)&maxBytesRequired);
       
        memTab[CC_LIST].size        = maxBytesRequired;
        memTab[CC_LIST].alignment   = 8;
        memTab[CC_LIST].space       = IALG_EXTERNAL;
        memTab[CC_LIST].attrs       = IALG_PERSIST;

       
       sizeOfCCHandle =  VLIB_GetSizeOfCCHandle();  
       
        memTab[CC_HANDLE].size        = sizeOfCCHandle;
        memTab[CC_HANDLE].alignment   = 8;
        memTab[CC_HANDLE].space       = IALG_EXTERNAL;
        memTab[CC_HANDLE].attrs       = IALG_PERSIST;

    Next Step in the Activate phase of the codec:

       VLIB_initConnectedComponentsList(p_cc_handle, p_cc_list,(int) maxBytesRequired);   

     

    The implementation to get that output images is has follow:

     

    memcpy(p_img_Buf,p_img_src,frame_size);

        // Do Background Subtraction
        VLIB_subtractBackgroundS16(   p_img_fg_pack,        // new foreground mask to be computed
                                                            p_img_Buf,         // the newest luma frame
                                                            p_img_background,     // running mean
                                                            p_img_bg_var,         // running variance
                                                            thresholdGlobal,    // global threshold
                                                            thresholdFactor,     // multiplicative factor for the image threshold
                                                            frame_size);        // no. of pixels to be processed
     
     
        // Update Background Mean
        VLIB_updateEWRMeanS16(        p_img_background,    // running mean
                                                              p_img_Buf,         // newest luma frame
                                                             p_img_fg_pack,         // current foreground mask
                                                             bgAdaptRate,        // old-new mixing ratio
                                                             frame_size);            // no. of pixels to be processed


        // Update Background Variance 
        VLIB_updateEWRVarianceS16(    p_img_bg_var,        // running variance
                                                              p_img_background,     // running mean
                                                              p_img_Buf,         // newest luma frame
                                                             p_img_fg_pack ,     // current foreground mask
                                                              bgAdaptRate,        // old-new mixing ratio
                                                             frame_size);               



        // Unpack from 1-pixel per bit to 1 pixel per byte
          VLIB_unpackMask32(         p_img_fg_pack,        //foreground packed mask
                                                     p_img_Buf,        //foreground mask unpacked
                                                     frame_size);        //no. of pixels to be processed

         IMG_thr_gt2max_8 (p_img_Buf, p_img_dst, frame_width, frame_height, 0);

    p_img_dst is the background_Subtraction image

     

    VLIB_createConnectedComponentsList(    p_cc_handle,
                                                                      (unsigned short)frame_width,
                                                                     ( unsigned short)frame_height,
                                                                    (p_img_fg_pack),
                                                                     MINBLOBAREA,
                                                                      1);
       
            memset(p_img_Buf, 0, frame_size);
       
            VLIB_createCCMap8Bit(            p_cc_handle,
                                                               p_img_Buf,
                                                             (unsigned short)frame_width,
                                                             (unsigned short)frame_height);


           IMG_thr_gt2max_8 (p_img_Buf, p_img_dst2, frame_width, frame_height, 0);

     

           VLIB_getNumCCs(p_cc_handle,(int *) &numCCs);
           outArgs->numCCs=numCCs;

       
        for(i=0;i<numCCs;i++){
            VLIB_getCCFeatures(p_cc_handle, &vlibBlob, i);
                         
                        DrawRectangle(    p_img_dst2,
                                                frame_width,
                                               frame_height,
                                              vlibBlob.xmin,
                                               vlibBlob.ymin,
                                                  vlibBlob.xmax-vlibBlob.xmin,
                                                  vlibBlob.ymax-vlibBlob.ymin,
                                                2,
                                               125);
        }

    p_img_dst2 is the CC image shown

     

    To finish:

    4 - Is the correct way to tell the Codec Engine how i acessed the Buffers

        // report how we accessed the input buffer
        inBufs->descs[0].accessMask = 0;
        XDM_SETACCESSMODE_READ(inBufs->descs[0].accessMask);
       
        inBufs->descs[1].accessMask = 0;
        XDM_SETACCESSMODE_READ(inBufs->descs[0].accessMask);

        inBufs->descs[2].accessMask = 0;
        XDM_SETACCESSMODE_READ(inBufs->descs[2].accessMask);

        inBufs->descs[3].accessMask = 0;
        XDM_SETACCESSMODE_READ(inBufs->descs[3].accessMask);


        // report how we accessed the output buffer
        outBufs->descs[0].accessMask = 0;
        XDM_SETACCESSMODE_WRITE(outBufs->descs[0].accessMask);

        outBufs->descs[1].accessMask = 0;
        XDM_SETACCESSMODE_WRITE(outBufs->descs[1].accessMask);
     
        outBufs->descs[2].accessMask = 0;
        XDM_SETACCESSMODE_WRITE(outBufs->descs[2].accessMask);

        outBufs->descs[3].accessMask = 0;
        XDM_SETACCESSMODE_WRITE(outBufs->descs[3].accessMask);

    5- Is Anything wrong with the above code?

    -------------------------------------------------------------------------------------------------

    In other parts of my program i seem to observe that it has to run 1 time and only then the output is correct other times some strange artifacts appear in my images. That is why i am a little lost debugging the issue.

     

    Thanks for your time Senthil if you could i would appreciate chatting with you to maybe clarify and help me and you resolving this issue faster.

     

    P.S. I know this is a very, very, very long post, and that TI employees have no obligation or similar to debug others code. I just asked it, cause i am getting desperate on it, my deadline to finish the product is ending and i cant seem to find the source of the problem.I dont know if it is mine or TI.

     

    Best Regards

     

    Filipe Alves


     

     

     


     

     

  •  Hi Filipe,

    I'm working on something very similar, I have to identify and count certain shapes (blobs) found in a video stream.
    I'm stuck however in a previous stage it seems you already passed.

    How did you perform the background subtraction ??

    Your code states:

        // Do Background Subtraction
        VLIB_subtractBackgroundS16(   p_img_fg_pack,        // new foreground mask to be computed
                                                            p_img_Buf,         // the newest luma frame
                                                            p_img_background,     // running mean
                                                            p_img_bg_var,         // running variance
                                                            thresholdGlobal,    // global threshold
                                                            thresholdFactor,     // multiplicative factor for the image threshold
                                                            frame_size);        // no. of pixels to be processed 
         // Update Background Mean
        VLIB_updateEWRMeanS16(        p_img_background,    // running mean
                                                              p_img_Buf,         // newest luma frame
                                                             p_img_fg_pack,         // current foreground mask
                                                             bgAdaptRate,        // old-new mixing ratio
                                                             frame_size);            // no. of pixels to be processed 
        // Update Background Variance 
        VLIB_updateEWRVarianceS16(    p_img_bg_var,        // running variance
                                                              p_img_background,     // running mean
                                                              p_img_Buf,         // newest luma frame
                                                             p_img_fg_pack ,     // current foreground mask
                                                              bgAdaptRate,        // old-new mixing ratio
                                                             frame_size);               

    To do the background sustraction it is needed the running mean and variance ( of the background model) and the newest luma frame. However, to update the mean you need the current foreground mask, but this is given by the VLIB_SubtractBackgroundS16() function,  so what do you use as the foreground mask ??

    same case, to update the background variance, it is needed the foreground mask... which is given by the  VLIB_SubtractBackgroundS16() function too,
    I'm confused into what to do first and what second ??

    What is the 1st step when having a new image and the background model ?   my guess is that it would be to obtain the Mean of the background model, and the variance, but to get the variance a foreground mask is needed, which it is inexistant at first.   

    How did you obtain the mean and the variance when having only the background model and the new luma frame ?? What is the order of the functions ?

    I'd really appreciate some help by anyone!

    Thank you,

     

  • Hi Rafael,

    When you are trying to find out the foreground in the current image, you will use the mean and the variance you calculated from the previous inputs.

    Once you have your current foreground mask, you can update your background mean and variance images. The foreground mask has inputs is telling the system not to update in those zones, or otherwise you would end up with a wrong background mean and variance.

    This is all to say that the above code has it is, is correct. What you are missing here is the first time you run it. At the first time you dont have a background mean nor variance, so you have to create it. There are a lot of ways to do that, VLIB gives you two functions:

     

            // initialize the running mean "image"
            VLIB_initMeanWithLumaS16(p_img_background, p_img_src1, frame_size);
     
            // initialize the running variance "image"
            VLIB_initVarWithConstS16(p_img_bg_var, thresholdGlobal, frame_size);

    You can check the examples that come with the VLIB to check this one out.

    Hope i was clear.

     

    Best Regards

     

    Filipe Alves

  • Hi Filipe,

    yes it was very clear, thank you.
    The problem I'm having is that I'm obtaining a foreground mask that tells me that almost all in the image is foreground.. ( no foreground object detection ).

    I'm doing exactly as suggested, ( initializing mean and variance the very first time as well); however the Foreground mask I obtain each time the background sustraction is done is mostly 0xFF's indicating pretty much the whole image is foreground. The only time that the Foreground mask is written with 0x00's  is right after performing the very first background sustraction,that is when I have the initialized background mean and the initialized background variance, from that point on every Foreground mask is written mostly with 0xFF's.

    For example,  I set the background as a scenary  (an empty corner of my office cubicule), and the let the camera run ( with these algorithms), then every new image is the same as the background, since no new objects appear in the scenary because the camera is always pointing to the same spot and nothing changes..
    under these conditions I expect that the whole time the foreground Mask is 0x00's completely... since the new incoming image is the same as the background model, and no foreground object exists...   However, the foreground mask I get indicates me that almost the whole image is a foreground object ( lots of 0xFF's everywhere).

    did you have the same problem when subtracting new images from the background model ?

    Regards!!

     

  • Lets just try to debug a few issues to see if we can find the problem.

     

    First, have you allocated the correct type of buffers?

       the foreground mask (p_img_fg_pack)                  - type : XDAS_UInt32      size: frame_size/32*sizeof(XDAS_UINT32)

       the newst luma frame (p_img_Buf)                       - type unsigned char        size: frame_size

       the background mean ( p_img_background)         - type : short                   size: frame_size*sizeof(short)

       the background variance (p_img_bg_var )             - type : short                    size: frame_size*sizeof(short)

       #define THRESHOLD_FACTOR_S16  0x31ff        // SQ4.11

        #define CAMERA_NOISE_S16      0x0A00         // SQ12.3

        short thresholdFactor     =     THRESHOLD_FACTOR_S16/2;            //Max Diff between input and background
        short thresholdGlobal     =     CAMERA_NOISE_S16/32;            //Associated with upper Definition

     

    After you confirm this, next step is, confirm you have this code after detecting the foreground:

     VLIB_unpackMask32(          p_Buf32,        //foreground packed mask
                                                  p_img_Buf,        //foreground mask unpacked
                                                  frame_size);        //no. of pixels to be processed


      IMG_thr_gt2max_8 (p_img_Buf, p_img_dst1, frame_width, frame_height, 0);

    If you dont want to use IMG_thr_gt2max_8 , just for debug you can do the following code

    for(i=0;i<frame_size;i++)

               if(p_img_Buf[i]>0)

                           p_img_Buf[i]=255;

     

    If you have all this and you still have problems, then maybe your background image is not correct.

    If you acquire the background image at the very start of your program with

      // initialize the running mean "image"
            VLIB_initMeanWithLumaS16(p_img_background, p_img_src1, frame_size);
     
            // initialize the running variance "image"
            VLIB_initVarWithConstS16(p_img_bg_var, thresholdGlobal, frame_size);

     

    then maybe your camera did not had the chance to stabilize the captured images, usually the first frames you capture from a camera should be discarded specially if it has auto-white balance. So what you can try is acquire lets say 10-30 frames and only then grab the background.

    Other test you can do is, at the end of every foreground detection you initialize your background with the newest luma you captured. So, in the next processing phase you will have your background that will be your last image compared to your new image, this is called frame-differencing if you move something in front of the camera you will see the zones where movement occurred.

     

    I hope it helps, it has to be something related to this.

     

    Best Regards

     

    Filipe Alves

     

     

     

     

     

  • Hi Filipe,

    FIXED!!   YES!! you were right, the problem was that I was taking the very 1st frame as my background and the camera wasn't stabilizing (plus, it has Auto While-balance), taking a bad background model reference to start. Taking the background model After 10 or 20 frames fixed the problem!!!

    The frame-differencing test was succesful.

    Now the problem I have is illumination, it seems that the subtraction is very sensitive to illumination.. problems I'm having are:

    •  If auto white-balance adjusts.. the scene illumination changes, and some foreground object reflects are detected as foreground objects
    •  If the illumination changes drastically, let's say an object is close to the camera and some dark areas are enlightened, and some bright areas get dark because of the white-balance, the whole scene is messed up and a huge foreground mask is detected. This goes away as soon as I take the foreground object and illumination goes back to normal, but sometimes some "fake foreground objects" caused by this, remain in mask.
    • Even if I took the auto white-balance out, this would cause not to drastically change video illumination, however external illumination would, e.g. a vehicle going on the road and entering under a bridge for example. (my application is for outdoors)

    I've played with the CAMERA_NOISE_S16 , IIR_ALPHA_S16 and THRESHOLD_FACTOR_S16 constants, according of course  to the specific notation of each (SQ0.15, SQ4.11 and SQ12.3)  but still haven't found a combination that is fairly inmune to illumination changes and also conserving a good foreground object detection. The default numbers seem to be very criptic ( I know what they mean, but I don't know what number represents a high or small value as reference).

    Did you use the default constant values for your application (works for you) ?
    is your application indoor ?
    does your camera has auto white-balance activated when you do the tests ?

    Thank you for all your previous hints, it has helped me a lot !

    Best regards,

  • Dear Senthil,

    I am also using the VLIB connected components feature and I am now in the need of the seedx and seedy.

    Should I wait until the next release or could I have a patch for this functionality?

    Thanks in advance,

    Regards

    Jon

  • can you tell me initial variance value?