《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(一)查找并绘制轮廓
第8章 图像轮廓与图像分割修复
8.1 查找并绘制轮廓
8.1.1 寻找轮廓:findContours()函数
1.作用:在二值图像中寻找轮廓
2.函数原型:
void findcontours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())
3.参数说明:
(1)输入图像,8位单通道图像,图像非零像素被保留为0,所以图像为二进制,可以使用cmopare()、inrange()、threshold()、adaptivethreshold()、canny()等函数由灰度图或彩色图创建二进制图像
(2)检测到的轮廓,每个轮廓存储为一个点向量,即用point类型的vector表示
(3)可选的输出向量,包含图像的拓扑信息,作为轮廓数量的表示,每个轮廓contours[i]对应4个hierarchy元素,contours[i][0]~contours[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,对应的hierarchy[i]值设为负数
(4)轮廓检索模式,取值:
(5)轮廓近似办法,取值:
(6)每个轮廓点的可选偏移量,默认值Point()
4.示例:
vector<vector<Point>>contours;
findContours(image,contours,RETR_EXTERNAL,CHAIN_APPROX_NONE);
8.1.2 绘制轮廓:drawContours()函数
1.作用:用于在图像中绘制外部或内部轮廓
2.函数原型:
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point())
3.参数说明:
(1)目标图像
(2)输入轮廓
(3)轮廓绘制指示变量,负值表示绘制所有轮廓
(4)轮廓颜色
(5)轮廓线条粗细度,默认值1,负值会绘制在轮廓内部
(6)线条类型,默认8,可取值:
(7)可选的层次结构信息,默认值noArray()
(8)用于绘制轮廓的最大等级,默认值INT_MAX
(9)可选的轮廓偏移参数,默认Point()
4.示例:
Mat result(image.size(),CV_8U,cv::Scalar(255));
drawContours(result,contours,-1,Scalar(0),3,8);
8.1.3 示例程序
1.查找并绘制轮廓示例
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{//以二值图模式载入并显示原图Mat srcImage = imread("girl.jpg",0);if (!srcImage.data){printf("图片载入失败~!\n");return false;}imshow("【原始图】", srcImage);//srcImage取大于阈值119的部分srcImage = srcImage > 119;imshow("取阈值后的原始图", srcImage);//初始化结果图Mat dstImage;dstImage=Mat::zeros(srcImage.rows,srcImage.cols, CV_8UC3);//定义轮廓和层次结构vector<vector<Point>>contours;vector<Vec4i>hierarchy;//查找轮廓findContours(srcImage, contours, hierarchy,RETR_CCOMP, CHAIN_APPROX_SIMPLE);//遍历所有顶层轮廓,以随机颜色绘制每个连接组件颜色for (int index = 0; index >= 0; index = hierarchy[index][0])//令index等于当前轮廓的下一个轮廓来更新循环,没有下一轮廓时,hierarchy[i][0]为负值,循环结束{Scalar color(rand() & 255, rand() & 255, rand() & 255);drawContours(dstImage, contours, index,color, FILLED, 8,hierarchy);}//显示轮廓图imshow("【轮廓图】", dstImage);waitKey(0);return 0;
}
运行效果:
2.综合示例
/*
效果:利用图像平滑和边缘检测,根据滑动条调节,动态检测图形轮廓
*/
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace cv;
using namespace std;
#define WINDOW_NAME1 "【原始图】"
#define WINDOW_NAME2 "【轮廓图】"
//全局变量
Mat g_srcImage,g_grayImage,g_cannyMat_output,g_dstImage;
int g_nThresh = 80;
int g_nThresh_max = 255;
RNG g_rng(12345);
vector<vector<Point>>g_vContours;
vector<Vec4i>g_vHierarchy;
//全局函数
static void ShowHelpText();
static void on_ThreshChange(int, void*);
int main()
{//改变console字体颜色system("color 1F");ShowHelpText();//载入原图g_srcImage = imread("girl.jpg", 1);if (!g_srcImage.data){printf("图片载入失败~!\n");return false;}//创建窗口namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);imshow(WINDOW_NAME1, g_srcImage);//转成灰度图并模糊化降噪cvtColor(g_srcImage, g_grayImage, CV_BGR2GRAY);blur(g_grayImage, g_grayImage, Size(3, 3));//创建滚动条并初始化createTrackbar("canny阈值", WINDOW_NAME2, &g_nThresh, g_nThresh_max, on_ThreshChange);on_ThreshChange(0, 0);waitKey(0);return 0;
}
static void on_ThreshChange(int, void*)
{//canny算子Canny(g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh * 2, 3);//查找轮廓findContours(g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//绘制轮廓Mat g_dstImage = Mat::zeros(g_srcImage.rows, g_srcImage.cols, CV_8UC3);//或 for (int index = 0; index >= 0; index = g_vHierarchy[index][0])for (int index = 0; index < g_vContours.size(); index++){Scalar color(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));//任意值drawContours(g_dstImage, g_vContours, index, color, 2, 8, g_vHierarchy, 0, Point());}//显示效果图imshow(WINDOW_NAME2, g_dstImage);
}
static void ShowHelpText()
{printf("\n\n\t欢迎来到【在图形中寻找轮廓】示例程序!\n\n");printf("\n\n\t操作说明:\n\n");printf("\t\t键盘任意键-退出程序\n\n");printf("\t\t滑动滚动条-改变canny阈值\n");
}
运行效果:
《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(一)查找并绘制轮廓相关推荐
- 原创 OpenCV3编程入门 学习笔记(总)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_36163358/article/ ...
- OpenCV3编程入门 学习笔记(总)
OpenCV3编程入门 学习笔记 2018.12.12-2018.12.29 此博客为在看过毛星云版<OpenCV3编程入门>后所总结的一本笔记,可供复习使用. 文章目录 OpenCV3编 ...
- Opencv3编程入门学习笔记(五)之通道分离(split)与合并(merge)
若要对Opencv中(BGR)颜色通道进行单一处理,那必然会涉及到通道分离(split)与合并(merge).那么本篇博客笔者记录了两个方法的使用方法和案例.案例来源于<Opencv3编程入门学 ...
- Opencv3编程入门学习笔记(三)之访问图像像素的三种方法
访问图像像素的三种方法:指针访问,迭代器访问,动态地址访问.访问最快的为指针访问,以下算法在几毫秒,但指针访问容易造成内存泄漏:其次为迭代器访问:最后为动态地址访问. 以下程序是根据<OpenC ...
- 【OpenCV3编程入门学习笔记】——第1章 邂逅OpenCV
邂逅OpenCV 文章目录 邂逅OpenCV 前言 1.1 OpenCV周边概念认知 1.1.1 图像处理.计算机视觉与OpenCV 1.1.2 OpenCV概述 1.1.3 起源及发展 1.1.4 ...
- 【OpenCV3编程入门学习笔记】——第3章 HighGUI图形用户界面初步
文章目录 前言 3.1 图形的载入.显示和输出到文件 3.1.1 OpenCV的命名空间 3.1.2 Mat类简析 3.1.3 图像的载入与显示概述 3.1.4 图像的载入:imread()函数 3. ...
- Opencv3编程入门学习笔记(四)之split通道分离Debug过程中0xC0000005内存访问冲突问题
这是笔者学习<Opencv3编程入门>的第四篇博客,这篇博客主要是解决在Windows系统下VS 2013中Debug含有split分离通道色彩函数时报出的0xC0000005内存访问冲突 ...
- Opencv3编程入门学习笔记(二)之显式创建Mat对象
以下总结是基于<Opencv3编程入门>一书4.1节总结的内容进行验证与总结,验证环境均为Windows10 ---VS2013 C++环境,验证Opencv3.0提供的开发包. 1. 方 ...
- 01.Java 编程入门学习笔记20210307
Java 编程入门学习笔记-day01 第0章:编程入门 1.计算机的概述 计算机 = 硬件 + 软件 1.1硬件:冯诺依曼体系 CPU: CPU的衡量标准:速度的计量单位是赫兹(Hz),1Hz相当于 ...
- Python快速编程入门#学习笔记01# |第一章 :Python基础知识 (Python发展历程、常见的开发工具、import模块导入)
全文目录 ==先导知识== 1 认识Python 1.1.1 Python的发展历程 1.1.2 Python语言的特点 2. Python解释器的安装与Python程序运行 1.2.1 安装Pyth ...
最新文章
- 【技术综述】“看透”神经网络
- python元类简述
- 学会对mysql的增删改查_Go实现对MySQL的增删改查
- Java实现二维码技术探讨。
- 这些年遇到的坑爹问题汇总
- 37.rust属性.txt
- 视频加速方案的最优解 - Xilinx硬件加速技术专场
- 使用ASP.NET Atlas实现拖放(Drag Drop)效果(下)
- mac升级node版本(用n升级nodejs)
- linux sub减法指令出错,sparc的指令的一些总结
- word中 数字或者字母间距 突然变大
- nas linux手机照片备份,本身着手,组建简洁好用的NAS!(存储同步篇)
- bread 块设备读取函数解析(1)
- 众享比特副总裁陈鸿刚:区块链技术在工业互联网中的应用
- D3 CSV表格文件的读取详解
- opencv打卡50:闭运算cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
- 2022年茶艺师(初级)考试模拟100题及模拟考试
- 多层商厦广播播音及背景音乐系统解决方案
- 前端实习——Vue学习笔记(一)
- java doc字数_JAVA 仿 MS word 字数统计