sobel算子边缘提取及程序优化(C语言)

sobel算子边缘提取及程序优化(C语言)

1. 利用高斯模糊

直接使用边缘检测算子,提取出的信息过多,使用高斯模糊滤去一些不必要的信息

根据正态分布,获取高斯模糊的归一化卷积核如下
在这里插入图片描述
直接对原图进行高斯模糊(以大小为120*188的灰度图为例)

void Gaussain_Blur() {
	uint8_t* map;
	uint8_t* my_map;
	//float Gaussain_Blur[9] = {0.075, 0.124, 0.075, 0.124, 0.204, 0.124, 0.075, 0.124, 0.075};
	float Gaussain_Blur[9] = { 0.0947416, 0.118318, 0.0947416, 0.118318, 0.147761, 0.118318, 0.0947416, 0.118318, 0.0947416 };
	uint8_t temp_fix[9];
	uint8_t Blur_image[CAMERA_H][CAMERA_W];

	map = fullBuffer;	// 获取原灰度图
	for (int j = 0; j < CAMERA_W; ++j) {	// 第一行不做处理
		Blur_image[0][j] = *(map);
		map++;
	}
	for (int i = 1; i < CAMERA_H - 1; ++i) {
		Blur_image[i][0] = *(map);	// 第一列不做处理
		map++;
		/* 高斯模糊 */
		for (int j = 1; j < CAMERA_W - 1; ++j) {
			temp_fix[0] = *(map - CAMERA_W - 1);
			temp_fix[1] = *(map - CAMERA_W);
			temp_fix[2] = *(map - CAMERA_W + 1);
			temp_fix[3] = *(map - 1);
			temp_fix[4] = *(map);
			temp_fix[5] = *(map + 1);
			temp_fix[6] = *(map + CAMERA_W - 1);
			temp_fix[7] = *(map + CAMERA_W);
			temp_fix[8] = *(map + CAMERA_W + 1);
			float fix_sum = 0;
			for (int k = 0; k < 9; ++k) {
				fix_sum += (float)temp_fix[k] * Gaussain_Blur[k];
			}
			Blur_image[i][j] = (int)fix_sum;
			map++;
		}
		Blur_image[i][CAMERA_W - 1] = *(map); // 最后一列不做处理
		map++;
	}
	for (int j = 0; j < CAMERA_W; ++j) { // 最后一行不做处理
		Blur_image[CAMERA_H - 1][j] = *(map);
		map++;
	}
}

2. sobel算子提取边缘的原理

s o b e l sobel sobel算子是 3*3 的矩阵,利用如下矩阵对图像进行卷积可以获取图像大的竖直边界和水平边界信息。

G Y = [ − 1 0 1 − 2 0 2 − 1 0 1 ] G_Y=\begin{bmatrix}-1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \\ \end{bmatrix} GY= 121000121      G X = [ − 1 − 2 − 1 0 0 0 1 2 1 ] G_X =\begin{bmatrix}-1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \\ \end{bmatrix} GX= 101202101

对图像的某九宫格进行卷积后,获取到的边缘像素信息如下

G i m a g e = [ f ( x − 1 , y − 1 ) f ( x , y − 1 ) f ( x + 1 , y − 1 ) f ( x − 1 , y ) f ( x , y ) f ( x + 1 , y ) f ( x − 1 , y + 1 ) f ( x , y + 1 ) f ( x + 1 , y + 1 ) ] G_{image}= \begin{bmatrix} f(x-1, y-1) & f(x, y-1) & f(x+1, y-1) \\ f(x-1, y) & f(x, y) & f(x+1, y)\\ f(x-1, y+1) & f(x, y+1) & f(x+1, y+1)\\ \end{bmatrix} Gimage= f(x1,y1)f(x1,y)f(x1,y+1)f(x,y1)f(x,y)f(x,y+1)f(x+1,y1)f(x+1,y)f(x+1,y+1)

为了方便理解,将图像九宫格信息标号

G i m a g e = [ p i x 1 p i x 2 p i x 3 p i x 4 p i x 5 p i x 6 p i x 7 p i x 8 p i x 9 ] G_{image}= \begin{bmatrix} pix_1 & pix_2 & pix_3 \\ pix_4 & pix_5 & pix_6\\ pix_7 & pix_8 & pix_9\\ \end{bmatrix} Gimage= pix1pix4pix7pix2pix5pix8pix3pix6pix9

G E D G E c o l o m = G X ∗ G i m a g e = − p i x 1 − 2 p i x 2 − p i x 3 + p i x 7 + 2 p i x 8 + p i x 9 G_{EDGE_{colom}} = G_X * G_{image} = -pix_1 -2pix_2 - pix_3 + pix_7 + 2pix_8 + pix_9 GEDGEcolom=GXGimage=pix12pix2pix3+pix7+2pix8+pix9

G E D G E r o w = G Y ∗ G i m a g e = − p i x 1 − 2 p i x 4 − p i x 7 + p i x 3 + 2 p i x 6 + p i x 9 G_{EDGE_{row}} = G_Y * G_{image} = -pix_1 - 2pix_4 - pix_7 + pix_3 + 2pix_6 + pix_9 GEDGErow=GYGimage=pix12pix4pix7+pix3+2pix6+pix9

最后根据卷积结果获得一个灰度值

G p i x 5 = G E D G E c o l o m 2 + G E D G E r o w 2 G_{pix_5} = \sqrt{G_{EDGE_{colom}}^2 + G_{EDGE_{row}}^2} Gpix5=GEDGEcolom2+GEDGErow2

2. sobel算子的C语言实现

代码实现

void Sobel_get_edge(void) {
	uint8_t* map;
	uint8_t* my_map;
	uint8_t pix_1 = 0;
	uint8_t pix_2 = 0;
	uint8_t pix_3 = 0;
	uint8_t pix_4 = 0;
	uint8_t pix_5 = 0;
	uint8_t pix_6 = 0;
	uint8_t pix_7 = 0;
	uint8_t pix_8 = 0;
	uint8_t pix_9 = 0;

	map = &Blur_image[0][0];	// 对高斯模糊之后的图像进行边缘提取
	for (int i = 0; i < CAMERA_H - 2; i++) {
		IMG[i][0] = *(map);	// 处理结果存储在IMG中
		map++;
		my_map = &IMG[i][1];
		for (int j = 1; j < 188 - 1; j++) {
			pix_1 = *(map - 1);
			pix_2 = *(map);
			pix_3 = *(map + 1);
			pix_4 = *(map + CAMERA_W - 1);
			pix_5 = *(map + CAMERA_W);
			pix_6 = *(map + CAMERA_W + 1);
			pix_7 = *(map + CAMERA_W + CAMERA_W - 1);
			pix_8 = *(map + CAMERA_W + CAMERA_W);
			pix_9 = *(map + CAMERA_W + CAMERA_W + 1);

			int G_x = -pix_1 - 2 * pix_2 - pix_3 + pix_7 + 2 * pix_8 + pix_9;
			int G_y = -pix_1 - 2 * pix_4 - pix_7 + pix_3 + 2 * pix_6 + pix_9;
			*(my_map) = sqrt(G_x * G_x + G_y * G_y);

			map++;
			my_map++;
		}
		IMG[i][CAMERA_W - 1] = *(map);
		map++;
		my_map++;
	}
	for (int j = 0; j < CAMERA_W; ++j) {
		IMG[CAMERA_H - 1][j] = *(map);
		map++;
	}
}

直接对原图进行边缘提取效果并不好,会出现断线、边缘检测过于敏锐等情况
未进行高斯模糊的边界提取效果如下

阈值为100时的二值化结果:
在这里插入图片描述
在这里插入图片描述

使用SCHARR算子结果如下

阈值为100时的二值化结果:

在这里插入图片描述
在这里插入图片描述

阈值改为150
在这里插入图片描述
高斯模糊后的边界提取效果如下
可以看到,高斯模糊之后的边界提取效果更好
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值