OpenCv学习笔记1-轮廓检测
一、轮廓检测的基本原理
实现思路:通过找出在一张图片中满足特定像素值的像素点,实现轮廓绘制。
实验流程: (1)颜色空间转换 (2)二值化处理 (3)腐蚀膨胀 (4)轮廓绘制
二、实验流程
1.颜色空间转换
实验第一步需要将RGB颜色空间转成HSV颜色空间,RGB对硬件友好,而HSV则对我们人眼友好,根据下面的表格我们可以得出需要的结果 例如我们如果想要框出这两车的车牌号,我们就可以直接用微信截图里的框(bushi),我们就可以把颜色为蓝色的点集寻找出来,使用阈值处理得到二值图
2.二值化处理
代码如下(示例):
// 转颜色空间
cvtColor(img, dst, CV_BGR2HSV);
Mat dstImage;
inRange(dst, Scalar(105, 53+90, 46), Scalar(114, 255, 255), dstImage);
3.腐蚀膨胀
腐蚀膨胀的主要作用就是去除噪声
腐蚀:遍历一个点周围的8个点,将当前点修改为周围点中的最小值 膨胀:遍历一个点周围的8个点,将当前点修改为周围点中的最大值 直接使用opencv中的现成库!
代码如下(示例):
// 转颜色空间
Mat dstImage1_5;
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
erode(dstImage, dstImage1_5, element, Point(-1, -1), 1, 0);
Mat dstImage1_75;
dilate(dstImage1_5, dstImage1_75, element, Point(-1, -1), 1);
前后效果图: 可以看出,左侧的噪声明显减少
4.轮廓绘制
第一步,找点集 我们在上面得到了二值图,即得到了想要部分(白色)和不想要部分,那么第二步,我们则需要找出边界的点集,使用以下函数即可
findContours(dstImage, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
第二步,找点集的外接矩形 在上面的函数处理后,返回的contours是一个点集,我们对这些点集直接使用下面函数寻找其外接矩形
boundRect[i] = boundingRect(Mat(contours[i]));
对返回的多个矩形通过长宽进行筛选,最终得到正确结果
double wh = boundRect[i].width / boundRect[i].height;
if(wh>2&& boundRect[i].height>20)
完整代码
#include<iostream>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include<cstdlib>
#include<ctime>
using namespace std;
using namespace cv;
int main() {
Mat img;
Mat dst;
Mat result;
img = imread("C:\\Users\\EDZ\\Desktop\\1.jpg");
cvtColor(img, dst, CV_BGR2HSV);
Mat dstImage;
inRange(dst, Scalar(105, 53+90, 46), Scalar(114, 255, 255), dstImage);
Mat dstImage1_5;
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
erode(dstImage, dstImage1_5, element, Point(-1, -1), 1, 0);
Mat dstImage1_75;
dilate(dstImage1_5, dstImage1_75, element, Point(-1, -1), 1);
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(dstImage, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
vector<Rect> boundRect(contours.size());
vector<RotatedRect> box(contours.size());
Point2f rect[4];
for (int i = 0; i < contours.size(); i++)
{
box[i] = minAreaRect(Mat(contours[i]));
boundRect[i] = boundingRect(Mat(contours[i]));
box[i].points(rect);
double wh = boundRect[i].width / boundRect[i].height;
if(wh>2&& boundRect[i].height>20){
rectangle(img, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8);
for (int j = 0; j < 4; j++)
{
line(img, rect[j], rect[(j + 1) % 4], Scalar(0, 255, 0), 2, 8);
}
}
imshow("结果图", img);
}
namedWindow("Image");
imshow("Image", img);
namedWindow("二值化后的图像1");
imshow("二值化后的图像1", dstImage);
namedWindow("腐蚀膨胀后的图像1");
imshow("腐蚀膨胀后的图像1", dstImage1_75);
waitKey(0);
return 0;
}
效果图:
|