在项目中遇到的matlab代码中的图像滤波函数,需要在opencv中去实现。关于怎么去转换,我主要参考的如下两篇 :
(1)https://blog.csdn.net/hust_sheng/article/details/79313503
(2)https://www.cnblogs.com/jsxyhelu/p/6597544.html
首先,关于matlab中imfilter函数的使用,主要涉及了两个概念:相关和卷积,实现方式有不同。下面简单附录一下:
函数名称:imfilter
函数语法:g=imfilter(f,w,filtering_mode,boundary_options,size_optinos)
函数功能:对任意类型数组或多维图像进行滤波
参数介绍:f是输入图像,w为滤波模板,g为滤波结果;表1-1总结了其他参数的含义。
opencv中对应的函数是filter2D,在第1篇参考里,讲述了关于一维情况下对应关系。
(一)一维情况下的滤波对应关系
因为我针对的是2维图像的滤波,所以暂时用不到一维,但是也附录一下,以备后用。
matlab:
kernel:[-1, 1, 0]
div_p_1 = imfilter(p(:, :, 1), [-1, 1, 0], 'corr', 0);
div_p_2 = imfilter(p(:, :, 2), [-1, 1, 0]', 'corr', 0)
Opencv:
float kernel_div[3] = {-1, 1, 0};
int ddepth = -1; // 默认值,-1表示和原图像一样的深度
Point anchor_center(-1, -1); // 十分关键!决定了滤波的边界处理形式!
Mat kerdiv_1 = Mat(1, 3, CV_32FC1, &kernel_div); // 水平kernel
Mat kerdiv_2 = Mat(3, 1, CV_32FC1, &kernel_div); // 垂直kernel
Mat div_p_1, div_p_2;
filter2D(p_channels.at(0), div_p_1, ddepth, kerdiv_1, anchor_center, 0, BORDER_CONSTANT);
filter2D(p_channels.at(1), div_p_2, ddepth, kerdiv_2, anchor_center, 0, BORDER_CONSTANT)
两者的结果一致,表明matlab的full或same模式对应于用opencv中的ancher调整。
matlab:
kernel:[-1, 1]
I_x = imfilter(I, [-1, 1], 'replicate');
I_y = imfilter(I, [-1, 1]', 'replicate')
Opencv:
int ddepth = -1;
Point anchor(0, 0);
float kernel_img[2] = {-1, 1};
Mat kerimg_1 = Mat(1, 2, CV_32FC1, &kernel_img);
Mat kerimg_2 = Mat(2, 1, CV_32FC1, &kernel_img);
Mat I_x, I_y;
filter2D(images_graystyle_tmp[imgNo]+ktheta*div_p, I_x, ddepth, kerimg_1, anchor, 0, BORDER_REPLICATE);
filter2D(images_graystyle_tmp[imgNo]+ktheta*div_p, I_y, ddepth, kerimg_2, anchor, 0, BORDER_REPLICATE)
BORDER_REPLICATE
边缘扩充模式,filter2D和imfilter是一样的的,需要注意的是opencv的anchor是:Point anchor(0, 0)
(二)针对二维图像进行滤波操作
首先,在matlab中进行测试,代码如下:
%测试比较matlab函数imfilter与opencv函数filter2D的区别
clc,clear all,close all;
img = im2double(imread('C:\image_fcq\C180806143231.jpg'));
kernel =[2.0,-1.0,3.0;2.0,-4.0,5.0];
rst = imfilter(img,kernel);
在opencv中正确的对应关系如下:
string imgName="C://image_fcq//C180806143231.jpg"
const int rows = 2, cols = 3;
float RawData1[rows][cols] = { { 2.0,-1.0,3.0 },{ 2.0,-4.0,5.0 } };
Mat RawDataMat1(2, 3, CV_32F, RawData1);
Mat img = imread(imgName,0);
img.convertTo(img, CV_32F);
img = img / 255; //归一化处理
Mat dst;
filter2D(img, dst, img.depth(), RawDataMat1);
WriteDataFloat("C://image//lv.txt", dst); //将滤波结果写到lv.txt中
结果:两者的滤波结果出了在边界有区别外,其他位置基本一致,能取得很好地对应关系,需要注意的是,在opencv中需要将图像进行归一化操作。