您的位置:首页 > 编程语言 > MATLAB

canny边缘提取之二 高斯图像滤波(将matlab的imfilter函数转换为C++函数)

2015-05-13 11:05 645 查看
matlab格式详解:

1.函数模板

 B=imfilter(A,H,options);

(a)   -Boundary
options

%

%      X           
Input array values outside thebounds of the array

%                   are implicitly assumed tohave the value X. 
When no

%                   boundary option isspecified, IMFILTER uses X = 0.

%

%      'symmetric' 
Input array values outside the bounds of thearray

%                   are computed bymirror-reflecting the array across

%                   the array border.

%

%      'replicate' 
Input array values outside the bounds of thearray

%                   are assumed to equal thenearest array border

%                   value.(图片边界处像素的计算,采用将边界向外延长n=((size(H,1)+1)/2-1)个像素,延长的像素值为对应边界像素值。)

%

%      'circular'  
Input array values outside the bounds of thearray

%                   are computed by implicitlyassuming the input array

%                   is periodic.

(b) Output size options

%    (Output size options for IMFILTER areanalogous to the SHAPE option

%    in the functions CONV2 and FILTER2.)

%

%      'same'      
The output array is the same size as theinput

%                   array. 
This is the default behavior when no output

%                   size options are specified.

%

%      'full'      
The output array is the full filteredresult, and so

%                   is larger than the inputarray.

%

c) Correlation and convolution

%

%      'corr'      
IMFILTER performs multidimensional filteringusing

%                   correlation, which is thesame way that FILTER2

%                   performs filtering. 
When no correlation or

%                   convolution option isspecified, IMFILTER uses

%                   correlation.(滤波模板H不发生变换,直接进行模板计算)

%

%      'conv'      
IMFILTER performs multidimensionalfiltering using

%                   convolution.
(滤波模板H发生180度旋转(先行转置,后列转置),之后进行模板计算)

 

%

‘Conv’详解:卷积窗为,180度旋转后==》

 

2.滤波/卷积过程

线性滤波可以用卷积实现,输出图像的像素值是输入图像对应像素及其邻域像素的线性加权,权重矩阵称为卷积窗。图20.56说明了图像卷积的过程,图像I为,卷积窗为。现在要计算像素点(2,4)卷积后的结果,卷积过程如下:

(1)将卷积窗相对于中心旋转180度,得;

(2)将卷积窗的中心滑动至(2,4);

(3)计算(2,4)的邻域与卷积窗对应像素的积,并求和,结果即为卷积后(2,4)处的像素值。

因此(2,4)的卷积结果为1´2 + 8´9+ 15´4 + 7´7 + 5´14 + 16´3 + 6´13 + 1´20 +8´22
= 575。

卷积窗滑动过程中有可能超出图像的边界,如图20.57所示。对于图像边界外的像素值,一般有两种方法处理,其一是用0填充(图20.58),其二是用最邻近的边界值填充(图20.59)。

       

图20.56 图像卷积过程                      图20.57 图像卷积越界

            

图20.58 卷积过程的边界处理,0填充         图20.59 卷积过程的边界处理,邻域填充

相关与卷积类似,输出图像的像素值是输入图像对应像素及其邻域的线性加权,权重矩阵称为相关窗。相关与卷积的唯一差别是,不需要对相关窗口旋转。图像相关也需要考虑到边界的处理,处理方式与卷积相同。

 

3.注意事项,

当前处理像素f(i,j)在卷积窗口的对应位置为,i=size(H,1)+1/2;j=size(H,2)+1/2;

即,(a)当H尺寸为7*1时,i=(7+1)/2=4;(该值对应matlab时=4;对应C时=3)

    (b)当H尺寸为6*1时,i=(6+1)/2=3;(该值对应matlab时=3;对应C时=2)

 

H=[h1,h2,h3,h4,h5,h6,h7]; F(i)=f(i-3)*h1+ f(i-2)*h2+f(i-1)*h3+ f(i)*h4+f(i+1)*h5+ f(i+2)*h6+f(i+3)*f7;

H=[h1,h2,h3,h4,h5,h6]; F(i)= f(i-2)*h1+f(i-1)*h2+ f(i)*h3+ f(i+1)*h4+f(i+2)*h5+f(i+3)*f6;

C++转换:

 //matlab_canny.h

//将matlab中的edge(I,'canny')函数转换为C++代码
class matlab_canny{
public:
struct canny_data{
int height;
int width;
float* data;
};
//对图像src进行水平方向/垂直方向的滤波 ,仅对一个方向进行卷积
//src --- 原始图像
//filter -- 滤波后图像
//H -- 卷积窗口
//其中相对于matlab中的imfilter来说,对应的option为'corr'+'replicate'

void matlab_imfilter(canny_data* src, canny_data* filter, canny_data* H);
};

//matlab_canny.cpp

#include"canny_matlab.h"

void matlab_canny::matlab_imfilter(canny_data* src, canny_data* filter, canny_data* H)
{
int height, width, h_h_1, h_h_2, h_w_1, h_w_2;
float sum_data, src_data;
height = src->height;
width = src->width;
int direction = 0;//进行水平和垂直方向卷积 direction-卷积方向:0--水平+垂直;1--水平; 2--垂直
if (H->height == 0 && H->width == 0)
{
printf("ERROR:卷积窗口H大小为0!");
}
if (H->height == 0)
{
h_h_1 = 0;
h_h_2 = 0;
direction = 1;//进行水平方向卷积
}
else
{
h_h_1 = (H->height - 1) / 2;
h_h_2 = H->height - h_h_1;
h_h_1 = -h_h_1;
}
if (H->width == 0)
{
h_w_1 = 0;
h_w_2 = 0;

direction = 2;//进行
b2b9
垂直方向卷积
}
else
{
h_w_1 = (H->width - 1) / 2;
h_w_2 = H->width - h_w_1;
h_w_1 = -h_w_1;
}

for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
sum_data = 0;
switch (direction)
{
case 0://水平卷积+垂直卷积
for (int h_h = h_h_1; h_h < h_h_2; h_h++)
{
for (int h_w = h_w_1; h_w < h_w_2; h_w++)
{
if ((i + h_h >= 0 && i + h_h < height) || (j + h_w >= 0 && j + h_w < width))//待处理的像素的行或者列在边界内,或者行和列都在边界内
{
//对于边界的处理,按照replicate规则,即延长边界像素值=边界像素值
if (i + h_h < 0)
src_data = src->data[0 * width + j];
else if (i + h_h >= height)
src_data = src->data[(height - 1) * width + j];
else if (j + h_w < 0)
src_data = src->data[i * width + 0];
else if (j + h_w >= width)
src_data = src->data[i * width + width - 1];
else
src_data = src->data[(i + h_h) * width + (j + h_w)];
}
else//待处理的像素的行和列都不在边界内
{

}
sum_data = sum_data + src_data * H->data[(h_h - h_h_1) * H->width + (h_w - h_w_1)];

}
}
case 1 ://水平卷积
for (int h_w = h_w_1; h_w < h_w_2; h_w++)
{
if (j + h_w < 0)
src_data = src->data[i * width + 0];
else if (j + h_w >= width)
src_data = src->data[i * width + width - 1];
else
src_data = src->data[i * width + (j + h_w)];

sum_data = sum_data + src_data * H->data[(h_w - h_w_1)];
}
break;
case 2://垂直卷积
for (int h_h = h_h_1; h_h < h_h_2; h_h++)
{
if (i + h_h < 0)
src_data = src->data[0 * width + j];
else if (i + h_h >= height)
src_data = src->data[(height - 1) * width + j];
else
src_data = src->data[(i + h_h) * width + j];

sum_data = sum_data + src_data * H->data[(h_h - h_h_1)];
}

}

filter->data[i * width + j] = sum_data;
}
}

}

实例:
int main()
{
matlab_canny::canny_data src, fff, HH;
matlab_canny m_canny;
float data[10 * 10];
float H[4] = { -2, -1, 4, 3 };
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
data[i * 10 + j] = i+1;
}
}
float filter[10 * 10];

src.height = 10;
src.width = 10;
src.data = data;
fff.height = 10;
fff.width = 10;
fff.data = filter;
HH.height = 0;
HH.width = 4;
HH.data = H;

m_canny.matlab_imfilter(&src, &fff, &HH);
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
printf("%f ", fff.data[i * 10 + j]);
}
printf("\n");
}

 

 

 


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: