matlab的conv二、imfilter、filter2

 

1算法

conv2函數

C=conv2(A,B,shape); %卷積濾波 
參數說明: 
A:輸入圖像 
B:卷積核 
shape的可選值爲full、same、valid。 
1)當shape=full時,返回所有二維卷積結果,即返回B的大小爲(ma+mb-1)x(na+nb-1)。 
2)shape=same時,返回與A一樣大小的卷積中心部分。 
3)shape=valid時,不考慮邊界補零,即只要有邊界補出的零參與運算的都捨去,返回B的大小爲(ma-mb+1)x(na-nb+1)。 
上面敘述看起來略有些抽象,能夠結合下面的圖一塊兒理解。 
3種參數的區別見圖。 
這裏寫圖片描述 
這裏寫圖片描述 
這裏寫圖片描述函數

filter2函數

B = filter2(h,A,shape) ; %相關(correlation)濾波 
這裏須要明晰一下卷積和相關的區別,卷積操做就是先將卷積核旋轉180度而後再和核大小相同的區域內的各元素對應相乘再相加。也就是核旋轉180後卷積。而相關操做就是直接用核卷積,不作旋轉。注意,我在敘述的時候,把2個區域對應元素相乘再相加這一個操做稱爲卷積。 
參數說明: 
A:輸入圖像,h:相關核 
假設輸入圖像A大小爲ma x na,相關核h大小爲mb x nb。 
1)當shape=full時,返回所有二維卷積結果,即返回B的大小爲(ma+mb-1)x(na+nb-1) 
2)shape=same時,返回與A一樣大小的卷積中心部分。 
3)shape=valid時,不考慮邊界補零,即只要有邊界補出的零參與運算的都捨去,返回B的大小爲(ma-mb+1)x(na-nb+1)。spa

imfilter函數

imfilter函數可以實現3通道的RGB圖像和單通道的濾波器的卷積,而且返回的圖像也是3通道的。 
B=imfilter(A,H,option1,option2,option3); 
參數說明: 
A:輸入圖像,H:濾波核 
1)option1:邊界選項,可選的有:補充固定的值X(默認都補零),symmetric,replicate,circular 
2)option2:輸出圖像大小選項,可選的有same(默認),full 
3)option3:決定採用與filter2相同的相關濾波仍是與conv2相同的卷積濾波code

三者的比較

1)filter2輸入類型無所謂,輸出是double的,輸入在邊界老是補零(zero padded), 不支持其餘的邊界補充選項。 
2)conv2的輸入只能爲double型的,不然會提示警告,輸出也是double型的。 
2) imfilter:不必定要將輸入轉換爲double,可是輸出只與輸入同類型,有靈活的邊界補充選項。有symmetric、replicate,same等。 
在適用圖像的維度上,imfilter可進行多維圖像(RGB等)進行空間濾波,filter2 只能對二維圖像(灰度圖)進行空間濾波,conv2能夠對圖像矩陣實現本身想實現的卷積操做,最簡單最經常使用的是二維。因此conv2和filter2相似,多維圖像(RGB等)要用imfilter。blog

 

【2】接口

二維卷積的算法原理比較簡單,參考隨意一本數字信號處理的書籍,而matlab的conv2函數的濾波有個形狀參數,用如下的一張圖很是能說明問題:圖片

這裏給出一種最原始的實現方案。這樣的實現對於數據矩陣大小爲1000x1000,卷積核矩陣大小爲20x20,在個人機器上需要大約1秒鐘的時間。而matlab採用的MKL庫最快僅僅需要將近0.1s的時間。ci

如下的代碼用到了本身眼下開發的FastIV中的一些函數接口。詳細代碼例如如下:開發

 

#include "fiv_core.h"

typedef enum{
	FIV_CONV2_SHAPE_FULL,
	FIV_CONV2_SHAPE_SAME,
	FIV_CONV2_SHAPE_VALID
}FIV_CONV_SHAPE;


void fIv_conv2(fIvMat** dst_mat, fIvMat* src_mat, fIvMat* kernel_mat, FIV_CONV_SHAPE shape)
{
	int src_row = src_mat->rows;
	int src_cols = src_mat->cols;
	int kernel_row = kernel_mat->rows;
	int kernel_cols = kernel_mat->cols;
	int dst_row = 0, dst_cols = 0, edge_row = 0, edge_cols = 0;
	int i,j, kernel_i,kernel_j,src_i,src_j;
	fIvMat* ptr_dst_mat = NULL;
	
	switch(shape){
		case FIV_CONV2_SHAPE_FULL:	
			
			dst_row = src_row + kernel_row - 1;
			dst_cols = src_cols + kernel_cols - 1;		
			edge_row = kernel_row - 1;
			edge_cols = kernel_cols - 1;
			break;
			
		case FIV_CONV2_SHAPE_SAME:
			
			dst_row = src_row;
			dst_cols = src_cols;
			edge_row = (kernel_row - 1) / 2;
			edge_cols = (kernel_cols - 1) / 2;
			break;
			
		case FIV_CONV2_SHAPE_VALID:
			
			dst_row = src_row - kernel_row + 1;
			dst_cols = src_cols - kernel_cols + 1;
			edge_row = edge_cols = 0;
			break;
			
	}
	
	ptr_dst_mat = fIv_create_mat(dst_row, dst_cols, FIV_64FC1);
	*dst_mat = ptr_dst_mat;
	
	for (i = 0; i < dst_row; i++) {	
		ivf64* ptr_dst_line_i = (ivf64* )fIv_get_mat_data_at_row(ptr_dst_mat, i);	
		for (j = 0; j < dst_cols; j++) {		
			ivf64 sum = 0;
			
			kernel_i = kernel_row - 1 - FIV_MAX(0, edge_row - i);
			src_i = FIV_MAX(0, i - edge_row);
			
			for (; kernel_i >= 0 && src_i < src_row; kernel_i--, src_i++) {
				
				ivf64* ptr_src_line_i,*ptr_kernel_line_i;
				
				kernel_j = kernel_cols - 1 - FIV_MAX(0, edge_cols - j);
				src_j = FIV_MAX(0, j - edge_cols);
				
				ptr_src_line_i = (ivf64*)fIv_get_mat_data_at_row(src_mat, src_i);
				ptr_kernel_line_i = (ivf64*)fIv_get_mat_data_at_row(kernel_mat, kernel_i);
				
				ptr_src_line_i += src_j;
				ptr_kernel_line_i += kernel_j;
				
				for (; kernel_j >= 0 && src_j < src_cols; kernel_j--, src_j++){
					sum += *ptr_src_line_i++ * *ptr_kernel_line_i--;
					}
			}			
			ptr_dst_line_i[j] = sum;
		}
	}
}


FIV_ALIGNED(16) ivf64 ker_data[4*4] = {0.1,0.2,0.3,0.4,
									   0.5,0.6,0.7,0.8,
									   0.9,1.0,1.1,1.2,
									   1.3,1.4,1.5,1.6};



void test_conv2()
{
	fIvMat* src_mat = fIv_create_mat_magic(8, FIV_64FC1); // 8x8 magic matrix
	fIvMat* kernel_mat = fIv_create_mat_header(4, 4, FIV_64FC1);

	fIvMat* dst_mat = NULL;
	fIv_set_mat_data(kernel_mat, ker_data, (sizeof(ivf64)) * 4 * 4);

	fIv_conv2(&dst_mat, src_mat, kernel_mat, FIV_CONV2_SHAPE_FULL);

	fIv_export_matrix_data_file(dst_mat,"dst_mat_4x4-full.txt", 1);


	fIv_release_mat(&src_mat);
	fIv_release_mat(&kernel_mat);
	fIv_release_mat(&dst_mat);



}

int main()
{
	test_conv2();

	return 0;
}
相關文章
相關標籤/搜索