2020.11.07 使用OpenCV进行图像边缘提取(Sobel算子)【OpenCV C++ Sobel】
图像边缘提取,采用的算子为Sobel
使用API:Sobel()以及增强了权重的Scharr()
处理流程:
1.进行高斯滤波
2.转化为灰度图像
3.进行X,Y轴的Sobel处理
4.对X,Y处理后的数据进行线性叠加(简化实际的Sobel运算)
源代码:
// testOpencv16.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
const char* inWin = "input window";
const char* outWin = "output window";
int main()
{
// std::cout << "Hello World!\n";
Mat src, graySrc,dst;
src = imread("E:/imageSources/7.jpg");
if (!src.data) {
printf("cannot load image,Please check you code");
return -1;
}
namedWindow(inWin, WINDOW_AUTOSIZE);
imshow(inWin,src);
//进行高斯滤波
GaussianBlur(src,dst,Size(3,3),0,0.0);
cvtColor(dst,graySrc,COLOR_BGR2GRAY);
imshow("gray image",graySrc);
Mat sobelX, sobelY, sobelOutImage;
//采用Sobel API进行图像边缘提取
//Sobel(graySrc, sobelX, -1, 1, 0);
//Sobel(graySrc, sobelY, -1, 0, 1);
//Sobel(graySrc,sobelX,CV_16S,1,0);
//Sobel(graySrc, sobelY, CV_16S, 0, 1);
//采用Scharr:加权之后的Sobel算法
Scharr(graySrc, sobelX, CV_16S, 1, 0);
Scharr(graySrc, sobelY, CV_16S, 0, 1);
//保证值都为正的相加
//取绝对值操作
convertScaleAbs(sobelX,sobelX);
convertScaleAbs(sobelY,sobelY);
Mat xyGrad = Mat::zeros(sobelX.size(),sobelX.type());
int heigh = xyGrad.rows;
int width = xyGrad.cols;
//采用像素点遍历的方式进行X,Y线性叠加
for (int row = 0; row < heigh; row++) {
for (int col = 0; col < width; col++) {
int x = sobelX.at<uchar>(row, col);
int y = sobelY.at<uchar>(row, col);
int xy = x + y;
//限制xy像素值在一定范围内(防止因为相加造成超出像素范围值)
xyGrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
//xyGrad.at<uchar>(row, col) = xy;
}
}
namedWindow(outWin, WINDOW_AUTOSIZE);
imshow(outWin, xyGrad);
//采用线性叠加,权重的方式
double alpha = 0.5;
addWeighted(sobelX, alpha ,sobelY,(1- alpha),0.0,sobelOutImage);
namedWindow(outWin, WINDOW_AUTOSIZE);
imshow("addWeight method", sobelOutImage);
waitKey(0);
return 0;
}
图像处理效果:
使用sobel()(像素点遍历相加 + addWeight的方法进行线性叠加)
使用Scharr()(像素遍历线性相加+addWeight的方法进行线性叠加)
可以看到使用Scharr()更加能抓住图像细节边缘