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

Canny Edge Detector


Hi, I have some problems width canny edge detector using IPP

I make three steps:

I have 3-channel image(byte array), that ordered like this RGBRGB...

The first step is applying grayScale filter.

The second is calculation gradients dx and dy using IPP vertical and horizontal Sobel filters with border, 

The last step is using ippiCanny


unsigned char * RGBToGrayScaleIpp(unsigned char * src, int width, int height, int channels)
    IppiSize ROI = {width, height};
    Ipp8u *GrayScaleImg = new Ipp8u[width * height];
    ippiRGBToGray_8u_C3C1R(src, width * channels * sizeof(Ipp8u), GrayScaleImg, width * sizeof(Ipp8u), ROI);
    return GrayScaleImg;

extern "C" __declspec(dllexport) unsigned char* __stdcall Canny(unsigned char * img, int channels, int width, int height)

    Ipp8u *GrayScaleImg = RGBToGrayScaleIpp(img, width, height, channels);

    IppiSize roiSize = {width - 1, height - 1};

    int horizBufferSize, vertBufferSize;
    IppiMaskSize maskSize = ippMskSize3x3;
    ippiFilterSobelVertGetBufferSize_8u16s_C1R(roiSize, maskSize, &vertBufferSize);
    ippiFilterSobelHorizGetBufferSize_8u16s_C1R(roiSize, maskSize, &horizBufferSize);

    Ipp8u *horizBuffer = ippsMalloc_8u(horizBufferSize);
    Ipp8u *vertBuffer = ippsMalloc_8u(vertBufferSize);

    Ipp16s *dx = new Ipp16s[width * height];
    Ipp16s *dy = new Ipp16s[width * height];

    ippiFilterSobelVertBorder_8u16s_C1R(GrayScaleImg, width * sizeof(Ipp8u), dx, (width - 1) * sizeof(Ipp16s), roiSize, maskSize, ippBorderRepl, 0, vertBuffer);
    ippiFilterSobelHorizBorder_8u16s_C1R(GrayScaleImg, width * sizeof(Ipp8u), dy, (width - 1) * sizeof(Ipp16s), roiSize, maskSize, ippBorderRepl, 0, horizBuffer);

    Ipp8u *buffer;
    if (vertBufferSize < horizBufferSize)
        ippiCannyGetSize(roiSize, &horizBufferSize);
        buffer = ippsMalloc_8u(horizBufferSize);
        ippiCannyGetSize(roiSize, &vertBufferSize);
        buffer = ippsMalloc_8u(vertBufferSize);

    Ipp32f low=100.0f, high=100.0f;
    Ipp8u* dst = new Ipp8u[width * height];
    ippiCanny_16s8u_C1R(dx, (width - 1) * sizeof(Ipp16s), dy, (width - 1) * sizeof(Ipp16s), dst, width * sizeof(Ipp8u), roiSize, low, high, buffer);


    return dst;


I get incorrect result. In attach files there are 3 images source, filtered using .NET Aforge and filtered using IPP. Can you see any mistakes in my code? Please, help.


0 Kudos
5 Replies

Hi Alexandr,

in the latest IPP versions you can find more advanced function:

//  Name:    ippiCannyBorder_8u_C1R
//  Purpose: Perform convolution operation with fixed kernels 3x3 and 5x5 and creates binary image of source's image edges,
//                using derivatives of the first order.
//  Parameters:
//    pSrc                     The pointer to the source image
//    srcStep                  The step in the source image
//    pDst                     The pointer to the destination image
//    dstStep                  The step in the destination image
//    roiSize                  The image ROI size
//    filterType               the filter type(ippFilterSobel,ippFilterScharr)
//    mask                     The mask size(ippMskSize3x3,ippMskSize5x5)
//    borderType               Type of border. Possible values are:
//                     ippBorderConst Values of all border pixels are set to constant.
//                     ippBorderRepl Border is replicated from the edge pixels.
//                     ippBorderInMem Border is obtained from the source image pixels in memory.
//                     Mixed borders are also supported. They can be obtained by the bitwise operation OR between ippBorderRepl and ippBorderInMemTop, ippBorderInMemBottom, ippBorderInMemLeft, ippBorderInMemRight.
//    borderValue              The value for the constant border
//    lowThresh                Low threshold for edges detection
//    highThresh               Upper threshold for edges detection
//    norm                     Norm type (ippNormL1,ippNormL2)
//    pBuffer                  Pointer to the pre-allocated temporary buffer, which size can be
//                             calculated using ippiCannyEdgeDetectionGetSize function
//  Return:
//    ippStsNoErr              Ok
//    ippStsNullPtrErr         One of pointers is NULL
//    ippStsSizeErr            The width or height of images is less or equal zero
//    ippStsNotEvenStepErr     Step is not multiple of element.
//    ippStsBadArgErr          Bad thresholds

IPPAPI(IppStatus, ippiCannyBorder_8u_C1R,( const Ipp8u* pSrc, int srcStep, Ipp8u* pDst, int dstStep, IppiSize roiSize,
                            IppiDifferentialKernel filterType, IppiMaskSize mask,IppiBorderType borderType, Ipp8u borderValue,
                            Ipp32f lowThresh, Ipp32f highThresh, IppNormType norm,Ipp8u* pBuffer ))
//  Name:    ippiCannyBorderGetSize
//  Purpose: Calculates size of temporary buffer, required to run ippiCannyBorder_8u_C1R function.
//  Parameters:
//    roiSize           Size of image ROI in pixel
//    filterType        The filter type(ippFilterSobel,ippFilterScharr)
//    mask              The mask size(ippMskSize3x3,ippMskSize5x5)
//    dataType          Data type of the image. Possible values are Ipp8u, Ipp16u, Ipp16s, or Ipp32f.
//    pBufferSize       Pointer to the variable that returns the size of the temporary buffer
//  Return:
//    ippStsNoErr       Ok
//    ippStsNullPtrErr  Pointer bufferSize is NULL
//    ippStsMaskSizeErr Indicates an error when mask has an illegal value.
//    ippStsDataTypeErr Indicates an error when dataType has an illegal value.
//    ippStsSizeErr     roiSize has a field with zero or negative value
IPPAPI(IppStatus, ippiCannyBorderGetSize,( IppiSize roiSize, IppiDifferentialKernel filterType,IppiMaskSize mask, IppDataType dataType, int* pBufferSize ))

And I can't find any attachments...

regards, Igor

0 Kudos

one more thing: I don't understand your manipulations with "width" - if you have allocated image of width*height, you can't use " (width - 1) * sizeof(Ipp16s)" as a step - you can set any roi inside this image (for example (width-N)x(height-M)), but image step still is == width...

regards, Igor

0 Kudos

Igor, thanks for your answer

I rewrote the code like this:

Ipp8u *GrayScaleImg = RGBToGrayScaleIpp(img, width, height, channels);

Ipp8u* pBuffer = 0;
int bufferSize;
IppiSize roiSize = {width, height};
IppiDifferentialKernel filterType = ippFilterSobel;

ippiCannyBorderGetSize( roiSize, filterType,ippMskSize3x3, ipp8u, &bufferSize);
pBuffer = ippsMalloc_8u( bufferSize );
Ipp32f low = 100.0f, high = 100.0f;
ippiCannyBorder_8u_C1R(GrayScaleImg, width, GrayScaleImg, width, roiSize, filterType, ippMskSize3x3, ippBorderRepl,0, low, high, ippNormL2, pBuffer);

but I have almost the same result, and I did not understand what values should take "src step", "dst step " and "roi size" in my case.

regards, Alexandr


0 Kudos

Hi Alexander,

Check this document on the step, ROI for image function:


0 Kudos

Hi Chao,

thanks for your response, I solved the problem

0 Kudos