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

2D wavelet transform then inverse transform results in imperfect reconstruction along top and left

Ben_Ochoa
Beginner
332 Views

In the code below, the resulting reconstruction is perfect, except for the first two rows and columns.  This is the case regardless of the source image or image extension (e.g., ippiCopyMirrorBorder method), and is also present in the case of 3 channel images.  For larger wavelet filter kernels, the imperfection is along a larger number of the first rows and columns.  Is there an issue with usage below?

Thanks,
Ben

 

int main( int argc, char *argv[] )
{
    // db2
    const int kernelFwdLowLen = 4;
    const int kernelFwdLowAnchor = 3;
    const float kernelFwdLow[kernelFwdLowLen] = 
    {
        -0.12940952255092145f,
         0.22414386804185735f,
         0.83651630373746900f,
         0.48296291314469025f
    };
    const int kernelFwdHighLen = 4;
    const int kernelFwdHighAnchor = 3;
    const float kernelFwdHigh[kernelFwdHighLen] = 
    {
        -0.48296291314469025f,
         0.83651630373746900f,
        -0.22414386804185735f,
        -0.12940952255092145f
    };
    const int kernelInvLowLen = 4;
    const int kernelInvLowAnchor = 0;
    const float kernelInvLow[kernelInvLowLen] = 
    {
         0.48296291314469025f,
         0.83651630373746900f,
         0.22414386804185735f,
        -0.12940952255092145f
    };
    const int kernelInvHighLen = 4;
    const int kernelInvHighAnchor = 0;
    const float kernelInvHigh[kernelInvHighLen] = 
    {
        -0.12940952255092145f,
        -0.22414386804185735f,
         0.83651630373746900f,
        -0.48296291314469025f
    };

    const int borderSize = 3; // Max size of all borders
    // Larger than needed for transform results, but is fine

    const int srcWidth = 8;
    const int srcHeight = 6;
    const float pSrc[srcWidth * srcHeight] = 
    {
        11, 12, 13, 14, 15, 16, 17, 18,
        21, 22, 23, 24, 25, 26, 27, 28,
        31, 32, 33, 34, 35, 36, 37, 38,
        41, 42, 43, 44, 45, 46, 47, 48,
        51, 52, 53, 54, 55, 56, 57, 58,
        61, 62, 63, 64, 65, 66, 67, 68
    };
    const int srcStep = sizeof( float ) * srcWidth;
    const IppiSize srcSize = { srcWidth, srcHeight };

    const int srcBorderedWidth  = srcWidth  + borderSize * 2;
    const int srcBorderedHeight = srcHeight + borderSize * 2;
    float pSrcBordered[srcBorderedWidth * srcBorderedHeight];
    const int srcBorderedStep = sizeof( float ) * srcBorderedWidth;
    const IppiSize srcBorderedSize = { srcBorderedWidth, srcBorderedHeight };
    ippiCopyMirrorBorder_32f_C1R( pSrc, srcStep, srcSize, pSrcBordered, 
        srcBorderedStep, srcBorderedSize, borderSize, borderSize );

    int specSize = 0;
    int bufferSize = 0;
    ippiWTFwdGetSize_32f( 1, kernelFwdLowLen, kernelFwdLowAnchor, 
        kernelFwdHighLen, kernelFwdHighAnchor, &specSize, &bufferSize );
    IppiWTFwdSpec_32f_C1R* pSpecFwd = 
        (IppiWTFwdSpec_32f_C1R*)ippMalloc( specSize );
    unsigned char* pBufferFwd = ippsMalloc_8u( bufferSize );
    ippiWTFwdInit_32f_C1R( pSpecFwd, kernelFwdLow, kernelFwdLowLen, 
        kernelFwdLowAnchor, kernelFwdHigh, kernelFwdHighLen, 
        kernelFwdHighAnchor );
    const int width  = srcWidth  / 2;
    const int height = srcHeight / 2;
    float pApprox[width * height];
    const int approxStep = sizeof( float ) * width;
    float pHdetail[width * height];
    const int HdetailStep = sizeof( float ) * width;
    float pVdetail[width * height];
    const int VdetailStep = sizeof( float ) * width;
    float pDdetail[width * height];
    const int DdetailStep = sizeof( float ) * width;
    const IppiSize size = { width, height };
    ippiWTFwd_32f_C1R( pSrcBordered + borderSize * srcBorderedWidth + 
        borderSize, srcBorderedStep, pApprox, approxStep, pHdetail, 
        HdetailStep, pVdetail, VdetailStep, pDdetail, DdetailStep, size, 
        pSpecFwd, pBufferFwd );

    const int borderedWidth  = width  + borderSize * 2;
    const int borderedHeight = height + borderSize * 2;
    const IppiSize borderedSize = { borderedWidth, borderedHeight };
    float pApproxBordered[borderedWidth * borderedHeight];
    const int approxBorderedStep = sizeof( float ) * borderedWidth;
    ippiCopyMirrorBorder_32f_C1R( pApprox, approxStep, size, pApproxBordered, 
        approxBorderedStep, borderedSize, borderSize, borderSize );
    float pHdetailBordered[borderedWidth * borderedHeight];
    const int HdetailBorderedStep = sizeof( float ) * borderedWidth;
    ippiCopyMirrorBorder_32f_C1R( pHdetail, HdetailStep, size, 
        pHdetailBordered, HdetailBorderedStep, borderedSize, borderSize, 
        borderSize );
    float pVdetailBordered[borderedWidth * borderedHeight];
    const int VdetailBorderedStep = sizeof( float ) * borderedWidth;
    ippiCopyMirrorBorder_32f_C1R( pVdetail, VdetailStep, size, 
        pVdetailBordered, VdetailBorderedStep, borderedSize, borderSize, 
        borderSize );
    float pDdetailBordered[borderedWidth * borderedHeight];
    const int DdetailBorderedStep = sizeof( float ) * borderedWidth;
    ippiCopyMirrorBorder_32f_C1R( pDdetail, DdetailStep, size, 
        pDdetailBordered, DdetailBorderedStep, borderedSize, borderSize, 
        borderSize );

    specSize = 0;
    bufferSize = 0;
    ippiWTInvGetSize_32f( 1, kernelInvLowLen, kernelInvLowAnchor, 
        kernelInvHighLen, kernelInvHighAnchor, &specSize, &bufferSize );
    IppiWTInvSpec_32f_C1R* pSpecInv = 
        (IppiWTInvSpec_32f_C1R*)ippMalloc( specSize );
    unsigned char* pBufferInv = ippsMalloc_8u( bufferSize );
    ippiWTInvInit_32f_C1R( pSpecInv, kernelInvLow, kernelInvLowLen, 
        kernelInvLowAnchor, kernelInvHigh, kernelInvHighLen, 
        kernelInvHighAnchor );
    float pReconstructed[srcWidth * srcHeight];
    const int reconstructedStep = sizeof( float ) * srcWidth;
    ippiWTInv_32f_C1R( pApproxBordered + borderSize * borderedWidth + 
        borderSize, approxBorderedStep, pHdetailBordered + borderSize * 
        borderedWidth + borderSize, HdetailBorderedStep, pVdetailBordered + 
        borderSize * borderedWidth + borderSize, VdetailBorderedStep, 
        pDdetailBordered + borderSize * borderedWidth + borderSize, 
        DdetailBorderedStep, size, pReconstructed, reconstructedStep, pSpecInv, 
        pBufferInv );
    // Perfect reconstruction, except for first two rows and columns

    ippsFree( pBufferInv );
    ippFree( pSpecInv );
    ippsFree( pBufferFwd );
    ippFree( pSpecFwd );

    return 0;
}

 

0 Kudos
2 Replies
Ben_Ochoa
Beginner
332 Views

Actually, using ippiCopyWrapBorder is the only image extension method that *does* result in a perfect reconstruction.  I did not try this one before because there is only a 1 channel version of the ippiCopyWrapBorder function.

1. Please correct me if I am mistaken, but I thought that as long as the image extension method was consistent, then the result is a perfect reconstruction.

2. Feature request: please add the following ippiCopyWrapBorder functions to IPP, such that it is consistent with ippiCopyReplicateBorder, ippiCopyMirrorBorder, and ippiCopyConstBorder.

ippiCopyWrapBorder_8u_C1R
ippiCopyWrapBorder_8u_C3R
ippiCopyWrapBorder_8u_AC4R
ippiCopyWrapBorder_8u_C4R
ippiCopyWrapBorder_16s_C1R
ippiCopyWrapBorder_16s_C3R
ippiCopyWrapBorder_16s_AC4R
ippiCopyWrapBorder_16s_C4R
ippiCopyWrapBorder_16u_C1R
ippiCopyWrapBorder_16u_C3R
ippiCopyWrapBorder_16u_AC4R
ippiCopyWrapBorder_16u_C4R
ippiCopyWrapBorder_32s_C3R
ippiCopyWrapBorder_32s_AC4R
ippiCopyWrapBorder_32s_C4R
ippiCopyWrapBorder_32f_C3R
ippiCopyWrapBorder_32f_AC4R
ippiCopyWrapBorder_32f_C4R
ippiCopyWrapBorder_8u_C1IR
ippiCopyWrapBorder_8u_C3IR
ippiCopyWrapBorder_8u_AC4IR
ippiCopyWrapBorder_8u_C4IR
ippiCopyWrapBorder_16s_C1IR
ippiCopyWrapBorder_16s_C3IR
ippiCopyWrapBorder_16s_AC4IR
ippiCopyWrapBorder_16s_C4IR
ippiCopyWrapBorder_32s_C3IR
ippiCopyWrapBorder_32s_AC4IR
ippiCopyWrapBorder_32s_C4IR
ippiCopyWrapBorder_16u_C1IR
ippiCopyWrapBorder_16u_C3IR
ippiCopyWrapBorder_16u_AC4IR
ippiCopyWrapBorder_16u_C4IR
ippiCopyWrapBorder_32f_C3IR
ippiCopyWrapBorder_32f_AC4IR
ippiCopyWrapBorder_32f_C4IR

0 Kudos
Abhinav_S_Intel
Moderator
332 Views

As you have already opened a support ticket on the same issue. Let's address your questions on the online support center.

0 Kudos
Reply