【C++】【图像处理】均值滤波 and 高斯滤波 and 中值滤波 (低通滤波器)and Sobel算子边缘提取算法解析(以.raw格式的图像为基础进行图像处理、gray levels:256)
1 void meanFilter(BYTE* image, int width, int height, BYTE* outImg) 2 { 3 //均值滤波 4 int smth[9]; 5 int i, j, m, n; 6 BYTE block[9]; 7 8 // 高斯卷积核初始化 9 smth[0] = 1, smth[1] = 2, smth[2] = 1, 10 smth[3] = 2, smth[4] = 4, smth[5] = 2, 11 smth[6] = 1, smth[7] = 2, smth[8] = 1; 12 13 int value; 14 for (i = 0;i < 9;i++) //初始化均值卷积核 15 smth[i] = 1; 16 17 for (i = 0;i < height;i++) 18 for (j = 0;j < width;j++) { 19 //将输出图像边缘的像素值设为 0 20 if (i == 0 || j == 0 || i == height - 1 || j == width - 1) 21 outImg[i * width + j] = 0; 22 23 //提取以当前像素为中心的 3x3 区域的像素值,然后利用卷积操作计算这个区域的均值,最后将计算得到的均值作为输出图像中对应位置的像素值 24 else { 25 for (m = -1;m < 2;m++) 26 for (n = -1;n < 2;n++) 27 block[(m + 1) * 3 + n + 1] = image[(i + m) * width + j + n]; 28 value = convolution(smth, block); 29 outImg[i * width + j] = BYTE(value / 9.0f); // 高斯为 value / 16.0f 30 } 31 } 32 33 } 34 35 36 int convolution(int* operatr, BYTE* block) 37 { 38 int value; 39 int i, j; 40 value = 0; 41 //卷积运算 42 //遍历 3x3 区域内的每个像素,并根据卷积核的权重计算出卷积结果 43 for (i = 0;i < 3;i++) 44 for (j = 0;j < 3;j++) 45 value += operatr[i * 3 + j] * block[i * 3 + j]; 46 /* 47 1 1 1 48 1 1 1 49 1 1 1 50 51 0 0 0 52 0 x y 53 0 j k 54 */ 55 56 return value; 57 58 }
中值滤波:
1 void midFindFiltering(BYTE* image, int width, int height, BYTE* outImg) 2 { 3 //中值滤波 4 int i, j, m, n; 5 BYTE block[9]; 6 7 int value; 8 9 for (i = 0;i < height;i++) 10 for (j = 0;j < width;j++) { 11 if (i == 0 || j == 0 || i == height - 1 || j == width - 1) 12 outImg[i * width + j] = 0; 13 else { 14 for (m = -1;m < 2;m++) 15 for (n = -1;n < 2;n++) 16 block[(m + 1) * 3 + n + 1] = image[(i + m) * width + j + n]; 17 } 18 value = MidValueFind(sizeof(block), block); 19 outImg[i * width + j] = value; 20 } 21 }
中值滤波中的MidValueFind函数的实现就是冒泡排序,最后去中间值返回:
int MidValueFind(int num, BYTE* d) { int value; int i, j; int temp; //冒泡排序 for (i = 0; i < num - 1; i++) for (j = i + 1; j < num; j++) { if (d[i] < d[j]) { temp = d[i]; d[i] = d[j]; d[j] = temp; } } return d[num / 2]; }
Soble算子边缘提取:
1 void sobel(BYTE* window, int wid, int hei, int* sob_x, int* sob_y) 2 { 3 int so_x[9];//horizontal 水平边缘提取卷积核初始化 4 so_x[0] = -1, so_x[1] = 0, so_x[2] = 1, 5 so_x[3] = -2, so_x[4] = 0, so_x[5] = 2, 6 so_x[6] = -1, so_x[7] = 0, so_x[8] = 1; 7 8 int so_y[9];//vertical 垂直边缘提取卷积核初始化 9 so_y[0] = -1, so_y[1] = -2, so_y[2] = -1, 10 so_y[3] = 0, so_y[4] = 0, so_y[5] = 0, 11 so_y[6] = 1, so_y[7] = 2, so_y[8] = 1; 12 13 int i, j, m, n; 14 BYTE block[9]; 15 int value; 16 17 //求图像边缘 18 for (i = 0;i < hei;i++) 19 for (j = 0;j < wid;j++) { 20 if (i == 0 || j == 0 || i == hei - 1 || j == wid - 1) { 21 sob_x[i * wid + j] = sob_y[i * wid + j] = 0; // 输出图像边缘归零 22 } 23 else { 24 for (m = -1;m < 2;m++) 25 for (n = -1;n < 2;n++) 26 block[(m + 1) * 3 + n + 1] = window[(i + m) * wid + j + n]; 27 } 28 sob_x[i * wid + j] = convolution(so_x, block); 29 sob_y[i * wid + j] = convolution(so_y, block); 30 31 } 32 }
总结:
1、均值、高斯滤波和Sobel算子边缘提取的核心,创建卷积核并确定各个点上的权重,然后将边缘灰度级归零(是否边缘归零按业务需求决定),提取非边缘像素点的3x3区域的像素级,最后计算卷积结果再输出。
2、中值滤波核心也可看为是卷积核,但是并不是在卷积核上计算权重,而是进行排序(升降均可)后直接取中间值来确定当前这一点的灰度级。