📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨
📢:不妨浏览一下我的博客主页【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;
}