索贝尔算子(Sobel operator)
在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量,主要用作边缘检测,可被认为是图像在垂直和水平方向变化的测量。
注意:
①观察灰度分布来描述一幅图像成为空间域,观察图像变化的频率被成为频域。
②频域分析:低频对应区域的图像强度变化缓慢,高频对应的变化快。低通滤波器去除了图像的高频部分,高通滤波器去除了图像的低频部分。
这里的卷积因子是卷积神经的一个小知识点就是以卷积因子为标本去对比总样本中的数据,如图
具体计算
将卷积因子与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:
Gx = (-1)f(x-1, y-1) + 0f(x,y-1) + 1f(x+1,y-1)
+(-2)f(x-1,y) + 0f(x,y)+2f(x+1,y)
+(-1)f(x-1,y+1) + 0f(x,y+1) + 1f(x+1,y+1)
= [f(x+1,y-1)+2f(x+1,y)+f(x+1,y+1)]-[f(x-1,y-1)+2f(x-1,y)+f(x-1,y+1)]*
Gy =1 f(x-1, y-1) + 2f(x,y-1)+ 1f(x+1,y-1)
+0f(x-1,y) 0f(x,y) + 0*f(x+1,y)
+(-1)*f(x-1,y+1) + (-2)f(x,y+1) + (-1)f(x+1, y+1)
= [f(x-1,y-1) + 2f(x,y-1) + f(x+1,y-1)]-[f(x-1, y+1) + 2f(x,y+1)+f(x+1,y+1)]
其中f(a,b), 表示图像(a,b)点的灰度值;
图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
通常,为了提高效率 使用不开平方的近似值:
如果梯度G大于某一阀值 则认为该点(x,y)为边缘点。
然后可用以下公式计算梯度方向:
代码
大致了解了Sobel算子的原理,我们来看一下在OpenCV中的使用方法:
#include <iostream>
#include <iomanip>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "laplacianZC.h"
int main()
{
//读取图像
cv::Mat image= cv::imread("boldt.jpg",0);
if (!image.data)
return 0;
// 展示读入的图像
cv::namedWindow("Original Image");
cv::imshow("Original Image",image);
// 计算 Sobel X 导数
cv::Mat sobelX;
cv::Sobel(image,sobelX,CV_8U,1,0,3,0.4,128);
// 显示图像
cv::namedWindow("Sobel X Image");
cv::imshow("Sobel X Image",sobelX);
// 计算 Sobel Y 导数
cv::Mat sobelY;
cv::Sobel(image,sobelY,CV_8U,0,1,3,0.4,128);
// 显示图像
cv::namedWindow("Sobel Y Image");
cv::imshow("Sobel Y Image",sobelY);
// 计算sobel的摸
cv::Sobel(image,sobelX,CV_16S,1,0);
cv::Sobel(image,sobelY,CV_16S,0,1);
cv::Mat sobel;
//compute the L1 norm
sobel= abs(sobelX)+abs(sobelY);
double sobmin, sobmax;
cv::minMaxLoc(sobel,&sobmin,&sobmax);
std::cout << "sobel value range: " << sobmin << " " << sobmax << std::endl;
// 打印窗口像素值
for (int i=0; i<12; i++) {
for (int j=0; j<12; j++)
std::cout << std::setw(5) << static_cast<int>(sobel.at<short>(i+135,j+362)) << " ";
std::cout << std::endl;
}
std::cout << std::endl;
std::cout << std::endl;
std::cout << std::endl;
// 转换为8位图像
// sobelImage = -alpha*sobel + 255
cv::Mat sobelImage;
sobel.convertTo(sobelImage,CV_8U,-255./sobmax,255);
// 显示图像
cv::namedWindow("Sobel Image");
cv::imshow("Sobel Image",sobelImage);
// 对Sobel norm应用阈值(低阈值)
cv::Mat sobelThresholded;
cv::threshold(sobelImage, sobelThresholded, 225, 255, cv::THRESH_BINARY);
// 显示图像
cv::namedWindow("Binary Sobel Image (low)");
cv::imshow("Binary Sobel Image (low)",sobelThresholded);
// 对Sobel norm应用阈值(高阈值)
cv::threshold(sobelImage, sobelThresholded, 190, 255, cv::THRESH_BINARY);
// 显示图像
cv::namedWindow("Binary Sobel Image (high)");
cv::imshow("Binary Sobel Image (high)",sobelThresholded);