【问题标题】:Error during convolution of image with a filter in opencv c++在opencv c ++中使用过滤器卷积图像时出错
【发布时间】:2013-11-28 20:40:57
【问题描述】:

我是 opencv c++ 的新手。我收到卷积代码错误(来自互联网),相当于 matlab 中的 conv2。问题是所有像素值都变为 255。我在代码中使用的过滤器与图像大小相同。谁能帮我纠正这个问题。我的opencv c++代码如下:

     #include<opencv2/highgui/highgui.hpp>
     #include <opencv2/imgproc/imgproc.hpp>
     #include<stdio.h>
     #include<iostream>
     #include<math.h>
     #include<cv.hpp>
     using namespace cv;
     using namespace std;
     Mat gd,img,bimgFiltered,gimgFiltered,rimgFiltered,fin_img;
     Mat b,g,r,cr,cb,cg,B,G,R;
     Mat b_logplane, b_plane,b_logfiltered,b_log,g_logplane,g_plane,g_logfiltered;
     Mat g_log,r_logplane,r_plane,r_logfiltered,r_log;
     Mat kernel, dest;
     int m,n,m1,m2,n1,n2;
     int c = 120;
     double mysum = 0.0, mysum1 = 0.0, k = 0;
     int cent=0,radius=0;
     enum ConvolutionType {   
     /* Return the full convolution, including border */
     CONVOLUTION_FULL, 
     /* Return only the part that corresponds to the original image */
     CONVOLUTION_SAME,
     /* Return only the submatrix containing elements that were not influenced   
     by the border     
     */
      CONVOLUTION_VALID
     };

    void conv2(const Mat &img, const Mat& kernel, ConvolutionType type,Mat& dest)
    {
    Mat source = img;
    if(CONVOLUTION_FULL == type) 
    {
    source = Mat();
    const int additionalRows = kernel.rows - 1, additionalCols = kernel.cols - 1;
    copyMakeBorder(img, source, (additionalRows + 1) / 2, additionalRows / 2, 
        (additionalCols + 1) / 2, additionalCols / 2, BORDER_CONSTANT, Scalar(0));
    }

    flip(kernel, kernel, -1);
    Point anchor(kernel.cols - kernel.cols / 2 - 1, kernel.rows - kernel.rows / 2 - 1);
    int borderMode = BORDER_CONSTANT;
    filter2D(source, dest, img.depth(), kernel, anchor, 0, borderMode);

    if(CONVOLUTION_VALID == type)
    {
    dest = dest.colRange((kernel.cols - 1) / 2, dest.cols - kernel.cols /    
    2).rowRange((kernel.rows - 1) / 2, dest.rows - kernel.rows / 2);
    }
    }

    int main()
    {  
    img = imread("milla.bmp",  CV_LOAD_IMAGE_COLOR);   
    b.create(img.size(),img.type());
    g.create(img.size(),img.type());
    r.create(img.size(),img.type());

    cr.create(img.size(),img.type());
    cg.create(img.size(),img.type());
    cb.create(img.size(),img.type());

    Mat planes[3];
    split(img,planes);

    bimgFiltered.create(img.size(),img.type());
    gimgFiltered.create(img.size(),img.type());
    rimgFiltered.create(img.size(),img.type());

    dest.create(img.size(), img.type());
    gd.create(img.size(), img.type());

    for(int j = 0; j < img.rows; j++)
    {
    for(int i = 0; i < img.cols; i++)
    {
        radius = ((cent - i)^2 + (cent - j)^2);
        gd.at<float>(j, i) = exp((-(radius) / c^2));

        mysum = mysum + gd.at<float>(j, i);
    }
    mysum1 = mysum1 + mysum; 
    }

      k=1/mysum1;
     cout<<endl<<k<<"\n"<<endl;

     for(int j = 0; j < img.rows; j++)
     {
       for(int i = 0; i < img.cols; i++)
       {
        gd.at<float>(j, i) = k * gd.at<float>(j, i);
        }
      } 

     planes[0].convertTo(planes[0],CV_32F,1.0/255.0);
     planes[1].convertTo(planes[1],CV_32F,1.0/255.0);
     planes[2].convertTo(planes[2],CV_32F,1.0/255.0);
     conv2(planes[0],gd,CONVOLUTION_SAME,bimgFiltered);
     conv2(planes[1],gd,CONVOLUTION_SAME,gimgFiltered);
     conv2(planes[2],gd,CONVOLUTION_SAME,rimgFiltered);

     imshow("img",gimgFiltered );
     waitKey(0);
     return 0;
     }

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    代码有几个问题:

    问题 1:

    以下两行:

    radius = ((cent - i)^2 + (cent - j)^2);
    gd.at<float>(j, i) = exp((-(radius) / c^2));
    

    您正在使用 ^ 运算符,它是 C/C++ 中的按位 XOR 运算符。我认为您将其误认为是电力运营商。要获取数字的幂,您必须使用 pow 函数,如下所示:

    radius = powf((cent - i),2) + powf((cent - j),2);
    gd.at<float>(j, i) = expf((-(radius) / (c*c)));
    

    问题 2:

    gd 矩阵被假定为具有浮点值,因为它像gd.at&lt;float&gt;(j, i) 一样被访问,但它被声明为与图像相同的类型,即CV_8UC3。所以gd的创建方式如下:

    gd.create(img.size(), CV_32FC1);
    

    问题 3:

    第一个嵌套循环中可能存在另一个可能的逻辑错误。您可能必须在启动内部循环之前设置mysum = 0;,如下所示:

    for(int j = 0; j < img.rows; j++)
    {
        mysum = 0;
        for(int i = 0; i < img.cols; i++)
        {
            radius = powf((cent - i),2) + powf((cent - j),2);
            gd.at<float>(j, i) = expf((-(radius) / (c*c)));
    
            mysum = mysum + gd.at<float>(j, i);
        }
        mysum1 = mysum1 + mysum; 
    }
    

    问题 4:

    输出过滤图像应创建单通道而不是 3 通道:

    bimgFiltered.create(img.size(),CV_8UC1);
    gimgFiltered.create(img.size(),CV_8UC1);
    rimgFiltered.create(img.size(),CV_8UC1);
    

    【讨论】:

    • 先生,感谢您的回复。我尝试了所有这些更正。我仍然没有得到正确的卷积输出。我得到的是黑色图像。这是等效的 matlab 代码。这是因为我在转换为 opencv c++ 时出现了一些问题。 Ir=I(:,:,1); Ig=I(:,:,2); Ib=I(:,:,3);美分 = ceil(a/2); gd = 零(a,b);总和=0;对于 i=1:a 对于 j=1:b 半径 = ((cent-i)^2+(cent-j)^2); gd(i,j) = exp(-(半径/(c^2)));结束 结束 k=1/(sum(sum(gd))) F=k .* gd; F_FIr=conv2(Ir,F,'same'); F_FIg=conv2(F,Ig,'相同'); F_FIb=conv2(F,Ib,'相同');
    • @user2943871... 你期待什么输出?您可以发布来自 matlab 代码的示例输入和输出图像吗?
    • 对不起,先生。
    • 我没有 10 个声望来发布图片。我期待任何输入图像的浅灰色平面图像,但我得到的是全黑图像。
    • @user2943871.. 目前,您可以在 imageshack 等图片托管网站上上传图片,并提供链接。
    猜你喜欢
    • 2020-05-26
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 2019-02-26
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    相关资源
    最近更新 更多