Canny example?

Canny example?

Hi all,

I am using the IPP 5.0 for linux on a 32-bit running Suse 10.1.
In the past I have used the IPP 4.1 with the following code:

#include "ippi.h"
#include "ippcv.h"

unsigned char img[1024*768*1];
unsigned char output[1024*768*1];
const int low_thr = 50;
const int high_thr = 140;
IppiSize size; size.width = 1024; size.height = 768;

Ipp16s imageSobel_1[1024*768*10];
Ipp16s *imageSobel_2 = &imageSobel_1[1024*768];
Ipp16s *imageSobel_3 = &imageSobel_1[1024*768*2];
ippiSobel3x3_Dx_8u16s_C1R( img , 1024, imageSobel_1, 2048, size);
ippiSobel3x3_Dy_8u16s_C1R( img , 1024, imageSobel_2, 2048, IPCV_ORIGIN_BL , size);
ippiCanny_16s8u_C1R(imageSobel_1, 2048, imageSobel_2, 2048, output, 1024, size, low_thr, high_thr, imageSobel_3);

This code (maybe is NOT the best one) works fine.

Now with the IPP5.0 I've tried to modify the code in this way:

#include "ippi.h"
#include "ippcv.h"

unsigned char img[1024*768*1];
unsigned char output[1024*768*1];
const int low_thr = 50;
const int high_thr = 140;
IppiSize size; size.width = 1024; size.height = 768;

Ipp16s imageSobel_1[1024*768*10];
Ipp16s *imageSobel_2 = &imageSobel_1[1024*768];
Ipp8u imageCanny[1024*768*2];

ippiFilterSobelHoriz_8u16s_C1R( img, 1024, imageSobel_1, 2048, size, ippMskSize3x3);
ippiFilterSobelVert_8u16s_C1R( img, 1024, imageSobel_2, 2048, size, ippMskSize3x3);
ippiCanny_16s8u_C1R(imageSobel_1, 2048, imageSobel_2, 2048, ouput, 1024, size, low_thr, high_thr, imageCanny);

but my program exit with a Segmentation Fault at this point.
Someone could help me or send me a simple program to apply the ippiCanny function?

Thanks in advance

Francesco

8 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

I think there's a couple of potential issues here...

First of all: Buffer allocation... Its a lot of memory to put on the stack(!)... Also, when you do allocation like this, the memory will probably not be 32-byte aligned which is required by IPP. Im actually suprised to hear that it worked with IPP4.1...

Instead you need to use the ippiMalloc/ippiFree functions when allocating your image buffers.

Another issue could be your calls to the sobel filtering functions... You need to provide a proper margin around your image, in order to accomedate the sobel filter kernel (3x3)...

Try something like this... (untested)

#include "ippi.h"
#include "ippcv.h"

int imgStep;
Ipp8u *img = ippiMalloc_8u_C1R(1024, 768, &imgStep);

int outputStep;
Ipp8u *output = ippiMalloc_8u_C1R(1024, 768, &outputStep);

const int low_thr = 50;
const int high_thr = 140;

int imageSobel1Step;
Ipp16s *imageSobel_1 = ippiMalloc_16s_C1R(1024, 768, &imageSobel1Step);

int imageSobel2Step;
Ipp16s *imageSobel_2 = ippiMalloc_16s_C1R(1024, 768, &imageSobel2Step);

IppiSize sobel1Size = { 1024 - 3, 768 };
ippiFilterSobelHoriz_8u16s_C1R( img + 1, imgStep, imageSobel_1 + 1, imageSobel1Step, sobel1Size, ippMskSize3x3 );

IppiSize sobel2Size = {1024, 768 - 3 };
ippiFilterSobelVert_8u16s_C1R( img + imgStep, imgStep, imageSobel_2, imageSobel2Step, sobel2Size, ippMskSize3x3);

...

Hope this helps.

Regards
Thomas Lund Dideriksen

Hi Thomas,
you're right for the dimension of the stack in my old program, but at same time I need a fast time of execution of the algorithm.
I've tried your code and the code of Andreas that I've found in this forum, but I don't understand very well the necessary step of the algorithm.

The ippiman.pdf said:
IppStatus ippiFilterSobelVert_8u16s_C1R( const Ipp* pSrc, int srcStep, Ipp* pDst, int dstStep, IppiSize dstRoiSize, IppiMaskSize mask);

Why you suggest to pass the pointer of image (img+1)for the Horizontal Sobel filter and (img+imgStep)for the Vertical one?
It is possible to store the images imageSobel_1 and imageSobel_2 at first and then use always this memory (maybe I must reallocate or simple clean the buffer) for all images that I want to process?

Then to apply the Canny algorithm I've tried this code:

IppiSize size = {1024, 768};
const int lowThresh = 50;
const int highThresh = 140;
int cannyBufferSize;
Ipp8u *cannyBuffer;

// Get the buffers to apply CANNY algorithm
ippiCannyGetSize(size, &cannyBufferSize);
cannyBuffer = ippsMalloc_8u(cannyBufferSize);

.......... your code .......

ippiCanny_16s8u_C1R( imageSobel_1, imageSobel1Step, imageSobel_2, imageSobel2Step, imgOutCanny, 1024, size, lowThresh, highThresh, cannyBuffer);

But it doesn't work?
Have you any idea?
Thanks in advance

Francesco

Why you suggest to pass the pointer of image (img+1)for the Horizontal Sobel filter and (img+imgStep)for the Vertical one?

Sorry.. I accidentally mistook the vertical sobel filter for a 1x3 filter and the horizontal sobel filter for a 3x1 kernel. Actually, both filters are 3x3... My mistake.

You need to offset your input image (img) in the following manner:

int imgStep;
Ipp8u *img = ippiMalloc_8u_C1(1024, 768, &imgStep);

int sobelStep;
Ipp16s *sobel = ippiMalloc_16s_C1(1024 - 2, 768 - 2, &sobelStep);

Ipp8u *imgOffset = img + imgStep + 1;

IppiSize dstRoiSize = {1024 - 2, 768 - 2};

ippiFilterSobelVert_8u16s_C1R(imgOffset, imgStep, sobel, sobelStep, dstRoiSize, IppiMaskSize3x3);

The reason you need this offset, is because the 3x3 sobel filters uses a 3x3 kernel, which needs a margin of 1 pixel on each of it four sides in order to work. If you just pass the img pointer to the sobel filter function, it will attempt to access pixels outside your allocated area (starting in point (-1,-1) and ending in (1025, 769)) which ofcourse is bad...

Note also, that the valid output of the sobel filter is is 2 pixel smaller on each side (1022x766 in this case). This is due to the same phenomenon.

In general 3x3 filters need a 1 pixel margin, 5x5 filters need a 2 pixel margin, 7x7 filters need a 3 pixel margin, etc.

It is possible to store the images imageSobel_1 and imageSobel_2 at
first and then use always this memory (maybe I must reallocate or
simple clean the buffer) for all images that I want to process?

Yes! It most certainly is... You should always try to minimize your memory allocation/deallocation as much as possible, since this is a relatively time-consuming process which can lead to memory fragmentation, and other bad things.
Allocate your imagebuffers outside your processing function (with ippiMalloc), and pass the pointers to the your processing function.
It is not necessary to clean the output buffers before each call to the sobel functions, since they will be overwritten by the function.

But it doesn't work?
Have you any idea?

I will look into this later today... I will post my results here...

-Thomas

This is tested... also with real image data. This works... Enjoy!

-Thomas

// Input image size
int width = 1024;
int height = 768;

// Allocate space for input image
int imageStep;
Ipp8u *image = ippiMalloc_8u_C1(width, height, &imageStep);

// Offset into input image
Ipp8u *imageOffset = image + imageStep + 1;

// Allocate space for horizontal sobel filter response
int sobelHorizStep;
Ipp16s *sobelHoriz = ippiMalloc_16s_C1(width-2, height-2, &sobelHorizStep);

// Allocate space for vertical sobel filter response
int sobelVertStep;
Ipp16s *sobelVert = ippiMalloc_16s_C1(width-2, height-2, &sobelVertStep);

// Allocate space for result
int outputStep;
Ipp8u *output = ippiMalloc_8u_C1(width-2, height-2, &outputStep);

// Define roi-size
IppiSize roiSize = {width-2, height-2};

// Do vertical and horizontal sobel filtering
ippiFilterSobelVert_8u16s_C1R(imageOffset, imageStep, sobelVert, sobelVertStep, roiSize, ippMskSize3x3);
ippiFilterSobelHoriz_8u16s_C1R(imageOffset, imageStep, sobelHoriz, sobelHorizStep, roiSize, ippMskSize3x3);

// Get size of canny buffer
int bufferSize;
ippiCannyGetSize(roiSize, &bufferSize);

// Allocate canny buffer
Ipp8u *buffer = ippsMalloc_8u(bufferSize);

// Do canny edge detection
float lowThresh = 50.0f;
float highThresh = 140.0f;
ippiCanny_16s8u_C1R(sobelVert, sobelVertStep, sobelHoriz, sobelHorizStep, output, outputStep, roiSize, lowThresh, highThresh, buffer);

// Memory cleanup
ippiFree(output);
ippiFree(image);
ippiFree(sobelHoriz);
ippiFree(sobelVert);
ippsFree(buffer);


Thank you very much,
Francesco

Thank you Thomas, for helping with this question. It is really nice to see that IPP community work and so, not every question should processed by me:)

Regards,
Vladimir

Another method without border outside the image (height*width array for the image). SobelNegVertBorder because SobelVert calculates -dx:

IppStatus sts;

Ipp32f low=50.0f, high=140.0f;

int size, size1, srcStep, dxStep, dyStep, dstStep;

IppiSize roi;

Ipp8u *src, *dst, *buffer;

Ipp16s *dx, *dy;

sts = ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size);

sts = ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roi, ippMskSize3x3, &size1);

if (size

ippiCannyGetSize(roi, &size1);

if (size

buffer = ippsMalloc_8u(size);

sts = ippiFilterSobelNegVertBorder_8u16s_C1R (src, srcStep, dx, dxStep, roi, ippMskSize3x3, ippBorderRepl, 0, buffer);

sts = ippiFilterSobelHorizBorder_8u16s_C1R(src, srcStep, dy, dyStep, roi, ippMskS
ize3x3, ippBorderRepl, 0, buffer);

sts = ippiCanny_16s8u_C1R(dx, dxStep, dy, dyStep, dst, dstStep, roi, low, high, buffer);

ippsFree(buffer);

Leave a Comment

Please sign in to add a comment. Not a member? Join today