在Hough检测一章中出现了代码验证出错问题,由于进度原因在此只贴出另外一个相关的链接,后期修复好程序的Bug后再将具体内容贴上详情文章及代码请查阅轮廓,直线圆的拟合
查阅函数可得原型
CV_EXPORTS_W void Canny( InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false );由图片可知Canny算子为双阈第五个参数也就是孔径大小尺寸
在OpenCV2中可以允许直接进行自操作
比如说Canny(srcImage,srImage,150,100,3);
但是在OpenCV3中废除了这一做法,常用的做法为
1,转换为灰度图
2,进行滤波操作(去噪)
3,运行Canny得到边缘edge
4, 将edge作为掩模拷贝到原始图像上
#include "stdafx.h" #include<opencv2/opencv.hpp> using namespace cv; using namespace std; int _tmain(int argc, _TCHAR* argv[]) { /* 读取图像 颜色空间转换 滤波 采用Canny进行检测 */ Mat src = imread("1.jpg"); Mat src1 = src.clone(); imshow("原始图", src); Mat dst, edge, gray; //创造一个一样尺寸的Mat类型的dst dst.create(src1.size(), src1.type()); //将图像转化为灰度图 cvtColor(src1, gray, COLOR_BGR2GRAY); //降噪 blur(gray, edge, Size(3, 3)); //运行Canny Canny(edge, edge, 3, 9, 3); //将g_dstImage内所有元素置0 dst = Scalar::all(0); //将Canny算子输出的边缘图作为掩码拷贝到原图中 imshow("边缘",edge); src1.copyTo(dst, edge); //clone和copyTo都是实现矩阵的拷贝 //void copyTo( OutputArray m, InputArray mask ) const; imshow("Canny检测", dst); waitKey(0); return 0; }
CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT );第三个参数:输出图像的深度
第四个参数:x方向上的差分阶数
第五个参数:y方向上的差分阶数
第六个参数:Sobel核大小,只能取1,3,5或7
Sobel程序实例
#include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; int main() { Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y, dst; //ConvertScaleAbs使用线性变换转换输入数组元素成8位无符号整型。 //内核大小为3时,Sobel内核可能产生明显的误差,提供了Scharr函数,结果更加精确 /* CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT ); The function computes the first x- or y- spatial image derivative using the Scharr operator. The call @brief Calculates the first x- or y- image derivative using Scharr operator. \f[\texttt{Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType)}\f] is equivalent to \f[\texttt{Sobel(src, dst, ddepth, dx, dy, CV\_SCHARR, scale, delta, borderType)} .\f] @param src input image. @param dst output image of the same size and the same number of channels as src. @param ddepth output image depth, see @ref filter_depths "combinations" @param dx order of the derivative x. @param dy order of the derivative y. @param scale optional scale factor for the computed derivative values; by default, no scaling is applied (see getDerivKernels for details). @param delta optional delta value that is added to the results prior to storing them in dst. @param borderType pixel extrapolation method, see cv::BorderTypes @sa cartToPolar */ //【1】载入原始图 Mat src = imread("1.jpg"); //工程目录下应该有一张名为1.jpg的素材图 //【2】显示原始图 imshow("【原始图】sobel边缘检测", src); //【3】求 X方向梯度 Sobel(src, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT); convertScaleAbs(grad_x, abs_grad_x); imshow("【效果图】 X方向Sobel", abs_grad_x); //【4】求Y方向梯度 Sobel(src, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT); convertScaleAbs(grad_y, abs_grad_y); imshow("【效果图】Y方向Sobel", abs_grad_y); //【5】合并梯度(近似) addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst); imshow("【效果图】整体方向Sobel", dst); waitKey(0); return 0; }
二阶微分算子,定义为梯度的散度
Mat src,src_gray,dst1; GaussianBlur(src, src, Size(3, 3), 0, 0, BORDER_DEFAULT); cvtColor(src, src_gray, COLOR_RGB2GRAY); Laplacian(src_gray, dst1, CV_16S, 3, 1, 0, BORDER_DEFAULT); convertScaleAbs(dst1, dst1); imshow("拉普拉斯", dst1);
/* -----------程序实现功能----------------- 编写函数功能: 依附滚动条的Canny,Sobel边缘检测 Scharr滤波器应用于图片上面 */ /* 函数回忆 createTrackbar()函数 需要参数:依附哪个窗口,设定滑动条范围及初始位置,响应函数 CV_EXPORTS int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, TrackbarCallback onChange = 0, void* userdata = 0); TrackbarCallback即执行主程序 */ /* 三个检测算子的参数定义 CV_EXPORTS_W void Canny( InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false ); CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT ); CV_EXPORTS_W void Scharr( InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT ); */ #include<opencv2/opencv.hpp> #include<iostream> using namespace cv; using namespace std; Mat g_srcImage, g_srcGrayImage, g_dstImage; //Canny边缘检测相关变量 /* CV_EXPORTS_W void Canny( InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false ); */ Mat g_cannyDetectedEdges; int g_cannyLowThreshold = 1;//TrackBar位置参数 //Sobel边缘检测相关变量 Mat g_sobelGradient_X, g_sobelGradient_Y; Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y; int g_sobelKernelSize = 1;//TrackBar位置参数 //Scharr滤波器相关变量 Mat g_scharrGradient_X, g_scharrGradient_Y; Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y; //-----------------------------------【全局函数声明部分】-------------------------------------- // 描述:全局函数声明 //----------------------------------------------------------------------------------------------- static void on_Canny(int, void*);//Canny边缘检测窗口滚动条的回调函数 static void on_Sobel(int, void*);//Sobel边缘检测窗口滚动条的回调函数 void Scharr();//封装了Scharr边缘检测相关代码的函数 void ProgramMessage(); int main() { system("color 2F"); ProgramMessage(); //载入原图 g_srcImage = imread("1.jpg"); if (!g_srcImage.data) { printf("Oh,no,读取srcImage错误~! \n"); return false; } //显示原始图 namedWindow("【原始图】"); imshow("【原始图】", g_srcImage); // 创建与src同类型和大小的矩阵(dst) g_dstImage.create(g_srcImage.size(), g_srcImage.type()); // 将原图像转换为灰度图像 cvtColor(g_srcImage, g_srcGrayImage, COLOR_BGR2GRAY); // 创建显示窗口 namedWindow("【效果图】Canny边缘检测", WINDOW_AUTOSIZE); namedWindow("【效果图】Sobel边缘检测", WINDOW_AUTOSIZE); // 创建trackbar createTrackbar("Canny:", "【效果图】Canny边缘检测", &g_cannyLowThreshold, 120, on_Canny); createTrackbar("Sobel:", "【效果图】Sobel边缘检测", &g_sobelKernelSize, 3, on_Sobel); // 调用回调函数 on_Canny(0, 0); on_Sobel(0, 0); //调用封装了Scharr边缘检测代码的函数 Scharr(); waitKey(0); return 0; } void ProgramMessage() { cout << "\n\n\n\t\t-------------------程序实现功能-------------------" << endl; cout << "\n\n\n\t\t依附滚动条的Canny,Sobel边缘检测,Scharr滤波器边缘检测" << endl; cout << "\n\n\n\t\tCanny算子的双阈值中高阈值为低阈值的三倍" << endl; } //-----------------------------------【on_Canny( )函数】---------------------------------- // 描述:Canny边缘检测窗口滚动条的回调函数 //----------------------------------------------------------------------------------------------- void on_Canny(int, void*) { // 先使用 3x3内核来降噪 blur(g_srcGrayImage, g_cannyDetectedEdges, Size(3, 3)); // 运行我们的Canny算子 Canny(g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold * 3, 3); //先将g_dstImage内的所有元素设置为0 g_dstImage = Scalar::all(0); //使用Canny算子输出的边缘图g_cannyDetectedEdges作为掩码,来将原图g_srcImage拷到目标图g_dstImage中 g_srcImage.copyTo(g_dstImage, g_cannyDetectedEdges); //显示效果图 imshow("【效果图】Canny边缘检测", g_dstImage); } //-----------------------------------【on_Sobel( )函数】---------------------------------- // 描述:Sobel边缘检测窗口滚动条的回调函数 //----------------------------------------------------------------------------------------- void on_Sobel(int, void*) { // 求 X方向梯度 Sobel(g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2 * g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); convertScaleAbs(g_sobelGradient_X, g_sobelAbsGradient_X);//计算绝对值,并将结果转换成8位 // 求Y方向梯度 Sobel(g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2 * g_sobelKernelSize + 1), 1, 1, BORDER_DEFAULT); convertScaleAbs(g_sobelGradient_Y, g_sobelAbsGradient_Y);//计算绝对值,并将结果转换成8位 // 合并梯度 addWeighted(g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage); //显示效果图 imshow("【效果图】Sobel边缘检测", g_dstImage); } //-----------------------------------【Scharr( )函数】---------------------------------- // 描述:封装了Scharr边缘检测相关代码的函数 //----------------------------------------------------------------------------------------- void Scharr() { // 求 X方向梯度 Scharr(g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT); convertScaleAbs(g_scharrGradient_X, g_scharrAbsGradient_X);//计算绝对值,并将结果转换成8位 // 求Y方向梯度 Scharr(g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT); convertScaleAbs(g_scharrGradient_Y, g_scharrAbsGradient_Y);//计算绝对值,并将结果转换成8位 // 合并梯度 addWeighted(g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage); //显示效果图 imshow("【效果图】Scharr滤波器", g_dstImage); }Hough变换