RV1126 NO.39:OPENCV查找图形轮廓并画框
一.实战简介
经过上一章节的讲解,我们对整个OPENCV提取轮廓的API有了一个大致的了解。本章节主要是讲解如何通过代码来实现OPENCV的轮廓检测提取然后进行画框。具体的如下图:
上面是我们整个代码的第一步,调用imread的API读取本地的三通道图片。
完成轮廓检测,需要做以上步骤。分别是imread读取图片(这个图片默认是3通道)、利用cvtColor把8VU3的三通道图片转换成灰度图(8VU1)、调用Canny对灰度图像进行边缘检测、调用findContours去查找轮廓、循环轮廓数量然后调用drawContours进行画框操作。
二.对代码进行拆分讲解
2.1. 读取需要处理的图片
Mat img = imread("shape.png"); //读取shape图片
上面是我们整个代码的第一步,调用imread的API读取本地的三通道的代码。
2.2. 对图片进行灰度处理并进行边缘检测
Mat imgGray;
cvtColor(img, imgGray, COLOR_RGB2GRAY); //把彩色图像转换成GRAY灰度图由于读取到的图片是三通道的图像,所以我们要把三通道的图像利用cvtColor的方式进行灰度处理,然后再调用Canny对灰度图像进行边缘检测处理。最小阈值threadhold1是25,最大阈值threadhold2是75;大于75表示的是强边缘需要保存下来的,小于25是弱边缘需要忽略的,25-75之间的边缘则会用算法进行候选。
2.3. 调用findContours去查找图像轮廓
findContours(imgCanny, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE); //查询轮廓,MODE是外部轮廓检测RETR_EXTERNAL,method是CHAIN_APPROX_NONE处理完边缘后,就findContours可以通过findContours去查找所有图像的轮廓了,由于我们检测的图像没有内嵌的形状,所以我们选择RETR_EXTERNAL的模式只检测外轮廓,Method的方法则选择CHAIN_APPROX_SIMPLE存储所有的轮廓点。注意:contours一般是用vector<vector<point>>表示,hierarchy通常用vector<Vec4i>表示,它都是由点的集合来保存的.
2.4. 获取轮廓数量后循环并且保存
Mat drawing = Mat::zeros(imgCanny.size(), CV_8UC3);for (int i = 0; i < contours.size(); i++){Scalar color = Scalar(255,255,0);drawContours(drawing, contours, i, color,1,8,hierarchy ); //对图像轮廓进行画框}imwrite("contour.jpg", drawing);最后我们需要用for循环轮廓数量,并且调用drawContours去描绘每个图像的轮廓,轮廓的颜色是Scalar(255,255,0)青色,并保存到新的Mat矩阵里面。
完整代码:
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>using namespace cv;
using namespace std;int main()
{Mat img = imread("shape.png"); //读取shape图片Mat imgGray;cvtColor(img, imgGray, COLOR_RGB2GRAY); //把彩色图像转换成GRAY灰度图Mat imgCanny;Canny(imgGray, imgCanny, 25 ,75); //Canny对图像进行边缘检测,弱阈值25,强阈值75vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(imgCanny, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE); //查询轮廓,MODE是外部轮廓检测RETR_EXTERNAL,method是CHAIN_APPROX_NONE//创建空白画布为轮廓绘制提供干净的画布背景Mat drawing = Mat::zeros(imgCanny.size(), CV_8UC3);for (int i = 0; i < contours.size(); i++){Scalar color = Scalar(255,255,0);drawContours(drawing, contours, i, color,1,8,hierarchy ); //对图像轮廓进行画框}imwrite("contour.jpg", drawing);return 0;
}最终结果:
经过上述几个步骤后,我们来看看运行的效果:图1是原图片;图2是经过轮廓提取后的图像,可以看到经过经过轮廓提取后,都可以清晰地画出每个形状的轮廓。

