Xilinx / xfopencv

Other
321 stars 144 forks source link

xf::boxFilter can't obtain same result with cv::boxFilter ? #36

Closed microlijun closed 5 years ago

microlijun commented 5 years ago

Hi, cv::boxFilter is used in my opencv application. I tried to migrate it to xfopencv, but the testbench can't pass. After print the output of xf::boxFilter and cv::boxFilter, the result is totally different. What's wrong? -------------------------------opencv-----------------------

cv::Mat N; cv::boxFilter(cv::Mat::ones(HEIGHT, WIDTH, I.type()), N, CV_8UC1, cv::Size(3, 3));

-------------------------------xfopencv---------------------

xf::Mat<XF_8UC1, HEIGHT, WIDTH, XF_NPPC1> M; for (int i = 0; i < HEIGHT; i++) for (int j = 0; j < WIDTH; j++) { M.data[i*WIDTH+j] = 1; } xf::boxFilter<XF_BORDER_CONSTANT,XF_FILTER_3X3,XF_8UC1,HEIGHT, WIDTH,XF_NPPC1>(M,N);

bgouthamb commented 5 years ago

Hello @microlijun ,

There will be 1-bit fixed point error. Considering that threshold, both the outputs should be matching. I just ran your case and it shows the same.

microlijun commented 5 years ago

Hello @microlijun ,

There will be 1-bit fixed point error. Considering that threshold, both the outputs should be matching. I just ran your case and it shows the same.

Hi bgouthamb, Thank for your help. But I'm still confused. How do I modify the xfopencv code?

bgouthamb commented 5 years ago

@microlijun, You can use the existing testbench file and modify it accordingly to test your case. xf::absDiff function can be used to compute the difference between opencv and xfopencv outputs.

Example:

cv::Mat ocv_ref, diff;
ocv_ref.create(HEIGHT,WIDTH,CV_8U); // create memory for output image
diff.create(HEIGHT,WIDTH,CV_8U); // create memory for output image

cv::boxFilter(cv::Mat::ones(HEIGHT, WIDTH, CV_8UC1),ocv_ref,CV_8UC1,cv::Size(3,3));
xf::Mat<IN_T, HEIGHT, WIDTH, NPIX> imgOutput;
xf::Mat<XF_8UC1, HEIGHT, WIDTH, XF_NPPC1> M;
for (int i = 0; i < HEIGHT; i++)
    for (int j = 0; j < WIDTH; j++)
    {
        M.data[i*WIDTH+j] = 1;
    }

xf::boxFilter<XF_BORDER_CONSTANT,FILTER_WIDTH,XF_8UC1,HEIGHT, WIDTH,XF_NPPC1>(M,imgOutput);  //call the kernel function

xf::absDiff(ocv_ref,imgOutput, diff);    // Compute absolute difference image

double minval=256,maxval=0;
int cnt = 0;
for (int i=0;i<HEIGHT;i++)
{
    for(int j=0;j<WIDTH;j++)
    {
        uchar v = diff.at<uchar>(i,j);
        if (v>1)
            cnt++;
        if (minval > v )
            minval = v;
        if (maxval < v)
            maxval = v;
    }
}
float err_per = 100.0*(float)cnt/(HEIGHT*WIDTH);
fprintf(stderr,"Minimum error in intensity = %f\nMaximum error in intensity = %f\nPercentage of pixels above error threshold = %f\n",minval,maxval,err_per);
microlijun commented 5 years ago

Hi, @bgouthamb By using this testbench, I did got Percentage of pixels above error threshold = 0.000000. However, if you print out ocv_ref and imgOutput , you can see there have a little difference between them. As shown bellow, ocv_ref: 1,1,1,1,......1 1,1,1,1,......1 ...... 1,1,1,1.......1 imgOutput: 0,0,0,0,......0 0,1,1,1,......0 0,1,1,1,......0 ... 0,0,0,0,......0

When I use a real image as input, the difference between ocv_ref and imgOutput is huge.

When I used the opencv function with full parameters, the result of cv::boxFilter(in_conv_img,ocv_ref,-1,cv::Size(3,3),cv::Point(-1,-1),true,cv::BORDER_CONSTANT); and xf::boxFilter<XF_BORDER_CONSTANT,FILTER_WIDTH,XF_8UC1,HEIGHT, WIDTH,XF_NPPC1>(imgInput,imgOutput); are matched.

What if I want get same result with cv::boxFilter(in_conv_img,ocv_ref,CV_8UC1,cv::Size(3,3)); How to set parameters of xf::boxFilter?

bgouthamb commented 5 years ago

The difference is at the borders, because of different border handling types. If you do not specify any value for the border type in cv::boxfilter, the default value BORDER_DEFAULT (which resolves to BORDER_RFLECT_101) will be used.

Currently, xf::boxfilter only supports BORDER_CONSTANT.