Sobel算子及C++实现

32 篇文章 10 订阅
29 篇文章 1 订阅

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

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


经典Sobel的卷积因子为:



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

                                                                  

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


    

或更为简单粗暴的:

   

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


以下是C++实现:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include "core/core.hpp"    
  2. #include "highgui/highgui.hpp"    
  3. #include "imgproc/imgproc.hpp"    
  4. #include "iostream"  
  5.   
  6. using namespace std;   
  7. using namespace cv;    
  8.   
  9. int main(int argc,char *argv[])    
  10. {  
  11.     Mat image=imread(argv[1],0);  
  12.     Mat imageX=Mat::zeros(image.size(),CV_16SC1);  
  13.     Mat imageY=Mat::zeros(image.size(),CV_16SC1);     
  14.     Mat imageXY=Mat::zeros(image.size(),CV_16SC1);    
  15.     Mat imageX8UC;  
  16.     Mat imageY8UC;  
  17.     Mat imageXY8UC;  
  18.     if(!image.data)  
  19.     {  
  20.         return -1;  
  21.     }  
  22.     GaussianBlur(image,image,Size(3,3),0); //高斯滤波消除噪点  
  23.     uchar *P=image.data;  
  24.     uchar *PX=imageX.data;  
  25.     uchar *PY=imageY.data;  
  26.     int step=image.step;  
  27.     int stepXY=imageX.step;  
  28.     for(int i=1;i<image.rows-1;i++)  
  29.     {  
  30.         for(int j=1;j<image.cols-1;j++)  
  31.         {  
  32.             //通过指针遍历图像上每一个像素  
  33.             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]);  
  34.             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]);  
  35.         }  
  36.     }  
  37.     addWeighted(imageX,0.5,imageY,0.5,0,imageXY);//融合X、Y方向    
  38.     convertScaleAbs(imageX,imageX8UC);  
  39.     convertScaleAbs(imageY,imageY8UC);  
  40.     convertScaleAbs(imageXY,imageXY8UC);   //转换为8bit图像  
  41.   
  42.     Mat imageSobel;  
  43.     Sobel(image,imageSobel,CV_8UC1,1,1); //Opencv的Sobel函数  
  44.   
  45.     imshow("Source Image",image);  
  46.     imshow("X Direction",imageX8UC);  
  47.     imshow("Y Direction",imageY8UC);  
  48.     imshow("XY Direction",imageXY8UC);  
  49.     imshow("Opencv Soble",imageSobel);  
  50.     waitKey();    
  51.     return 0;  
  52. }  

原始的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算子锐化过程中,对于每个像素点,先将其周围的像素点与卷积核进行卷积,得到横向和纵向的梯度值,然后计算其模长,即得到锐化后的像素值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值