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,强阈值75
vector<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是经过轮廓提取后的图像,可以看到经过经过轮廓提取后,都可以清晰地画出每个形状的轮廓。

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐

所有评论(0)