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.

sobel edge detector problem on dm6467

Hello, everyone,

I am now do some image processing  based dm6467.

I want to do the sobel edge detection over the captured buffer from capture.c, but after the processing, I only got the black image.

the buffer format is YUV422Psemi, first I grayed the image ( set the U,V componet to 0x80 ), then I do the sobel detection over the Y component, but only got a black image.

 

My sobel source codes are as follows:

the size of GrayArray is 720 x 480 x 2 ( YUV422Psemi ).

unsigned char *Sobel( unsigned char *GrayArray, unsigned char *SobelArray )

{
    int width = 720;
    int height = 480;
    int i;
    int j;
    int k;


    int RowMove = width;
    int SobelResult;

    int lSobelResult;

    int VerticalPlate[9]={2,1,0,-1,-2,-1,0,1,0};
    int neighbourx[9]={1,1,0,-1,-1,-1,0,1,0};
    int neighboury[9]={0,-1,-1,-1,0,1,1,1,0};

    static unsigned char *copy_inbuffer = NULL;

    int n;
   

copy_inbuffer = (unsigned char*) Memory_contigAlloc( width * height, Memory_DEFAULTALIGNMENT);

    for ( n = 0; n < width * height; n++ )
    {
        *copy_inbuffer = *GrayArray;
        GrayArray++;
        copy_inbuffer++;
    }

    for ( i = 1; i < height -2; i++ )
    {
        for ( j = 1; j < width -2; j++ )
        {
            SobelResult=0;
            for ( k=0;k<9;k++ )
            {
                SobelResult=SobelResult+ copy_inbuffer[RowMove+neighboury[k]*width+j+neighbourx[k]]*VerticalPlate[k];
            }
            lSobelResult=(int)(SobelResult);

            GT_1trace(curTrace, GT_ENTER, "TTTTTTTTTTTTTTTTTTTTTTTTTTT(0x%d)\n",SobelResult );
            if(lSobelResult>255)
            {
                lSobelResult=255;
            }

            if(lSobelResult<0)
            {
                lSobelResult=0;
            }

            SobelArray[RowMove+j]= lSobelResult;
        }
        RowMove+=width;
    }
    return SobelArray;
}

 

could anyone help me?

thank you!

zhiqiang

  • Hi,

    I am not sure what you are asking us to do here. If you can see the video on display without going through the sobel detection, then the problem you are seeing should be with your implemention of the algorithm. Here is a sample implementation

    http://www.pages.drexel.edu/~weg22/edge.html

    Maybe you should simulate your algorithm using matlab.

  • Hi, Paul. Yin,

    I am sure that the algorithm is correct because I have verified it on PC using Borland C++ builder.

    I can only see a complete black image on display.

    I want to know why this happened?    

    If the reason is the architecture difference between PC and DSP?

    thank you.

    Zhiqiang

     

  • I see. Just to be sure you initialized the VPIF correctly.  you were able to see the original image on the display right?

  • Hi, Paul,

    Thank you for your message.

    I am sure that I can see the original image on the display right.

    I can also see the gray level image too.

    But I still can't see the result of sobel operation.

    thank you.

    Zhiqiang

  • The only thing I can think of is to check whether your implementation is for fixed point processors or for floating point processors.  Look for overflow or loss of precision.

  • Hi, Paul,

           "the buffer format is YUV422Psemi, first I grayed the image ( set the U,V componet to 0x80 ), then I do the sobel detection over the Y component"

            I regard the Y component as gray level image, then do the sobel detection over the Y component, am I right?

            If the right way is convert yuv to rgb, then gray the image , and convert back to yuv?

            thank you.

    Zhiqiang 

  • Hi,

    I believe treating Y component as gray image is correct.

    Unfortunately, we will not be able to debug your implementation. However, you might benefit from reading this doc (Our IMGLIB Sobel implemenation)  http://www.ti.com/litv/pdf/spruf30a

     

  • Hi, Paul,

    I have solved the problem.

    The problem is that I use

                                 "copy_inbuffer = (unsigned char*) Memory_contigAlloc( width * height, Memory_DEFAULTALIGNMENT);"

    to allocate memory, which is not correct, and return a NULL pointer. Instead, I should use

                                 "copy_inbuffer = (unsigned char*) malloc( width * height );"

    However,  another question appears, on the arm side, the memory should be allocated using "Memory_contigAlloc" but not "malloc", because it can guarantee that the buffer address  is contiguous, but "malloc" can not.

    why "Memory_contigAlloc" fails on the DSP side?

    why "malloc" is right on the DSP side?

    thank you.

    Zhiqiang

  • Hi, I am looking for an answer to your question. Just to clarify, by

    "why "Memory_contigAlloc" fails on the DSP side?

    why "malloc" is right on the DSP side?"

    You meant on ARM, not DSP, right? I am slightly confused here because I was under the impression that you implemented your algortihm on the ARM side.

  • Here is what I've learnt from our expert:

    On the ARM side you can’t guarantee that malloc is contiguous and will give you a virtual address, not a physical one. The Memory_contigAlloc function that you are calling is a CMEM function I believe which allocates from a memory region not controlled by the ARM and where you can get the actual physical address of the memory region.  As for why this fails on the DSP side the possible explanations are:

     

    1. The DSP doesn’t have CMEM APIs
    2. The DSP doesn’t run through the MMU, etc.  It’s malloc is contiguous and physical.

  • Not quite.  Memory_contigAlloc() is an API intended to isolate callers from the underlying OS.  It's part of the 'ti.sdo.ce.osal' package - where 'osal' means "Operating System Abstraction Layer".

    In all cases, the pointer returned is accessible by the caller.  On BIOS, it'll likely be a physical address since most of the BIOS-based systems don't have an MMU (or have it configured with a phys==virt address mapping).  On Linux/WinCE user mode, it'll be a virtual address of a buffer mapped into your application's address space.

    On Linux and WinCE, Memory_contigAlloc() is implemented with CMEM.  On BIOS, it's implemented with standard BIOS MEM_alloc() APIs.  The implementations are shipped with the product (assuming your using a release made after Aug 2008).  You can see the latest BIOS implementation here - http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/ce/latest_2_x/packages/ti/sdo/ce/osal/bios/Memory_BIOS.c

    If it's failing on a BIOS system, you may be running out of heap (typically configured in a .tcf script) - or possibly the heap is fragmented(?).  We probably should move this thread to the Embedded Software forum (probably the BIOS one, since that's where this error is?) as that's where most of the SW folks hang out.

    Chris

  • Hi, Paul and Chris,

        Now I understand it completely.

        thank you.

    Zhiqiang