Sobel算子及C++实现

Sobel 算子是一个离散的一阶微分算子,用来计算图像灰度函数的近似梯度。

在空间域上Sobel算子很容易实现,执行速度快,对部分噪声具有平滑作用,还能够提供较为精确的边缘方向信息,缺点是边缘定位精度不够高。边缘是指一个物体与另一个物体的分界处,一般边缘内外处都会有灰度值上的差异,Sobel算子就是通过像素点空间邻域内上下,左右相邻点的灰度加权运算,求取物体边缘。


经典Sobel的卷积因子为:



对于待检测边缘的图像I,分别在水平(X)方向和垂直方向(Y)方向求导,方法是分别图像I与卷积核Gx和Gy进行卷积,公式表述如下:

                                                                  

之后对求得的水平和垂直方向的梯度图像上的每一点执行:


    

或更为简单粗暴的:

   

G即为Sobel求得的梯度图像。


以下是C++实现:

#include "core/core.hpp"  
#include "highgui/highgui.hpp"  
#include "imgproc/imgproc.hpp"  
#include "iostream"

using namespace std; 
using namespace cv;  

int main(int argc,char *argv[])  
{
	Mat image=imread(argv[1],0);
	Mat imageX=Mat::zeros(image.size(),CV_16SC1);
	Mat imageY=Mat::zeros(image.size(),CV_16SC1);	
	Mat imageXY=Mat::zeros(image.size(),CV_16SC1);	
	Mat imageX8UC;
	Mat imageY8UC;
	Mat imageXY8UC;
	if(!image.data)
	{
		return -1;
	}
	GaussianBlur(image,image,Size(3,3),0); //高斯滤波消除噪点
	uchar *P=image.data;
	uchar *PX=imageX.data;
	uchar *PY=imageY.data;
	int step=image.step;
	int stepXY=imageX.step;
	for(int i=1;i<image.rows-1;i++)
	{
		for(int j=1;j<image.cols-1;j++)
		{
			//通过指针遍历图像上每一个像素
			PX[i*imageX.step+j*(stepXY/step)]=abs(P[(i-1)*step+j+1]+P[i*step+j+1]*2+P[(i+1)*step+j+1]-P[(i-1)*step+j-1]-P[i*step+j-1]*2-P[(i+1)*step+j-1]);
			PY[i*imageX.step+j*(stepXY/step)]=abs(P[(i+1)*step+j-1]+P[(i+1)*step+j]*2+P[(i+1)*step+j+1]-P[(i-1)*step+j-1]-P[(i-1)*step+j]*2-P[(i-1)*step+j+1]);
		}
	}
	addWeighted(imageX,0.5,imageY,0.5,0,imageXY);//融合X、Y方向	
	convertScaleAbs(imageX,imageX8UC);
	convertScaleAbs(imageY,imageY8UC);
	convertScaleAbs(imageXY,imageXY8UC);   //转换为8bit图像

	Mat imageSobel;
	Sobel(image,imageSobel,CV_8UC1,1,1); //Opencv的Sobel函数

	imshow("Source Image",image);
	imshow("X Direction",imageX8UC);
	imshow("Y Direction",imageY8UC);
	imshow("XY Direction",imageXY8UC);
	imshow("Opencv Soble",imageSobel);
	waitKey();	
	return 0;
}

原始的Lena美女;



X方向梯度:



Y方向梯度:



X、Y方向梯度融合效果:



Opencv Sobel函数效果:



Sobel算子是一种常用的边缘检测算子,可以用于图像锐化。下面是C语言实现Sobel算子锐化的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define WIDTH 512 #define HEIGHT 512 int main() { int i, j, k, l; int sobel_x, sobel_y, sobel; int image[HEIGHT][WIDTH]; int sharp_image[HEIGHT][WIDTH]; int gx[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; int gy[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; // 读取原始图像 FILE *fp = fopen("lena512.raw", "rb"); fread(image, sizeof(unsigned char), WIDTH * HEIGHT, fp); fclose(fp); // Sobel算子锐化 for (i = 1; i < HEIGHT - 1; i++) { for (j = 1; j < WIDTH - 1; j++) { sobel_x = sobel_y = 0; for (k = -1; k <= 1; k++) { for (l = -1; l <= 1; l++) { sobel_x += (image[i + k][j + l] * gx[k + 1][l + 1]); sobel_y += (image[i + k][j + l] * gy[k + 1][l + 1]); } } sobel = (int) sqrt(sobel_x * sobel_x + sobel_y * sobel_y); if (sobel > 255) sobel = 255; sharp_image[i][j] = sobel; } } // 将结果写入文件 fp = fopen("lena512_sharp.raw", "wb"); fwrite(sharp_image, sizeof(unsigned char), WIDTH * HEIGHT, fp); fclose(fp); return 0; } ``` 该示例代码使用Sobel算子对lena512.raw图像进行锐化,并将结果写入lena512_sharp.raw文件中。在该示例代码中,使用了两个3x3的矩阵gx和gy来表示Sobel算子的两个卷积核。在Sobel算子锐化过程中,对于每个像素点,先将其周围的像素点与卷积核进行卷积,得到横向和纵向的梯度值,然后计算其模长,即得到锐化后的像素值。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值