是opencv中的任何函数,相当于matlab conv2

ara*_*nga 4 matlab opencv image-processing convolution

matlab函数conv2有没有直接的opencv函数?我尝试使用cvFilter2D(),但它似乎给我不同于conv2()的结果.

例如:

CvMat * Aa = cvCreateMat(2, 2, CV_32FC1);
CvMat * Bb = cvCreateMat(2, 2, CV_32FC1);
CvMat * Cc = cvCreateMat(2, 2, CV_32FC1);
cvSetReal2D(Aa, 0, 0, 1);
cvSetReal2D(Aa, 0, 1, 2);
cvSetReal2D(Aa, 1, 0, 3);
cvSetReal2D(Aa, 1, 1, 4);
cvSetReal2D(Bb, 0, 0, 5);
cvSetReal2D(Bb, 0, 1, 5);
cvSetReal2D(Bb, 1, 0, 5);
cvSetReal2D(Bb, 1, 1, 5);
cvFilter2D(Aa, Cc, Bb);

This produces the matrix [20 30; 40 50]


In MATLAB:
>> A=[1 2; 3 4]
A =
1 2
3 4

>> B=[5 5; 5 5]
B =
5 5
5 5

>> conv2(A,B,'shape')
ans =
50 30
35 20
Run Code Online (Sandbox Code Playgroud)

请帮帮我.对我非常有用.谢谢.

问候

Arangarajan.

fre*_*015 8

数值计算环境Matlab(或例如其自由替代GNU Octave)提供了一个称为conv2的函数,用于给定矩阵与卷积核的二维卷积.在编写基于免费图像处理库OpenCV的一些C++代码时,我发现OpenCV目前没有提供等效的方法.

虽然有一个filter2D()方法可以实现二维相关,并且可以用于使用给定内核卷积图像(通过翻转该内核并将锚点移动到正确的位置,如相应的OpenCV文档页面所述) ),有一种方法提供与Matlab("完整","有效"或"相同"卷积)相同的边界处理选项,例如用于比较使用OpenCV在Matlab和C++中实现的相同算法的结果,这将是很好的.

这是我想出的:

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));
  }

  Point anchor(kernel.cols - kernel.cols/2 - 1, kernel.rows - kernel.rows/2 - 1);
  int borderMode = BORDER_CONSTANT;
  filter2D(source, dest, img.depth(), flip(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);
  }
}
Run Code Online (Sandbox Code Playgroud)

在我的单元测试中,这个实现产生的结果几乎与Matlab实现相同.请注意,如果内核足够大,OpenCV和Matlab都会在傅立叶空间中进行卷积."大"的定义在两种实现中都有所不同,但结果应该仍然非常相似,即使对于大型内核也是如此.

此外,此方法的性能可能是"完整"卷积情况的问题,因为需要复制整个源矩阵以在其周围添加边框.最后,如果在filter2D()调用中收到异常并且您使用的内核只有一列,则可能是由此错误引起的.在这种情况下,请将borderMode变量设置为例如BORDER_REPLICATE,或者使用OpenCV主干中的最新版本的库.


sie*_*hie 5

如果使用卷积,则矩阵边缘存在问题.卷积掩模需要在矩阵之外的值.OpenCV和matlab的算法使用不同的策略来解决这个问题.OpenCV只复制边框的像素,而matlab只假设所有这些像素都为零.

因此,如果要在OpenCV中模拟matlab的行为,可以手动添加此零填充.甚至还有专门的功能.让我举一个例子来说明如何修改代码:

CvMat * Ccb = cvCreateMat(3, 3, CV_32FC1);
CvMat * Aab = cvCreateMat(3, 3, CV_32FC1);
cvCopyMakeBorder(Aa,Aab, cvPoint(0,0),IPL_BORDER_CONSTANT, cvScalarAll(0));
cvFilter2D(Aab, Ccb, Bb);
Run Code Online (Sandbox Code Playgroud)

结果是:

20.000   30.000   20.000 
40.000   50.000   30.000 
30.000   35.000   20.000 
Run Code Online (Sandbox Code Playgroud)

要获得预期的结果,您只需删除第一列和第一行即可删除我们添加的边框引入的其他数据.

  • +1请记住,函数`cvFilter2D`执行相关,而`conv2`执行卷积.对于上面的示例,这无关紧要,但如果内核不对称,则需要将其旋转180度才能使结果匹配. (4认同)