[Learning OpenCV入门 3]OpenCV的图像变换

在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变换


你可能感兴趣的:([Learning OpenCV入门 3]OpenCV的图像变换)