c語言數字影象處理(五):空間濾波
空間濾波原理
使用大小為m*n的濾波器對大小為M*N的影象進行線性空間濾波,將濾波器模板乘以影象中對應灰度值,相加得模板中心灰度值
a = (m-1)/2, b = (n-1)/2
若f(x+s, y+t)不在原圖內,補0
平滑線性濾波器
濾波過程
分母為濾波器模板和
程式碼實現
1 int is_in_array(short x, short y, short height, short width) 2 { 3if (x >= 0 && x < width && y >= 0 && y < height) 4return 1; 5else 6return 0; 7 } 8 9 /* 10* element 11* v0v1v2 12* v3v4v5 13* v6v7v8 14* 15*/ 16 void filtering(short** in_array, short** out_array, long height, long width) 17 { 18short value[9]; 19 20/* linear filtering */ 21short sum; 22for (int i = 0; i < ARRAY_SIZE; i++) 23for (int j = 0; j < ARRAY_SIZE; j++) 24sum += average[i][j]; 25 26for (int i = 0; i < height; i++){ 27for (int j = 0; j < width; j++){ 28value[0] = is_in_array(j-1, i-1, height, width) ? in_array[i-1][j-1] : 0; 29value[1] = is_in_array(j, i-1, height, width) ? in_array[i-1][j] : 0; 30value[2] = is_in_array(j+1, i-1, height, width) ? in_array[i-1][j+1] : 0; 31value[3] = is_in_array(j-1, i, height, width) ? in_array[i][j-1] : 0; 32value[4] = in_array[i][j]; 33value[5] = is_in_array(j+1, i, height, width) ? in_array[i][j+1] : 0; 34value[6] = is_in_array(j-1, i+1, height, width) ? in_array[i+1][j-1] : 0; 35value[7] = is_in_array(j, i+1, height, width) ? in_array[i+1][j] : 0; 36value[8] = is_in_array(j+1, i+1, height, width) ? in_array[i+1][j+1] : 0; 37 38/* linear filtering */ 39out_array[i][j] = (value[0] * average[0][0] + value[1] * average[0][1] + value[2] * average[0][2] + 40value[3] * average[1][0] + value[4] * average[1][1] + value[5] * average[1][2] + 41value[6] * average[2][0] + value[7] * average[2][1] + value[8] * average[2][2]) / sum; 42 43} 44} 45 }
原圖
模板
結果
可以看出線性濾波器會較大程度地影響原圖,降低對比度,對與圖片右上角的噪聲沒有明顯的去除效果
統計排序(非線性)濾波器
中值濾波器
中值濾波器對處理脈衝噪聲非常有效,這種噪聲被稱為椒鹽噪聲
實現方法:取該畫素某鄰域中值(本次測試取3*3)
程式碼實現
1 short mid_val(short* a, short num) 2 { 3short temp; 4 5for (int i = 0; i < num; i++) 6{ 7temp = a[i]; 8int j = i; 9for (; j > 0 && a[j - 1] > temp; j--) 10a[j] = a[j - 1]; 11a[j] = temp; 12} 13 14return a[num/2]; 15 } 16 int is_in_array(short x, short y, short height, short width) 17 { 18if (x >= 0 && x < width && y >= 0 && y < height) 19return 1; 20else 21return 0; 22 } 23 24 /* 25* element 26* v0v1v2 27* v3v4v5 28* v6v7v8 29* 30*/ 31 void filtering(short** in_array, short** out_array, long height, long width) 32 { 33short value[9]; 34 35for (int i = 0; i < height; i++){ 36for (int j = 0; j < width; j++){ 37value[0] = is_in_array(j-1, i-1, height, width) ? in_array[i-1][j-1] : 0; 38value[1] = is_in_array(j, i-1, height, width) ? in_array[i-1][j] : 0; 39value[2] = is_in_array(j+1, i-1, height, width) ? in_array[i-1][j+1] : 0; 40value[3] = is_in_array(j-1, i, height, width) ? in_array[i][j-1] : 0; 41value[4] = in_array[i][j]; 42value[5] = is_in_array(j+1, i, height, width) ? in_array[i][j+1] : 0; 43value[6] = is_in_array(j-1, i+1, height, width) ? in_array[i+1][j-1] : 0; 44value[7] = is_in_array(j, i+1, height, width) ? in_array[i+1][j] : 0; 45value[8] = is_in_array(j+1, i+1, height, width) ? in_array[i+1][j+1] : 0; 46 47/* median filtering */ 48out_array[i][j] = mid_val(value, 9); 49 50} 51} 52 }
銳化空間濾波器
一階微分
二階微分
二階微分在增強細節方面比一階微分好很多,適合銳化影象
使用二階微分進行影象銳化-拉普拉斯運算元
程式碼實現
1 int is_in_array(short x, short y, short height, short width) 2 { 3if (x >= 0 && x < width && y >= 0 && y < height) 4return 1; 5else 6return 0; 7 } 8 9 /* 10* element 11* v0v1v2 12* v3v4v5 13* v6v7v8 14* 15*/ 16 void filtering(short** in_array, short** out_array, long height, long width) 17 { 18short value[9]; 19 20for (int i = 0; i < height; i++){ 21for (int j = 0; j < width; j++){ 22value[0] = is_in_array(j-1, i-1, height, width) ? in_array[i-1][j-1] : 0; 23value[1] = is_in_array(j, i-1, height, width) ? in_array[i-1][j] : 0; 24value[2] = is_in_array(j+1, i-1, height, width) ? in_array[i-1][j+1] : 0; 25value[3] = is_in_array(j-1, i, height, width) ? in_array[i][j-1] : 0; 26value[4] = in_array[i][j]; 27value[5] = is_in_array(j+1, i, height, width) ? in_array[i][j+1] : 0; 28value[6] = is_in_array(j-1, i+1, height, width) ? in_array[i+1][j-1] : 0; 29value[7] = is_in_array(j, i+1, height, width) ? in_array[i+1][j] : 0; 30value[8] = is_in_array(j+1, i+1, height, width) ? in_array[i+1][j+1] : 0; 31 32/* sharpening filtering */ 33out_array[i][j] = value[0] * sharpen[0][0] + value[1] * sharpen[0][1] + value[2] * sharpen[0][2] + 34value[3] * sharpen[1][0] + value[4] * sharpen[1][1] + value[5] * sharpen[1][2] + 35value[6] * sharpen[2][0] + value[7] * sharpen[2][1] + value[8] * sharpen[2][2]; 36out_array[i][j] += in_array[i][j]; 37 38} 39} 40 }
原圖
銳化
使用一階微分對(非線性)影象銳化-梯度
實現邊緣增強
演算法實現
1 int is_in_array(short x, short y, short height, short width) 2 { 3if (x >= 0 && x < width && y >= 0 && y < height) 4return 1; 5else 6return 0; 7 } 8 9 /* 10* element 11* v0v1v2 12* v3v4v5 13* v6v7v8 14* 15*/ 16 void filtering(short** in_array, short** out_array, long height, long width) 17 { 18short value[9]; 19 20for (int i = 0; i < height; i++){ 21for (int j = 0; j < width; j++){ 22value[0] = is_in_array(j-1, i-1, height, width) ? in_array[i-1][j-1] : 0; 23value[1] = is_in_array(j, i-1, height, width) ? in_array[i-1][j] : 0; 24value[2] = is_in_array(j+1, i-1, height, width) ? in_array[i-1][j+1] : 0; 25value[3] = is_in_array(j-1, i, height, width) ? in_array[i][j-1] : 0; 26value[4] = in_array[i][j]; 27value[5] = is_in_array(j+1, i, height, width) ? in_array[i][j+1] : 0; 28value[6] = is_in_array(j-1, i+1, height, width) ? in_array[i+1][j-1] : 0; 29value[7] = is_in_array(j, i+1, height, width) ? in_array[i+1][j] : 0; 30value[8] = is_in_array(j+1, i+1, height, width) ? in_array[i+1][j+1] : 0; 31 32/* sharpening using grad */ 33out_array[i][j] = (short)abs(value[0] * soble1[0][0] + value[1] * soble1[0][1] + value[2] * soble1[0][2] + 34value[3] * soble1[1][0] + value[4] * soble1[1][1] + value[5] * soble1[1][2] + 35value[6] * soble1[2][0] + value[7] * soble1[2][1] + value[8] * soble1[2][2]) + 36(short)abs(value[0] * soble2[0][0] + value[1] * soble2[0][1] + value[2] * soble2[0][2] + 37value[3] * soble2[1][0] + value[4] * soble2[1][1] + value[5] * soble2[1][2] + 38value[6] * soble2[2][0] + value[7] * soble2[2][1] + value[8] * soble2[2][2]); 39} 40} 41 }
原圖
邊緣增強