OpenCV(C++) 入门示例

编程入门 行业动态 更新时间:2024-10-13 14:25:39

OpenCV(C++) 入门<a href=https://www.elefans.com/category/jswz/34/1770116.html style=示例"/>

OpenCV(C++) 入门示例

前言:本示例是本人为了帮老师带实验课现学现卖做的一个小项目,使用的方法不一定是最合适的,大家可以作为参考。


运行环境:Windows + OpenCV 3.4.1 + C++,环境配置大家自己找教程吧,网上教程很多。

项目目标:我们对工件进行检测,目标是识别出工件二维 bounding box,以及获取工件的中心点像素坐标和旋转角度。效果如下:

 原图

效果图


 代码如下:

#include<opencv2\opencv.hpp>
#include<iostream>using namespace std;
using namespace cv;int main()
{//	原图Mat srcImg = imread("1.png");Mat midImg;Mat dstImg = srcImg.clone();namedWindow("【原图】", WINDOW_NORMAL);imshow("【原图】", srcImg);//	灰度化cvtColor(srcImg, midImg,COLOR_BGR2GRAY);namedWindow("【灰度图】", WINDOW_NORMAL);imshow("【灰度图】", midImg);//	中值滤波medianBlur(midImg, midImg, 9);namedWindow("【滤波后】", WINDOW_NORMAL);imshow("【滤波后】", midImg);//	二值化threshold(midImg, midImg, 100, 255, 0);namedWindow("【二值图】", WINDOW_NORMAL);imshow("【二值图】", midImg);//	形态学滤波,开运算Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));morphologyEx(midImg, midImg, MORPH_OPEN, element);namedWindow("【开运算后】", WINDOW_NORMAL);imshow("【开运算后】", midImg);//	轮廓提取//	(注:六角螺母的外层轮廓为i=2时的轮廓,若只要该轮廓,将i替换为2即可)vector<vector<Point>> contours;findContours(midImg, contours, RETR_CCOMP, CHAIN_APPROX_SIMPLE);Mat midImg1 = Mat::zeros(midImg.rows, midImg.cols, CV_8UC3);for (int i = 0; i < contours.size(); i++){Scalar color(255, 255, 255);drawContours(midImg1, contours, i, color, 2);}namedWindow("【轮廓图】", WINDOW_NORMAL);imshow("【轮廓图】", midImg1);//	创建最小包围矩形及获取中心点图像坐标//	(注:六角螺母的外层轮廓为i=2时的轮廓,若只要该轮廓,将i替换为2即可)for (int i = 0; i < contours.size(); i++){//每个轮廓vector<Point> points = contours[i];//对给定的2D点集,寻找最小面积的包围矩形RotatedRect box = minAreaRect(Mat(points));Point2f vertex[4];//将box 中存储的4 个顶点的坐标 存储到vertex[0]~vertex[3]中去box.points(vertex);//打印中心点位置及外接矩形角度cout << "中心点位置(第" << i << "条轮廓):" << box.center << endl;cout << "外接矩形角度(第" << i << "条轮廓):" << box.angle << endl;//绘制出最小面积的包围矩形line(dstImg, vertex[0], vertex[1], Scalar(200, 255, 200), 3, LINE_AA);line(dstImg, vertex[1], vertex[2], Scalar(200, 255, 200), 3, LINE_AA);line(dstImg, vertex[2], vertex[3], Scalar(200, 255, 200), 3, LINE_AA);line(dstImg, vertex[3], vertex[0], Scalar(200, 255, 200), 3, LINE_AA);//绘制中心的光标,为了容易理解,此处为手动计算中心点,也可以直接使用 box.centerPoint center, l, r, u, d;center.x = (vertex[0].x + vertex[2].x) / 2.0;center.y = (vertex[0].y + vertex[2].y) / 2.0;l.x = center.x - 10;l.y = center.y;r.x = center.x + 10;r.y = center.y;u.x = center.x;u.y = center.y - 10;d.x = center.x;d.y = center.y + 10;line(dstImg, l, r, Scalar(200, 255, 200), 2, LINE_AA);line(dstImg, u, d, Scalar(200, 255, 200), 2, LINE_AA);}namedWindow("【最小包围矩形及获取中心点】", WINDOW_NORMAL);imshow("【最小包围矩形及获取中心点】", dstImg);waitKey(0);
}
  • 注:如上代码中的 1.png 即为如上原图
  • 注:展示效果为代码中 i = 2 的输出结果

经代码处理的中间图像如下:​​​​​​

图像滤波的目的是在最大限度地减少噪声干扰的同时,尽可能多地保留目标的特征。

为了克服常见的线性滤波器带来的图像细节模糊以及保护边缘信息,我们的滤波处理方式选择非线性滤波中的中值滤波。

中值滤波的的基本思想是用像素点邻域的灰度值的中值来代替该像素点的灰度值,从而消除孤立的噪声点。该方法对于斑点噪声和椒盐噪声来说尤其有用,因为它不依赖于邻域内哪些与典型值差别很大的值。并且中值滤波具有保存边缘的特性,能很好的保护边缘信息。

  

膨胀与腐蚀是一对相反的操作,都是对图像中高亮部分而言的。简单来讲,膨胀是图像中的高亮部分进行膨胀,类似于“领域扩张”,效果为比原来拥有更大面积的高亮区域;腐蚀是图像中高亮部分被腐蚀,类似于“领域被蚕食”,效果为比原来拥有更小面积的高亮区域。

开运算,其实就是先腐蚀后膨胀的过程。其表达式为: dst=open(src)=dilate(erode(src)) 。

文通过调用 OpenCV 中的 FindContours()函数实现对轮廓的提取,通过调用 minAreaRect()函数实现获取最小外接矩形,并通过该函数返回值中参数获取中心点及旋转角度。

  


以上代码也是可以实现多目标检测的,只需要根据输入图像稍微调整一下二值化操作中的阈值参数,即可以得到如下效果。

原图:

 效果图:

更多推荐

OpenCV(C++) 入门示例

本文发布于:2024-03-06 08:37:02,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1714865.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:示例   入门   OpenCV

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!