Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.
6709 Discussions

How to use ippiDilate_8u_C1IR and ippiErode_8u_C1IR?

zhangguang
Beginner
527 Views

const unsigned char pMask[15] = {1,1,1,1,1,

1,1,1,1,1,

1,1,1,1,1};

IppiSize maskSize = { 3,5 };

IppiPoint anchor = { 1 , 2};

IppiSize roiSize = { 2048 , 1536 };

IppStatus status;

status = ippiErode_8u_C1IR( (Ipp8u*)image.DataPtr(),

image.Step( ),

roiSize,

pMask,

maskSize,

anchor

);

ippiDilate_8u_C1IR( (Ipp8u*)image.DataPtr(),

image.Step( ),

roiSize,

pMask,

maskSize,

anchor

);

the iamge has no change

the image width is 2048 and the height is 1536, status return value is ippStsStrideErr, it means Stride value is less than the row length, but how to define image.Step( ),what can I do?

Thanks!

0 Kudos
3 Replies
Vladimir_Dudnik
Employee
527 Views

Hello,

I think youneed to specify MaskSize as 5,3 instead of 3,5.

probably following info from ippi.h file can help to clarify a bit how image step is related to the mask.

it is from where ippiErode/Dilate defined in ippi.h file

// ippStsStrideErr, if (maskSize.width-1+dstRoiSize.width)*nChannels*sizeof(item)) > srcStep or
// (maskSize.width-1+dstRoiSize.width)*nChannels*sizeof(item)) > dstStep

Regards,
Vladimir

0 Kudos
Emilio_G_
Beginner
527 Views
I have had problems like this in the past; namely because the documentation is not explicitly clear.

Because you are calling a function which looks at pixels around each pixel in the ROI, if your ROI is an entire image, you must first create a new image with a border of sufficient size to accomodate whatever kernel (neighborhood) size you are using---the documentation has a section on borders. This is true also of the convolution functions, for example. Therefore, it is not possible to use the "in-place" version of these functions if the ROI is the entire image (with the exception of the seemingly rare functions that create their own borders). You must first create a new "scratch" image, then either use one of three border-creating functions in IPP (which copy the source image and add either a duplicated, wrapped, or constant border) into the scratch image or do your own thing. Then run the function with the scratch as the source and the original image as the destination.

It may also be that your neighborhood dimensions are inverted, as mentioned in the other answer, but that's a separate issue.

Be advised that there is a bug with respect to the anchor point, at least in IPP 5.1. The documentation seems to claim that the anchor point is assigned relative to the neighborhood, that is, as in your sample code above, the anchor is set to the center of your neighborhood. However this does not seem to be true. You will find if you modified your code to use an image with a border, you will see that you will get an access violation because the dilate function is trying to read the source image beyond its size. For example, if your neighborhood is 3x3 (so you create an image with border 1; new width = original width + 2*border) and your anchor is 1,1, the access violation occurs precisely 1 step size + 1 sizeof(pixel data type) before the location of the image pointer, meaning that it goes to pixel 0,0 of the source image and looks up one and one to the left. In my case I just set the anchor to 0,0 which prevents the access violation, but I am not sure if now the dilate funtion is actually using the top left corner of the neighborhood as the anchor or if anchor is simply defined incorrectly in the documentation and the function always uses the center of the neighborhood as the anchor.
0 Kudos
Vladimir_Dudnik
Employee
527 Views

Hello,

in IPP functions which need border values for calculations do assume that these values are available in the memory. Please refer to IPP manual for the details.

So, if you have 3x3 kernel and you wnat to process image starting from its the first pixel you need to create border values before call of function. On practice it means that you need to copy your image into memory buffer with sufficient size for the border and then to point pSrc to the beginning of your image (so border values exists around your image).

But if you can guarantee that border values are exist before call of function (for example you erode/dilate some part of image in the middle) you can use in-place operation.

We have no registered issues with kernel anchor point for these functions. You throuble might be related to the way you use function (with not taking into account IPP assumption about border values).

Regards,
Vladimir

0 Kudos
Reply