【OpenCV基础】凸包检测、Harris角点检测、Canny边缘检测

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨
📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852
📢:文章若有幸对你有帮助,可点赞 👍 收藏 ⭐不迷路🙉
📢:内容若有错误,敬请留言 📝指正!原创文,转载请注明出处


一、凸包检测

凸包检测的方法:

(1)Graham扫描法

(2)Jarvis步进法

方法详细解释参考:https://blog.csdn.net/shuiyixin/article/details/104625013

API

1.drawContours

作用:绘制轮廓

函数原型及其参数如下:

void drawContours( InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true );

参数含义如下:

(1)InputArray类型的points,输入二维点集,存储在std::vector或Mat中。

(2)OutputArray类型的hull,输出凸包。它可以是索引的整数向量,也可以是点的向量。

(3)bool类型的clockwise,方向标志。如果为真,则输出凸包将顺时针方向。否则,它是逆时针方向的。假定坐标系的X轴指向右侧,Y轴指向上方。

(4)bool类型的returnPoints,操作标志。对于矩阵,当标志为真时,函数返回凸壳点。否则,返回凸壳点的索引。

2.convexHull

作用:凸包检测,从检测到的图像的轮廓点,通过函数convexhull转化成凸包上点的坐标

函数原型及其参数如下:

void convexHull(InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true)
convexHull(Mat(contours[i]), hull[i], false);

参数含义如下:

1.InputArray points: 得到的点集,一般是用图像轮廓函数求得的轮廓点

2.OutputArray hull: 输出的是凸包的二维xy点的坐标值,针对每一个轮廓形成的

3.bool clockwise = false: 表示凸包的方向,顺时针或者逆时针

4.bool returnPoint = true: 表示返回点还是点地址的索引

全部代码-有滑动条

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

RNG rng(12345);

Mat src, src_gray, dst,threshold_output;
int threshold_value = 100;
void Threshold_Callback(int, void*) {
	Mat src_copy = src.clone();
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	threshold(src_gray, threshold_output, 100, 255, THRESH_BINARY);

	//检测轮廓
	findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

	vector<vector<Point> >hull(contours.size());
	for (int i = 0; i < contours.size(); i++)
	{//检测轮廓的凸包
		convexHull(Mat(contours[i]), hull[i], false);
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		//绘制凸包
		drawContours(src, hull, i, color, 2, 8, vector<Vec4i>(), 0, Point());
		imshow("output_win", src);
	}
}

int main()
{
	src = imread("D:/images/hand.jpg");
	if (!src.data)
	{
		cout << "could not load image !";
		waitKey(0);
		return -1;
	}

	imshow("input_win", src);
	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	blur(src_gray, src_gray, Size(3, 3));

	Threshold_Callback(0, 0);
	createTrackbar("trackbar_title", "output_win", &threshold_value, 255, Threshold_Callback);

	waitKey(0);
	return 0;
}

效果展示

在这里插入图片描述

部分代码-无滑动条

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

RNG rng(12345);


int main()
{
	Mat src, src_gray, dst, threshold_output;
	src = imread("D:/images/hand.jpg");
	if (!src.data)
	{
		cout << "could not load image !";
		waitKey(0);
		return -1;
	}
	imshow("input_win", src);
	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	blur(src_gray, src_gray, Size(3, 3));

	Mat src_copy = src.clone();
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	int threshold_value = 100;
	threshold(src_gray, threshold_output, 100, 255, THRESH_BINARY);
	//检测轮廓
	findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	//检测轮廓的凸包上的点坐标
	vector<vector<Point> >hull(contours.size());
	for (int i = 0; i < contours.size(); i++)
	{
		convexHull(Mat(contours[i]), hull[i], false);
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		//绘制凸包
		drawContours(src, hull, i, color, 2, 8, vector<Vec4i>(), 0, Point());
		imshow("output_win", src);
	}

	waitKey(0);
	return 0;
}

二、Harris角点检测

角点

1.角点的定义:如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,那么我们就把它称之为角点

2.角点又称为:兴趣点(interest points),或称作关键点(keypoints),但是要注意跟特征点(feature points)之间的区别,特征点有角点和描述子组成。

3.角点的特点:

1.一阶导数(即灰度的梯度)的局部最大所对应的像素点;
2.两条及两条以上边缘的交点;
3.图像中梯度值和梯度方向的变化速率都很高的点;
4.角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向

4.角点检测的定义:Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中。也称为特征点检测。

5.角点检测方法的一个很重要的评价标准:是其对多幅图像中相同或相似特征的检测能力,并且能够应对光照变化、图像旋转等图像变化。

Harris角点

API-cornerHarris

函数原型及其参数如下:

cornerHarris(InputArray src,OutputArray dst, int blockSize, int ksize, double k, intborderType=BORDER_DEFAULT )

参数含义如下:

1.InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
2.OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型。
3.int类型的blockSize,表示邻域的大小,更多的详细信息在cornerEigenValsAndVecs()中有讲到。
4.int类型的ksize,表示Sobel()算子的孔径大小。
5.double类型的k,Harris参数。
6.int类型的borderType,图像像素的边界模式,注意它有默认值BORDER_DEFAULT。更详细的解释,参考borderInterpolate( )函数。

三、部分代码-无滑动条

3.1部分代码

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

int main()
{
	Mat src, gray_src, dst, norm_dst;
	src = imread("D:/images/lena.png");
	if (src.empty())
	{
		cout << "图片为空" << endl;
		return -1;
	}
	imshow("input title", src);

	cvtColor(src, gray_src, COLOR_BGR2GRAY);

	int thres_value = 130;
	dst = Mat::zeros(gray_src.size(), CV_32FC1);
	cornerHarris(gray_src, dst, 2, 3, 0.04, BORDER_DEFAULT);
	normalize(dst, norm_dst, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
	convertScaleAbs(norm_dst, norm_dst);
	Mat resultImg = src.clone();

	for (int row = 0; row < resultImg.rows; row++)
	{
		uchar* currentRow = norm_dst.ptr(row);
		for (int col = 0; col < resultImg.cols; col++)
		{
			int value = (int)*currentRow;

			if (value > thres_value)
			{
				circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);
			}
			currentRow++;
		}
	}
	imshow("outputTitle", resultImg);

	waitKey(0);
	return 0;
}

3.2效果展示

在这里插入图片描述

四、全部代码-有滑动条

4.1全部代码

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

int thres_value = 130;
Mat src, gray_src, dst, norm_dst;

void Harris_demo(int, void *)
{
	dst = Mat::zeros(gray_src.size(), CV_32FC1);
	cornerHarris(gray_src, dst, 2, 3, 0.04, BORDER_DEFAULT);
	normalize(dst, norm_dst, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
	convertScaleAbs(norm_dst, norm_dst);
	Mat resultImg = src.clone();

	for (int row = 0; row < resultImg.rows; row++)
	{
		uchar* currentRow = norm_dst.ptr(row);
		for (int col = 0; col < resultImg.cols; col++)
		{
			int value = (int)*currentRow;

			if (value > thres_value)
			{
				circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);
			}
			currentRow++;
		}
	}
	imshow("outputTitle", resultImg);
}

int main()
{
	src = imread("D:/images/lena.png");
	if (src.empty())
	{
		cout << "图片为空" << endl;
		return -1;
	}
	imshow("input title", src);
	cvtColor(src, gray_src, COLOR_BGR2GRAY);
	Harris_demo(0, 0);
	createTrackbar("Harris", "outputTitle", &thres_value, 255, Harris_demo);

	waitKey(0);
	return 0;
}

4.2效果展示

在这里插入图片描述

三、Canny边缘检测

Canny边缘检测所有操作步骤

Canny算法使用前:

高斯模糊 - GaussianBlur
目的:高斯模糊了之后,能去掉一些不太关注的边缘,使后续canny算子提取到的边缘更好。

Canny算法所用的API已经包含以下步骤:

1.灰度转换 - cvtColor
2.计算梯度 – Sobel/Scharr
3.非最大信号抑制
4.高低阈值输出二值图像

API-Canny

函数原型以及所用的参数如下:

Canny( src, edges, threshold1, threshold2, apertureSize = 3, bool L2gradient = false);

参数含义如下:

1.src:输入图像
2.edges:输出边缘图;单通道8位图像,其大小与图像相同。
3…threshold1:滞后过程的第一个阈值。
4…threshold2:滞后过程的第二个阈值。 T1, T2为像素阈值,大于T2的像素值都保留,小于T1都去除,从高于T2的像素出发,凡是大于T1而且相互连接的,都保留。最终得到一个输出二值图像。推荐的高低阈值比值为 T2: T1 = 3:1/2:1其中T2为高阈值,T1为低阈值
5.apertureSize:Sobel运算符的孔径大小。
6.L2gradient:一个标志,指示是否应使用更精确的L2来计算图像渐变幅度(L2gradient=true),或者是否应使用默认的L1(L2gradient=false)。

部分代码-无滑动条

代码

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat img, src;
	img = imread("D:/images/lena.png");
	if (img.empty())
	{
		cout << "could not load image !";
		return -1;
	}
	imshow("【输入图像】", img);

	GaussianBlur(img, img, Size(5, 5), 0, 0);//高斯模糊操作
	Canny(img, src, 115, 255);//canny边缘检测操作

	imshow("边缘检测", src);
    bitwise_not(src, src);//颜色取反操作
	imshow("颜色取反后", src);
	waitKey(0);
	return 0;
}

显示效果

在这里插入图片描述
在这里插入图片描述

全部代码-设置滑动条

代码

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

Mat src, src_dst, src_canny, src_bitwise;
void Canny_change(int pos, void*) {
	GaussianBlur(src, src_dst, Size(3, 3), 0, 0);
	Canny(src_dst, src_canny, pos, 255, 3);
	imshow("src_canny", src_canny);
	bitwise_not(src_canny, src_bitwise);
	imshow("src_bitwise", src_bitwise);
}

int main()
{
	src = imread("D:/images/lena.png");
	Canny_change(0, 0);
	createTrackbar("threshold", "src_bitwise", 0, 255, Canny_change);

	waitKey(0);
	return 0;
}

显示效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望闻问嵌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值