cnn下matlab移植opencv体会

在从matlab转opencv的代码移植中,主要关注(x,y)的索引、矩阵相乘、函数计算的差异、是否需要flip等。

(1)针对(x,y)的索引中

          在matlab中,M(x,y)表示的行为x,列为y,即x对应左边索引的值,y对应上边索引的值,即如下:

a =


     1     2
     3     4


>> a(2,1)


ans =


     3

          在opencv中,Mat型矩阵,M(x,y)表示的rows索引(行)为x,cols索引(列)为y,即x对应左边索引的值,y对应上边索引的值,即如下:



   matlab与opencv的坐标索引不同之处在前者是从1开始索引,而后者是从0开始索引的。


(2)矩阵相乘

在matlab中,矩阵相乘(不是点乘)是直接进行的,c = a * b;

在opencv中,两个Mat型矩阵相乘,其方式与matlab的方式是一样的,c = a * b;

也就是二者对应的矩阵的值是保存一致的,不存在需要什么倒置等行为(除非涉及到内置函数中可能存在的不同)。


(3)卷积操作

在matlab中,卷积操作可通过函数convn来完成(或conv2来完成);

在opencv中,与matlab对应的函数是filter2D,但此时要注意,直接调用filter2D会产生和matlab中convn不一样的结果。当 将matlab中convn函数转成opencv实现时,应加处理,例子如下:

Point anchor(m_vecKernel[i].cols - m_vecKernel[i].cols / 2 - 1, m_vecKernel[i].rows - m_vecKernel[i].rows / 2 - 1);
int borderMode = BORDER_REPLICATE;
flip(m_vecKernel[i], m_vecKernel[i], -1);
filter2D(m_im1, c, m_im1.depth(), m_vecKernel[i], anchor, 0, borderMode);
c = c.colRange((m_vecKernel[i].cols - 1) / 2, c.cols - m_vecKernel[i].cols / 2)
.rowRange((m_vecKernel[i].rows - 1) / 2, c.rows - m_vecKernel[i].rows / 2);
m_vecConvMap[i] = c;


参考如下网站:http://blog.timmlinder.com/2011/07/opencv-equivalent-to-matlabs-conv2-function/

内容如下:

OpenCV: Equivalent to Matlab’s conv2() function

The numerical computing environment Matlab (or e.g. its free alternative GNU Octave) provides a function called conv2for the two-dimensional convolution of a given matrix with a convolution kernel. While writing some C++ code based upon the free image processing library OpenCV, I found that OpenCV currently offers no equivalent method.

Although there is a filter2D() method that implements two-dimensional correlation and that can be used to convolute an image with a given kernel (by flipping that kernel and moving the anchor point to the correct position, as explained on the corresponding OpenCV documentation page), it would be nice to have a method offering the same border handling options as Matlab (“full”, “valid” or “same” convolution), e.g. for comparing results of the same algorithm implemented in both Matlab and C++ using OpenCV.

Here is what I came up with:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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);
   }
}

In my unit tests, this implementation yielded results that were almost identical with the Matlab implementation. Note that both OpenCV and Matlab do the convolution in Fourier space if the kernel is large enough. The definition of ‘large’ varies in both implementations, but results should still be very similar, even for large kernels.

Also, the performance of this method might be an issue for the ‘full’ convolution case, since the entire source matrix needs to be copied to add a border around it. Finally, If you receive an exception in the filter2D() call and you are using a kernel with only one column, this might be caused by this bug. In that case, set the borderMode variable to e.g.BORDER_REPLICATE instead, or use the latest version of the library from the OpenCV trunk.



(4)函数计算差异

如(3)所知,两个都是卷积操作,但结果会有所不同,需要做处理才行,得引起注意。


(5)数值类型注意

针对matlab中进行处理的数值类型,如float、double、int型等,在opencv中处理时,要引起注意,最好保持一致,同时opencv中数值类型之间转换时可能出错,要引起注意,比如一个错误如下:

int a[] = { 1, 2, 3, 4 };
Mat a1 = Mat(2, 2, CV_32FC1, a);
cout << a1 << endl;
cout << a1.at<float>(1, 0);

       上面想将一个int型数据a赋给浮点型数据a1,结果是未知数:

[1.4012985e-045    2.8...e-045

4.2..........e-45     5.6......e-45]

       需要这样表示才行:

float a[] = { 1, 2, 3, 4 };
Mat a1 = Mat(2, 2, CV_32FC1, a);
cout << a1 << endl;
cout << a1.at<float>(1, 0);

       即将a表示为浮点型float。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值