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

Possible bug in ippiFilterMedianBorder_32f_C1R

Michal_K_1
Beginner
765 Views

Hello,

I may have found a bug in ippiFilterMedianBorder_32f_C1R. Could you check if this code is correct and if you can reproduce this bug?

#include <ipps.h>
#include <ippi.h>
#include <vector>
#include <iostream>

int main()
{
   const IppLibraryVersion *pp = ippiGetLibVersion();

   IppiSize roi = { 33, 33 };
   //IppiSize roi = { 250, 250 };
   IppiSize mask = { 41, 41 };

   int align = 64;
   int widthBytes = ((roi.width * 4 + align - 1) / align) * align;
   int pitch = widthBytes / 4;

   std::vector<float> v1(pitch * roi.height, 10.0f);
   std::vector<float> v2(pitch * roi.height);

   int bufferSize = 0;
   IppStatus sts;

   sts = ippiFilterMedianBorderGetBufferSize(roi, mask, ipp32f, 1, &bufferSize);

   Ipp8u *buffer = ippsMalloc_8u(bufferSize);
   sts = ippiFilterMedianBorder_32f_C1R(&v1.front(), widthBytes, &v2.front(), widthBytes, roi, mask, ippBorderRepl, 0.0f, buffer);
   ippsFree(buffer);

   for (size_t i = 0; i < roi.height; ++i)
   {
      std::cout << "ROW " << i << ": " << v1[i * pitch] << ", " << v2[i * pitch] << std::endl;
   }

   std::cin.get();

   return 0;
}

If you run this code with 33x33 size, then it crashes on my system. If you use 250x250 size, then it doesn't crash, but first few rows of the resulting image are wrong.

ippiGetLibVersion returns:

major - 2017

minor - 0

majorBuild - 3

build - 55431

targetCpu - l9

Name - ippIP AVX2 (l9)

Version - 2017.0.3 (r55431)

BuildDate - Apr 12 2017

 

0 Kudos
7 Replies
Jonghak_K_Intel
Employee
765 Views

Hi Michal K, 

 

thank you for reporting the issue with ippiFilterMedianBorder function. 

We found the bug and fixed it. The fix has been delivered with the latest IPP 2017 Update 3 release. 

Please update your IPP to 2017 update 3 and see if the bug still remains. 

 

Thank you 

0 Kudos
Michal_K_1
Beginner
765 Views

Hi JON J K,

as far as I know, I am using the latest IPP 2017 Update 3 release. I reinstalled this version again to make sure, but I continue to have the same results. Could you please provide a link to a correct version?

I downloaded IPP from here: https://software.intel.com/en-us/intel-ipp - then I chose "Get this library for free" and on next page: Product - Intel Performance Libraries for Windows, Version - 2017 Update 3. The downloaded file is w_ipp_2017.3.210.exe. The resulting installation directory is C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2017.4.210\windows

To setup my project in Visual Studio I followed advice in https://software.intel.com/en-us/get-started-with-ipp-for-windows

The result of a call to ippGetLibVersion is the same as in my first post and the bug is still present. Is there something I overlooked?

With Regards,

Michal

 

0 Kudos
Jonghak_K_Intel
Employee
765 Views

Hi Michal,

 

 With your code , I see the same thing. I don't fully understand how you got your way to calculate 'widthBytes = ((roi.width * 4 + align - 1) / align) * align;' .

Could you try to follow this example and see if you get the same results?

 


#include <stdio.h>
#include "ipp.h"

#define WIDTH 16 /* image width */
#define HEIGHT 16 /* image height */

/* Next two defines are created to simplify code reading and understanding */
#define EXIT_MAIN exitLine: /* Label for Exit */
#define check_sts(st) if((st) != ippStsNoErr) goto exitLine; /* Go to Exit if IPP function returned status different from ippStsNoErr */

/* Results of ippMalloc() are not validated because IPP functions perform bad arguments check and will return an appropriate status */

int main(void)
{
    IppStatus status = ippStsNoErr;
    Ipp8u* pSrc = NULL, *pDst = NULL;     /* Pointers to source/destination images */
    int srcStep = 0, dstStep = 0;         /* Steps, in bytes, through the source/destination images */
    IppiSize srcImageSize = { WIDTH+1, HEIGHT+1}; /* size of source image in pixels */
    IppiSize roiSize = { WIDTH, HEIGHT }; /* Size of source/destination ROI in pixels */
    Ipp8u *pBuffer = NULL;                /* Pointer to the work buffer */
    int iTmpBufSize = 0;                  /* Common work buffer size */
    IppiBorderType borderType = (IppiBorderType)(ippBorderRepl | ippBorderInMemTop | ippBorderInMemRight);
    Ipp8u borderValue = 254;
    IppiSize maskSize = { 3, 3 };
    int numChannels = 1;

    /* memory allocation */
    pSrc = ippiMalloc_8u_C1(srcImageSize.width, srcImageSize.height, &srcStep);
    pDst = ippiMalloc_8u_C1(roiSize.width, roiSize.height, &dstStep);

    check_sts( status = ippiFilterMedianBorderGetBufferSize(roiSize, maskSize, ipp8u, numChannels, &iTmpBufSize) )

    pBuffer = ippsMalloc_8u(iTmpBufSize);

    check_sts( status = ippiFilterMedianBorder_8u_C1R(pSrc + srcStep, srcStep, pDst, dstStep, roiSize, maskSize, borderType, borderValue, pBuffer) )

EXIT_MAIN
    ippsFree(pBuffer);
    ippiFree(pSrc);
    ippiFree(pDst);
    printf("Exit status %d (%s)\n", (int)status, ippGetStatusString(status));
    return (int)status;
}
 

0 Kudos
Michal_K_1
Beginner
765 Views

Hi JON J K,

thank you for your answer. The code:

widthBytes = ((roi.width * 4 + align - 1) / align) * align;

calculates widthBytes (or step as you call it) from width of the image, that is aligned to "align" bytes. Align is 64 in my case, so this code calculates the 64-byte aligned step size.

I tried to run your code and it works, however my problems are with the 32f version of median. Also, the bug seems to surface only when evaluating median over large mask and when using ippBorderRepl. Here is your modified code that crashes on my system:

#include <stdio.h>
#include "ipp.h"

#define WIDTH 16 /* image width */
#define HEIGHT 16 /* image height */

/* Next two defines are created to simplify code reading and understanding */
#define EXIT_MAIN exitLine: /* Label for Exit */
#define check_sts(st) if((st) != ippStsNoErr) goto exitLine; /* Go to Exit if IPP function returned status different from ippStsNoErr */

/* Results of ippMalloc() are not validated because IPP functions perform bad arguments check and will return an appropriate status */

int main(void)
{
    IppStatus status = ippStsNoErr;
    Ipp32f* pSrc = NULL, *pDst = NULL;     /* Pointers to source/destination images */
    int srcStep = 0, dstStep = 0;         /* Steps, in bytes, through the source/destination images */
    IppiSize srcImageSize = { WIDTH, HEIGHT}; /* size of source image in pixels */
    IppiSize roiSize = { WIDTH, HEIGHT }; /* Size of source/destination ROI in pixels */
    Ipp8u *pBuffer = NULL;                /* Pointer to the work buffer */
    int iTmpBufSize = 0;                  /* Common work buffer size */
    IppiBorderType borderType = (IppiBorderType)ippBorderRepl;
    Ipp32f borderValue = 254;
    IppiSize maskSize = { 41, 41 };
    int numChannels = 1;

    /* memory allocation */
    pSrc = ippiMalloc_32f_C1(srcImageSize.width, srcImageSize.height, &srcStep);
    pDst = ippiMalloc_32f_C1(roiSize.width, roiSize.height, &dstStep);

    check_sts( status = ippiFilterMedianBorderGetBufferSize(roiSize, maskSize, ipp32f, numChannels, &iTmpBufSize) )

    pBuffer = ippsMalloc_8u(iTmpBufSize);

    check_sts( status = ippiFilterMedianBorder_32f_C1R(pSrc, srcStep, pDst, dstStep, roiSize, maskSize, borderType, borderValue, pBuffer) )

EXIT_MAIN
    ippsFree(pBuffer);
    ippiFree(pSrc);
    ippiFree(pDst);
    printf("Exit status %d (%s)\n", (int)status, ippGetStatusString(status));
    return (int)status;
}

 

Now in this case the maskSize is larger than the image itself, but that shouldn't be a problem with ippBorderRepl

Also, if you change the roiSize and srcImageSize to 250x250 the above code doesn't crash, but calculates incorrect results on first few rows of the image. I'm attaching the changed source code as well:

#include <stdio.h>
#include "ipp.h"

#define WIDTH 250 /* image width */
#define HEIGHT 250 /* image height */

/* Next two defines are created to simplify code reading and understanding */
#define EXIT_MAIN exitLine: /* Label for Exit */
#define check_sts(st) if((st) != ippStsNoErr) goto exitLine; /* Go to Exit if IPP function returned status different from ippStsNoErr */

/* Results of ippMalloc() are not validated because IPP functions perform bad arguments check and will return an appropriate status */

int main(void)
{
    IppStatus status = ippStsNoErr;
    Ipp32f* pSrc = NULL, *pDst = NULL;     /* Pointers to source/destination images */
    int srcStep = 0, dstStep = 0;         /* Steps, in bytes, through the source/destination images */
    IppiSize srcImageSize = { WIDTH, HEIGHT}; /* size of source image in pixels */
    IppiSize roiSize = { WIDTH, HEIGHT }; /* Size of source/destination ROI in pixels */
    Ipp8u *pBuffer = NULL;                /* Pointer to the work buffer */
    int iTmpBufSize = 0;                  /* Common work buffer size */
    IppiBorderType borderType = (IppiBorderType)ippBorderRepl;
    Ipp32f borderValue = 254;
    IppiSize maskSize = { 41, 41 };
    int numChannels = 1;

    /* memory allocation */
    pSrc = ippiMalloc_32f_C1(srcImageSize.width, srcImageSize.height, &srcStep);
    pDst = ippiMalloc_32f_C1(roiSize.width, roiSize.height, &dstStep);

    for (int j = 0; j < srcImageSize.height; ++j)
    {
       for (int i = 0; i < srcImageSize.width; ++i)
       {
          pSrc[j * srcStep / 4 + i] = 10.0f;
       }
    }

    check_sts( status = ippiFilterMedianBorderGetBufferSize(roiSize, maskSize, ipp32f, numChannels, &iTmpBufSize) )

    pBuffer = ippsMalloc_8u(iTmpBufSize);

    check_sts( status = ippiFilterMedianBorder_32f_C1R(pSrc, srcStep, pDst, dstStep, roiSize, maskSize, borderType, borderValue, pBuffer) )

    for (int j = 0; j < roiSize.height; ++j)
    {
       printf("ROW %i: %f, %f\n", j, pSrc[j * srcStep / 4], pDst[j * dstStep / 4]);
    }

EXIT_MAIN
    ippsFree(pBuffer);
    ippiFree(pSrc);
    ippiFree(pDst);
    printf("Exit status %d (%s)\n", (int)status, ippGetStatusString(status));
    return (int)status;
}

 

With Regards,

Michal

0 Kudos
Jonghak_K_Intel
Employee
765 Views

Hi Michal,

 I escalated this issue to the engineering.

 Thank you and I will come back to you when we get this resolved.

0 Kudos
Ivan_Z_Intel
Employee
765 Views

Hi all,

There is the bug in function ippiFilterMedianBorder_32f_C1R. The function executions incorrectly if mask.width * mask.height >= 625.

This bug will be fixed in the next versions.

Thank you very much for the example of incorrect work of the function.

0 Kudos
Michal_K_1
Beginner
765 Views

Thank you guys.

0 Kudos
Reply