在Hough检测一章中出现了代码验证出错问题,由于进度原因在此只贴出另外一个相关的链接,后期修复好程序的Bug后再将具体内容贴上详情文章及代码请查阅轮廓,直线圆的拟合
边缘检测
Canny边缘检测
查阅函数可得原型
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;
}
Sobel
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变换