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

Help required to use ippiFilter

georgiswan
Beginner
635 Views

Hi

Ihave a hard time using ippiFilter, no matter what I do, I either get a segmentation fault or ippStsStepErr (some error with my images steps).

Would someone have a working example showing how to use this function and similar functions ?

For example, the following example works (status = 0). However, if I try to use a 4x3 output image (instead of a 3x3) with corresponding dstRoiSize, I get the step error (keeping all the rest identical). I dont see why I could not get a 4x3 output image from that example.

~~~~~~~~~~~~~~~~~~~~~~~~

char pSrc[8*5] = {0,1,2,3,4,5,6,7,
0,1,2,3,4,5,6,7,
0,1,2,3,4,5,6,7,
7,6,5,4,3,2,1,0,
7,6,5,4,3,2,1,0};

int srcStep = 8;

char pDst[3*3];
int dstStep = 3;

IppiSize dstRoiSize = {3,3};
int pKernel[3*3] = {1,1,1,1,1,1,1,1,1};
IppiSize kernelSize = {3,3};
IppiPoint anchor = {1,1};
int divisor = 9;

IppStatus status = ippiFilter_8u_C1R(pSrc, srcStep, pDst, dstStep, dstRoiSize, pKernel,kernelSize , anchor, divisor);

printf("ippiFilter status = %d\n",status);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

From the documentation, it is not very clear how to determine the steps so that they are accepted by the routine:


ippStsStepErr Indicates an error condition if the srcStep is less than
(roiSize.width + kernelSize.width)*sizeof(Ipp64f);
or dstStep is less than roiSize.width*sizeof(Ipp64f).

Why this multiplication by sizeof(Ipp64f)if I am using 8 bit unsigned integers?

Do I need or not a border around my source image? If yes, what is the size of that border?

I guess it shows that I am quite lost. Any help on that topic would be welcome.

Thank you!

Gilbert
0 Kudos
5 Replies
amyron
Beginner
635 Views
Quoting - georgiswan

Hi

Ihave a hard time using ippiFilter, no matter what I do, I either get a segmentation fault or ippStsStepErr (some error with my images steps).

Would someone have a working example showing how to use this function and similar functions ?

For example, the following example works (status = 0). However, if I try to use a 4x3 output image (instead of a 3x3) with corresponding dstRoiSize, I get the step error (keeping all the rest identical). I dont see why I could not get a 4x3 output image from that example.

~~~~~~~~~~~~~~~~~~~~~~~~

char pSrc[8*5] = {0,1,2,3,4,5,6,7,
0,1,2,3,4,5,6,7,
0,1,2,3,4,5,6,7,
7,6,5,4,3,2,1,0,
7,6,5,4,3,2,1,0};

int srcStep = 8;

char pDst[3*3];
int dstStep = 3;

IppiSize dstRoiSize = {3,3};
int pKernel[3*3] = {1,1,1,1,1,1,1,1,1};
IppiSize kernelSize = {3,3};
IppiPoint anchor = {1,1};
int divisor = 9;

IppStatus status = ippiFilter_8u_C1R(pSrc, srcStep, pDst, dstStep, dstRoiSize, pKernel,kernelSize , anchor, divisor);

printf("ippiFilter status = %dn",status);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

From the documentation, it is not very clear how to determine the steps so that they are accepted by the routine:


ippStsStepErr Indicates an error condition if the srcStep is less than
(roiSize.width + kernelSize.width)*sizeof(Ipp64f);
or dstStep is less than roiSize.width*sizeof(Ipp64f).

Why this multiplication by sizeof(Ipp64f) if I am using 8 bit unsigned integers?

Do I need or not a border around my source image? If yes, what is the size of that border?

I guess it shows that I am quite lost. Any help on that topic would be welcome.

Thank you!

Gilbert

Try using
Ipp8u pSrc[8*5]=...
Ipp8u pDst[3*3];

instead of
char pSrc[8*5]=...
char pDst[3*3];


0 Kudos
Ying_H_Intel
Employee
636 Views
Hi Gilbert,

The ippStsStepErr error happen when
char pDst[4*3];
int dstStep = 3;
IppiSize dstRoiSize = {4,3};
right?

The parameter stepBytes represents the Distance in bytes between starts of consecutive lines in the image.
In general, if the image is stored in contiguous memory,stepBytes= image width*sizeof(data type).

In above case, theimage is stored in 1-D array,the width of image may undetermined at first. But if we define dstRoiSize={4, 3}={width, height}, this means the image width=4.
Soyou maytry dstStep=4, the errorshould begone.

Butas you asked," Do I need or not a border around my source image? If yes, what is the size of that border?", The answer is yes, we should consider border issue here. In fact, Intel IPP image filtering functions assume that for each pixel being processed, adjacent pixels also exist. So you need to consider it in your code.
For example,
IppStatus status = ippiFilter_8u_C1R((Ipp8u*) pSrc+srcStep+1, srcStep, (Ipp8u*)pDst, dstStep, dstRoiSize, pKernel,kernelSize , anchor, divisor);
shouldreturn more reasonable value than ippiFilter_8u_C1R((Ipp8u*) pSrc ...

We haverelated discussion andFilter sampe code at KB:
Processing an Image from Edge to Edge
<http://software.intel.com/en-us/articles/intel-integrated-performance-primitives-intel-ipp-calling-image-processing-functions/>
Please refer it.

Best Regards,
Ying
0 Kudos
georgiswan
Beginner
636 Views

I created a complete program to test the ippiFilter routine and to experiment with the very senstitive parameters. I pastedthe codebelow in this posting in case it can help others as well. The program shows how to load an image (using the 3rd party library FreeImage ), run a kernel on the image and save it back to disk.

This file compiles under linux and never segment faults when you use reasonable kernel size and anchor coordinates.

You can change the kernel size and the anchor point (via the #define at the top of the file) and the image offset will be calculated to avoid segmentation fault.

The image border is a little vague in the documentation, this programs shows exactly how to compute it and how to apply it for a RGB image.

If you dont have freeImage, you should give it a try. Otherwise, you can use your preferred way to load a file in memory.

My problem is solved ;-) !!

Gilbert

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#include
#include
#include

#include
#include

#define JPEG_FILE "b.jpg"

// Set the size of the kernel to use here. It will be filled with 1 everywhere.
#define KERNEL_WIDTH 7
#define KERNEL_HEIGHT 7

// Set the anchor coordinate in the kernel ([0 kernelSize-1] )
#define ANCHOR_X 2
#define ANCHOR_Y 5

// The rest of the parameters is all computed automatically to use IppiFitlter
// on the largest portion of the source image without causing a segmentation fault.

int main(int argc, char **argv)
{

fprintf(stderr,"--------------------------------------------------n");
fprintf(stderr,"Test program for the IPP library.n");
fprintf(stderr,"--------------------------------------------------n");

//----------------------------------------------------------------------------------
// Load a JPEG image using FreeImage library ( http://freeimage.sourceforge.net/ )
// FreeImage is great, you should try it.
// FreeImage let you access the low level image data in a binary format
// compatible to IPP. So, we usually dont need to copy the data to reformat it.
//---------------------------------------------------------------------------------
fprintf(stderr,"Loading a JPEG image...");
FIBITMAP* bitmap = FreeImage_Load(FIF_JPEG, JPEG_FILE, 0);
fprintf(stderr,"done.n");

fprintf(stderr,"Calling IppiFilter on that image...n");

// get the low level data using FreeImage calls
int srcWidth = FreeImage_GetWidth(bitmap);
int srcHeight = FreeImage_GetHeight(bitmap);
int srcStep = FreeImage_GetPitch(bitmap);
unsigned char *pSrc = FreeImage_GetBits(bitmap);

fprintf(stderr," Src Size : %d X %dn",srcWidth, srcHeight);
fprintf(stderr," Src Step : %dn", srcStep);

// take the anchor point as is
IppiPoint anchor = {ANCHOR_X, ANCHOR_Y};

// need to reserve a border around the source image otherwise IppiFilter will crash trying to access
// the pixel outside the image border. The border to leave around the image depends on
// the anchor point and on the size of the kernel.
//
// Because IPP inverts the kernel (convolution style), we need to invert the size of the
// border (hor. and vert. accordingly).
int borderWidth = KERNEL_WIDTH - anchor.x - 1;
int borderHeight = KERNEL_HEIGHT - anchor.y - 1;
fprintf(stderr," Border width : %dn", borderWidth);
fprintf(stderr," Border height : %dn", borderHeight);

// prepare the kernel for IppiFilter
int kernelWidth = KERNEL_WIDTH;
int kernelHeight = KERNEL_HEIGHT;
int divisor = kernelWidth*kernelHeight;
Ipp32s* pKernel = (Ipp32s*) malloc(kernelWidth * kernelHeight * sizeof(Ipp32s));

fprintf(stderr," Kernel Size : %d X %dn", kernelWidth, kernelHeight);
fprintf(stderr," Kernel Anchor: (%d, %d)n", anchor.x, anchor.y);

// fill the kernel with 1 eveywhere (just an average will do for our test)
for (int i=0; ipKernel = 1;
}
IppiSize kernelSize = {kernelWidth, kernelWidth};

// prepare other data structures for IppiFilter
int dstWidth = srcWidth - (kernelWidth - 1); // max dst width depends on kernel size
int dstHeight = srcHeight - (kernelHeight - 1); // max dst height also depends on kernel size
int dstStep = (((dstWidth*3-1)/4)+1)*4; // round up to nearest multiple of 4 (RGB data -> *3)
int dstSize = dstHeight * dstStep; // total memory size required
unsigned char *pDst = (unsigned char*) malloc(dstSize);
IppiSize dstRoiSize = {dstWidth, dstHeight};

fprintf(stderr," Dst Size : %d X %dn", dstWidth, dstHeight);
fprintf(stderr," Dst step : %dn", dstStep);


// Offset the source pointer. That's how we build a border around the source image to avoid
// segmentation fault. Note that I use an RGB image so that explains the *3. srcStep already
// has taken the RGB interleaved structure in consideration so no need for the *3 there for the
// vertical border offset.
// See above to know how to compute the borders (really pointer offsets).
unsigned char * pSrcIPP = pSrc + borderHeight * srcStep + borderWidth*3;

// Try to predict the ippStsStepErr IPP error (its doc is wrong, I think that this test will do)
if (srcWidth < dstWidth + (kernelWidth-1)) {
fprintf(stderr,"Warning: IPP will procduce a ippStsStepErr errorn");
}

// finally, calling IppiFilter (it is about time)
fprintf(stderr,"Calling Ipp_Filter....");
IppStatus filterStatus = ippiFilter_8u_C3R(pSrcIPP, srcStep, pDst, dstStep, dstRoiSize,
pKernel, kernelSize, anchor, divisor);

fprintf(stderr,"done. IppiFilter status = %dn", filterStatus);
if (filterStatus != 0) {
fprintf(stderr,"Problem with IppFilter. Giving up!n");
exit(1);
}

// save the image with FreeImage to validate visually that it worked
FIBITMAP* bitmapSave = FreeImage_Allocate(dstWidth, dstHeight, 24, 0, 0, 0);
unsigned char *pDstFI = FreeImage_GetBits(bitmapSave);
int dstStepFI = FreeImage_GetPitch(bitmapSave);

if (dstStepFI == dstStep) {
// Just a straight copy over from IPP to freeimage low-level pointer will do.
// This is not pure luck, it should always be like that.
memcpy(pDstFI, pDst, dstSize);
}
else {
// FreeImage pitch and IPP pitch differ. In this case, we should copy the data line per line.
// That's unfortunate and should virutally never happen. So I dont even handle that case...
// If that happens to you, you should check what's wrong.
fprintf(stderr,"Need to copy line per line ( dstStepFI(%d) <> dstStep(%d) )n", dstStepFI, dstStep);
exit(1);
}


fprintf(stderr,"Saving filtered image to disk...");
bool statusSave = FreeImage_Save(FIF_BMP, bitmapSave, "./filterIPP.bmp", 0);
fprintf(stderr,"done. Status : %dn",statusSave);


// free the memory to make sure that everything is sane
if (pDst) free(pDst);
if (bitmapSave) FreeImage_Unload(bitmapSave);
if (bitmap) FreeImage_Unload(bitmap);
if (pKernel) free(pKernel);


return 0;
}
0 Kudos
Ying_H_Intel
Employee
636 Views
Hi georgiswan,

Your sample code looks great. It takes care of threekey problems when using IPP image functions.

1. stepBytes.
int dstStep = (((dstWidth*3-1)/4)+1)*4; // round up to nearest multiple of 4 (RGB data -> *3)

Note: the srcStep may != channel*srcWidth in some of cases.
srcStep may be = ((nChannel*srcWidth+3)>>2)<<2 if bmp 4 bytes-aligned format;
srcStep may be = a 32x value if use ippiMalloc(), it is 32 bytes-aligned

2.Image Border
int borderWidth = KERNEL_WIDTH - anchor.x - 1;
int borderHeight = KERNEL_HEIGHT - anchor.y - 1;

3. ROI (Region of Interesting)
unsigned char * pSrcIPP = pSrc + borderHeight * srcStep + borderWidth*3;

dstWidth = srcWidth - (kernelWidth - 1);
dstHeight = srcHeight - (kernelHeight - 1); // max dst height also depends on kernel size
IppiSize dstRoiSize = {dstWidth, dstHeight};

Thank you a lot for sharing! For who haveIPP book v2, therearesame discussion in chapter 10: Image Filtering and Manipulation and corresponding sample code.

Best Regards,
Ying
here is part of code from IPP book
<http://software.intel.com/en-us/articles/intel-integrated-performance-primitives-intel-ipp-intel-ipp-source-code-examples/>

0 Kudos
georgiswan
Beginner
636 Views

IMHO, the Java Interface sample to IppiFilter usd in the sample code provided withIPP ( IPP/ipp-samples/language-interface/java/test/tip.java ) is buggy in the sense that it does not offsets the pointer to the source image to create a safe border. In fact, when you run that sample code ( ./run32.sh ) and you presse in sequence

.....


you get a segmentation fault (usually within 5 iterations on my computer, always less then 10).

Now, this brings a problem with the JNI interface (which I am trying to use) : how can one offset his/her pointer in JAVA before calling the IppiFilter routine ? I dont know any way to do that offset in Java directly. So, I am looking at modyfing the JNI side to apply the offset there (since I can't do it in JAVA, JAVA does not support pointer arithmetic). Any idea/comment on that?

Thanks

Gilbert
0 Kudos
Reply