您的位置:首页 > 其它

图像处理之基础---二维卷积c实现

2014-08-31 00:00 477 查看
http://wenku.baidu.com/link?url=4RzdmvP9sdaaUbnVEW4OyBD-g67wIOiJjKFF3Le_bu7hIiBS7I6hMcDmCXrQwsHvrsPvR4666J1qF1ff5JVvd2xL8rzL9N81qvL-1dwkiim

特别说明一下,根据那本书所说,这算的是线性卷积。还有种卷积叫循环卷积。

(1)、二维卷积运算之C语言实现

若x为N1*M1的二维信号,y为N2*M2的二维信号,则卷积为(N1+N2-1)*(M1+M2-1)的信号

z(i,j)=∑ ∑ x(m,n)y(i

-m,j-n)

........m n

#define N1 8 信号1的行

#define M1 10 信号1的列

#define N2 2 信号2的行

#define M2 3 信号2的列

void juanji(int x[N1][M1],int y[N2][M2],int z[N1+N2-1][M1+M2-1])

{

int i,j;

int n,m;

for(i=0;i<N1+N2-1;i++)

for(j=0;j<M1+M2-1;j++)

{

int temp=0;

for(m=0;m<N1;m++)

for(n=0;n<M1;n++)

if((i-m)>=0&&(i-m)<N2&&(j-n)>=0&&(j-n)<M2)

temp+=x[m]
*y[i-m][j-n];

z[i][j]=temp;

}

}

http://www.netfoucs.com/article/linger2012liu/76164.html#

(2)、

看卷积神经网络的时候,发现代码中计算卷积是通过矩阵乘法来计算的。

搜了一下发现网上这方面的资料很少。刚开始找中文的,找到两个。

http://blog.csdn.net/anan1205/article/details/12313593

http://zhongcheng0519.blog.163.com/blog/static/161690688201122141335874/

看了之后,还是不懂。然后开始搜英文的。

最后搜到两个挺有用的,一个是维基百科对Toeplitz的介绍,一个是图像处理的书籍。
http://en.wikipedia.org/wiki/Toeplitz_matrix
Toeplitzmatrix

http://books.google.com.hk/books?id=JeDGn6Wmf1kC&pg=PA110&lpg=PA110&dq=2-D+convolution+as+a+matrix-matrix+multiplication&source=bl&ots=kdxpa_C-Ax&sig=afy2CMZHEkoV-7ymwcBFMwvRB8U&hl=zh-CN&sa=X&ei=wjVOU_jkEMypkgW09IDwCQ&ved=0CEEQ6AEwAg#v=onepage&q=2-D%20convolution%20as%20a%20matrix-matrix%20multiplication&f=false

下面拿一个例子来讲解一下,怎么把卷积运算转换为矩阵乘法运算。其实是那本书的一个例子。

X=[

1 2

3 4]

h= [

5 6

7 8]

其中,X是卷积核。

1 X的每一行生成一个小矩阵

第一行[1 2],

首先插入1,得[1 0],补的0的数量等于H的列数-1。这里,h的列数是2,故补2-1=1个0。

再右移一位插入2,得出第二行,得[10

2 1]

再右移一位得出第三行,得

[

1 0

2 1

0 2]。把这个等于H0。

第二行[3 4],同理得

H1=[

3 0

4 3

0 4]。

观察这个过程,明显是将上一行右移再插入新的值到第一个列从而得出下一行。

我们可以假设第0行是[0 0],最后一行是[0 0]。

[

0 0

3 0

4 3

0 4

0 0

]就可以看到规律。

2 算出Toeplitz矩阵

A= [

H0 O

H1 H0

O H1],其中O是一个由若干个0组成的小矩阵。

这个例子中,

A=

[

1 0 0 0

2 1 0 0

0 2 0 0

3 0 1 0

4 3 2 1

0 4 0 2

0 0 3 0

0 0 4 3

0 0 0 4

]

3 将h变为列向量,按照行的顺序来,得

[

5

6

7

8

]

4 将Toeplitz矩阵和列向量相乘,得

[

5

16

12

22

60

40

21

52

32

]

整理为矩阵得,

[

5 16 12

22 60 40

21 52 32

]。

下面来验证一下,

首先将卷积核旋转180度,得

[

4 3

2 1

]

从左上开始,滑动算点积,得

5*1= 5,

5*2+ 6*1 = 16,

6*2= 12,

5*3+7*1=22,

5*4+6*3+7*2+8*1=60,

。。。。。。

正确!!!

特别说明一下,根据那本书所说,这算的是线性卷积。还有种卷积叫循环卷积。

值得注意的是:

  第一种方法是根据定义来的,浙大、北大的教案都是这种方法,

  第二种是根据几何定义来求得

  其实有第三种方法:根据原理 多项式加权相乘求和,跟第二种类似

http://www.netfoucs.com/article/linger2012liu/76164.html#

(4)、

/article/1221447.html

// 计算卷积矩阵的函数
function ConvolutionMatrix(input, matrix, divisor, offset){
// 创建一个输出的 imageData 对象
var output = document.createElement("canvas")
.getContext('2d').createImageData(input);

var w = input.width, h = input.height;
var iD = input.data, oD = output.data;
var m = matrix;

// 对除了边缘的点之外的内部点的 RGB 进行操作,透明度在最后都设为 255
for (var y = 1; y < h-1; y += 1) {
for (var x = 1; x < w-1; x += 1) {
for (var c = 0; c < 3; c += 1) {
var i = (y*w + x)*4 + c;
oD[i] = offset
+(m[0]*iD[i-w*4-4] + m[1]*iD[i-w*4] + m[2]*iD[i-w*4+4]
+ m[3]*iD[i-4] + m[4]*iD[i] + m[5]*iD[i+4]
+ m[6]*iD[i+w*4-4] + m[7]*iD[i+w*4] + m[8]*iD[i+w*4+4])
/ divisor;
}
oD[(y*w + x)*4 + 3] = 255; // 设置透明度
}
}
return output;
}

(5)、

http://zhidao.baidu.com/question/50407836.html?fr=qrl&index=3&qbl=topic_question_3&word=%BE%D8%D5%F3%BE%ED%BB%FD

  code:

  

一个5*5的图像和一个3*3的图像做卷积运算,具体过程如下:
*
*   函数名称:
*       TemplateMatchDIB()
*
*   参数:
*       LPSTR   lpDIBBits         -   指向源DIB图像指针
*       LPSTR   lpDIBBitsBK     -   指向背景DIB图像指针
*       LONG     lWidth               -   源图像宽度(象素数)
*       LONG     lHeight             -   源图像高度(象素数)
*       LONG     lTemplateWidth               -   模板图像宽度(象素数)
*       LONG     lTemplateHeight             -   模板图像高度(象素数)
*
*   返回值:
*       BOOL                               -   运算成功返回TRUE,否则返回FALSE。
*
*   说明:
*   该函数用于对图像进行模板匹配运算。
*
*   要求目标图像为255个灰度值灰度图像。
************************************************************************/

BOOL   WINAPI   TemplateMatchDIB   (LPSTR   lpDIBBits,   LPSTR   lpTemplateDIBBits,   LONG   lWidth,   LONG   lHeight,
LONG   lTemplateWidth,LONG   lTemplateHeight)
{
//   指向源图像的指针
LPSTR lpSrc,lpTemplateSrc;

//   指向缓存图像的指针
LPSTR lpDst;

//   指向缓存DIB图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;

//循环变量
long   i;
long   j;
long   m;
long   n;

//中间结果
double   dSigmaST;
double   dSigmaS;
double   dSigmaT;

//相似性测度
double   R;

//最大相似性测度
double   MaxR;

//最大相似性出现位置
long   lMaxWidth;
long   lMaxHeight;

//像素值
unsigned   char   pixel;
unsigned   char   templatepixel;

//   图像每行的字节数
LONG   lLineBytes,lTemplateLineBytes;

//   暂时分配内存,以保存新图像
hNewDIBBits   =   LocalAlloc(LHND,   lWidth   *   lHeight);

if   (hNewDIBBits   ==   NULL)
{
//   分配内存失败
return   FALSE;
}

//   锁定内存
lpNewDIBBits   =   (char   *   )LocalLock(hNewDIBBits);

//   初始化新分配的内存,设定初始值为255
lpDst   =   (char   *)lpNewDIBBits;
memset(lpDst,   (BYTE)255,   lWidth   *   lHeight);

//   计算图像每行的字节数
lLineBytes   =   WIDTHBYTES(lWidth   *   8);
lTemplateLineBytes   =   WIDTHBYTES(lTemplateWidth   *   8);

//计算dSigmaT
dSigmaT   =   0;
for   (n   =   0;n   <   lTemplateHeight   ;n++)
{
for(m   =   0;m   <   lTemplateWidth   ;m++)
{
//   指向模板图像倒数第j行,第i个象素的指针
lpTemplateSrc   =   (char   *)lpTemplateDIBBits   +   lTemplateLineBytes   *   n   +   m;
templatepixel   =   (unsigned   char)*lpTemplateSrc;
dSigmaT   +=   (double)templatepixel*templatepixel;
}
}

//找到图像中最大相似性的出现位置
MaxR   =   0.0;
for   (j   =   0;j   <   lHeight   -   lTemplateHeight   +1   ;j++)
{
for(i   =   0;i   <   lWidth   -   lTemplateWidth   +   1;i++)
{
dSigmaST   =   0;
dSigmaS   =   0;

for   (n   =   0;n   <   lTemplateHeight   ;n++)
{
for(m   =   0;m   <   lTemplateWidth   ;m++)
{
//   指向源图像倒数第j+n行,第i+m个象素的指针
lpSrc     =   (char   *)lpDIBBits   +   lLineBytes   *   (j+n)   +   (i+m);

//   指向模板图像倒数第n行,第m个象素的指针
lpTemplateSrc     =   (char   *)lpTemplateDIBBits   +   lTemplateLineBytes   *   n   +   m;

pixel   =   (unsigned   char)*lpSrc;
templatepixel   =   (unsigned   char)*lpTemplateSrc;

dSigmaS   +=   (double)pixel*pixel;
dSigmaST   +=   (double)pixel*templatepixel;
}
}
//计算相似性
R   =   dSigmaST   /   (   sqrt(dSigmaS)*sqrt(dSigmaT));
//与最大相似性比较
if   (R   >   MaxR)
{
MaxR   =   R;
lMaxWidth   =   i;
lMaxHeight   =   j;
}
}
}

//将最大相似性出现区域部分复制到目标图像
for   (n   =   0;n   <   lTemplateHeight   ;n++)
{
for(m   =   0;m   <   lTemplateWidth   ;m++)
{
lpTemplateSrc   =   (char   *)lpTemplateDIBBits   +   lTemplateLineBytes   *   n   +   m;
lpDst   =   (char   *)lpNewDIBBits   +   lLineBytes   *   (n+lMaxHeight)   +   (m+lMaxWidth);
*lpDst   =   *lpTemplateSrc;
}
}

//   复制图像
memcpy(lpDIBBits,   lpNewDIBBits,   lWidth   *   lHeight);

//   释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);

//   返回
return   TRUE;
}Top

这是模板匹配的代码,
里面用的就是时域卷积的算法。

同时,时域卷积就是频域的乘积,
可以把时域的图转化成频域,相乘。

ps
卷积需要补位,
a   ,b
l   >=   a+b-1;
http://wenku.baidu.com/link?url=N_AvksJPpds6tlT7uGKE896ByVDH7n8olJjYiCwoqrWgUIoAA2KLVfUI-OSBYYp3j0jA6kOAYCsh4Y19IPYoG71YS2lrNgQcHUMJumYuk2O
(6)、卷积的各种优化
 包括二维转一维
http://bbs.csdn.net/topics/30472434

卷积的应用太广泛了:比如说 考试舞弊找代考的,把两个人的照片进行卷积就,类似同一个人了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: