Opencv——查找并绘制凸包、凸包与轮廓的关系

定义

给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型。
理解物体形状或轮廓的一 种比较有用的方法便是计算一个物体的凸包,然后计算其凸缺陷(convexity defects)。
凸包

检测凸包

opencv自带函数:convexHull()

参数解释:
参数解释

示例1:检测随机点群的凸包(只有一个凸包)

代码以及注释:

#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>using namespace cv;
using namespace std;//===========================凸包检测基础====================
//先随机生成3~103个坐标值随机的彩色点,然后利用convexHull,对链接起来的图形求凸包
int main()
{Mat image(600, 600, CV_8UC3);//RNG& rng = theRNG();		//返回一个当前线程的随机数生成器		RNG类可以产生多种类型的随机数,故使用时需要指定是哪种类型的RNG rng((unsigned)time(NULL));		//这样每次重新运行会产生不一样的随机数while (1){//参数初始化char key;int count = (unsigned)rng % 100 + 3;	//随机生成点的数量vector<Point> points;		//点值//随机生成点坐标for (int i = 0;i < count;i++){Point point;point.x = rng.uniform(image.cols / 4, image.cols * 3 / 4);point.y = rng.uniform(image.rows / 4, image.rows * 3 / 4);points.push_back(point);			//将此时生成的点数据送入	points数组的最后一个}//检测凸包(这里认为凸包只有一个)vector<int> hull;		//存储一个凸包的边的一维数组	convexHull(Mat(points),hull,true);//输入二维点集,输出找到的凸包//绘制出随机颜色的点image = Scalar::all(0);		//背景for (int i = 0;i < count;i++){circle(image,points[i],3,Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255)),FILLED,LINE_AA);}//准备参数int hullcount = (int)hull.size();		//凸包的边数(因为只有一个凸包,而凸包是由边构成的序列,所以返回序列长度,应该返回的是边的个数)Point point0 = points[hull[hullcount - 1]];		//连接凸包边的坐标点		最后一条边的坐标点//绘制凸包的边for (int i = 0;i < hullcount;i++){Point point = points[hull[i]];		//points[hull[i]]表示构成凸包边的某点(因为凸包是一个点集合最外面的点连接起来的区域)line(image, point0, point, Scalar(255, 255, 255), 2, LINE_AA);point0 = point;}//显示效果图imshow("凸包检测示例",image);//按下ESC程序退出//key = (char)waitKey();//if (key == 27) break;waitKey(1000);		//每秒显示一次}return 0;
}

演示效果:
示例

示例2:动态检测并绘制轮廓和凸包(一个轮廓对应一个凸包)

//===========================动态检测绘制图形的轮廓和凸包====================//=================全局变量声明=================
Mat g_srcImage;
Mat g_grayImage;
int g_nThresh = 50;
int g_nThresh_max = 255;
RNG g_rng(12345);
Mat srcImage_copy = g_srcImage.clone();
Mat g_thresholdMat_output;
vector<vector<Point>> g_vContours;
vector<Vec4i> g_vHierarchy;//=============全局函数声明===============
void on_ThreshChange(int,void*);
int main()
{// Read image 读取图像SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字体为绿色//载入原图g_srcImage = imread("D:\\opencv_picture_test\\lena.jpg",1);//Mat srcImage = imread("D:\\opencv_picture_test\\形态学操作\\孔洞.png", 0);	//读取灰度图//转换成灰度并且模糊化降噪cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);blur(g_grayImage, g_grayImage, Size(3, 3));//创建窗口namedWindow("原始图窗口", WINDOW_AUTOSIZE);imshow("原始图窗口", g_srcImage);//创建滑动条并初始化createTrackbar("阈值", "原始图窗口", &g_nThresh,g_nThresh_max, on_ThreshChange);on_ThreshChange(0,0);waitKey(0);return 0;
}
void on_ThreshChange(int, void*)
{//用Canny算子检测边缘Canny(g_grayImage, g_thresholdMat_output, g_nThresh, g_nThresh * 2, 3);//寻找轮廓.findContours(g_thresholdMat_output, g_vContours, g_vHierarchy,RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//遍历每个轮廓,寻找其凸包vector<vector<Point> > hull( g_vContours.size());		//轮廓、凸包、点,构成三维数组	凸包的数组的大小等于轮廓的大小for (unsigned int i = 0;i<g_vContours.size();i++){convexHull(Mat (g_vContours[i]), hull[i],false);		//在轮廓数组中寻找凸包,存入对应的hull中}//绘出轮廓及其凸包Mat drawing = Mat::zeros(g_thresholdMat_output.size(), CV_8UC3);for (int i = 0; i < g_vContours.size(); i++){Scalar color = Scalar(g_rng.uniform(0, 255),g_rng.uniform(0, 255), g_rng.uniform(0, 255));//任意值//绘制轮廓drawContours(drawing, g_vContours, i, color, 1, 8, g_vHierarchy,0, Point());//绘制凸包drawContours(drawing, hull, i, color, 1, 8, g_vHierarchy,0, Point());}//显示效果图imshow("效果图",drawing);
}

演示效果:
1、仅绘制凸包:
仅绘制凸包
2、仅绘制轮廓:
仅绘制轮廓
3、既绘制轮廓也绘制凸包:
既绘制轮廓也绘制凸包
更加凸显出轮廓与凸包的关系。
总结:
学到的凸包知识点:检测并绘制凸包;轮廓、凸包、凸包连接点的结构关系。
学到的c++语法知识点:随机数生成器RNG的用法;vector的push_back()操作。

参考链接:
C++RNG类与毛星云寻找凸包例程的理解
C++ push方法与push_back方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378627.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EF Code First 简单的示例

一对多&#xff1a; public class Category {public Category(){Id GuidComb.GenerateComb();}public Guid Id { get; set; }public string Name { get; set; }public string Description { get; set; }public virtual IList<Topic> Topics { get; set; } }public class…

线程同步 - 整理

线程同步机制为线程协同工作而设计&#xff0c;windows系统中有多种机制可以用于线程同步&#xff0c;最常用的有下面几种&#xff1a; 互斥对象(Mutex)时间对象(Event)信号量(Semaphore)临界区(critical section)可等待计时器(waitable Timer)同步过程中两个重要的概念是同步对…

智能车复工日记【N】:图像处理——环岛debug记录(持续更新)

博主联系方式: QQ:1540984562 QQ交流群:892023501 群里会有往届的smarters和电赛选手,群里也会不时分享一些有用的资料,有问题可以在群里多问问。 Debug记录 代码以及思路整理:系列文章4.10号更新5.4号更新5.5号更新代码以及思路整理: 【智能车Code review】——环岛的判…

java接口并发衡量_java 后端设计高并发接口总结

如何设置高并发接口一、并发队列的选择二、请求接口的合理设计三、高并发下的数据安全3.1 超发的原因3.2 悲观锁思路3.3 FIFO队列思路3.4 乐观锁思路一、并发队列的选择Java的并发包提供了三个常用的并发队列实现&#xff0c;分别是&#xff1a;ArrayBlockingQueue、Concurrent…

两倍---C++

【问题描述】给定n个不同的正整数&#xff0c;你的任务是计算这些数里面有多少个数对满足&#xff1a;数对中一个数是另一个数的两倍&#xff0c;比如给定1 4 3 2 9 7 18 22&#xff0c;得到的答案是3&#xff0c;因为2是1的两倍&#xff0c;4是2的两倍&#xff0c;18是9的两倍…

java bitset_Java BitSet cardinality()方法与示例

java bitsetBitSet类cardinality()方法 (BitSet Class cardinality() method) cardinality() method is available in java.util package. cardinality()方法在java.util包中可用。 cardinality() method is used to return the cardinality (i.e. the number of bits is set t…

LeetCode: Merge k Sorted Lists

自己写的太复杂了&#xff0c;一开始想的是给开始的lists头们排序&#xff0c;然后从这个序列的第一个抽出来&#xff0c;然后再重新用二分法进行排序&#xff0c;不过这个方法large超时了&#xff0c;看了网上的发现还是用很土地方法用一个for循环从前两个开始merge到最后&…

JAVA 取得当前目录的路径

在写java程序时不可避免要获取文件的路径...总结一下,遗漏的随时补上 1.可以在servlet的init方法里 String path getServletContext().getRealPath("/"); 这将获取web项目的全路径 例如 :E:/eclipseM9/workspace/tree/ tree是我web项目的根目录 2.你也可以随时在任意…

golang mysql curd_Go 语言操作 MySQL 之 CURD 操作

本文转载于SegmentFault社区作者&#xff1a;Meng小羽MySQL 是目前开发中最常见的关系型数据库&#xff0c;使用 Go 语言进行操控数据库需要使用 Go 自带database/sql和驱动go-sql-driver/mysql来实现。创建好 Go 项目&#xff0c;需要引用驱动依赖&#xff1a;go get -u githu…

02.1-元素定位(find)

常用的一些方法 一、导包 from selenium import webdriver二、打开火狐&#xff08;空白页&#xff09; b webdriver.Firefox()三、跳转到指定的网站 b.get(https://www.baidu.com/)四、将浏览器页面最大化 b.maximize_window()五、通过F12可查看当前的贴吧为超链接形式 …

快速傅里叶变换(FFT)——按时间抽取DIT的基

目录【1】前言1、DIF计算量2、利用性质改善【2】公式推导1、N 到 2*N/2a、分解原序列b、分解后的DFT变换c、一系列化简操作之后d、蝶形信号流e、计算量总结2、N/2 到 2*N/4a、分解X2(k)序列b、蝶形信号流&#xff08;2列&#xff09;3、N/4 到 2*N/8a、蝶形信号流&#xff08;3…

Python字符串| 带示例的format()方法

String.format()方法 (String.format() Method) format() method is used to format the string (in other words - we can say to achieve the functionality like printf() in C language). format()方法用于格式化字符串(换句话说&#xff0c;我们可以说实现了C语言中类似于…

PLSQL Developer使用技巧

1、PL/SQL Developer记住登陆密码在使用PL/SQL Developer时&#xff0c;为了工作方便希望PL/SQL Developer记住登录Oracle的用户名和密码&#xff1b;设置方法&#xff1a;PL/SQL Developer 7.1.2 ->tools->Preferences->Oracle->Logon History &#xff0c; “St…

3月份的总结

租房子找了个黑中介&#xff0c;各种扣钱&#xff0c;合租的违约了&#xff0c;押金不要了直接一走了之&#xff0c;水费我们承担&#xff0c;中介这会儿又把责任推得一干二净&#xff0c;还耍小聪明&#xff0c;非说我是两个人住的&#xff0c;各种费用要交两份。。。我一时气…

快速傅里叶变换(FFT)——按频率抽取DIF的基

目录【1】回顾DIT【2】算法原理【3】运算特点【1】回顾DIT https://blog.csdn.net/qq_42604176/article/details/105559756 【2】算法原理 设序列点数&#xff1a;N2^M,M为正整数。将输入序列按照前一半、后一半分开。&#xff08;并非按照奇偶分&#xff09; 由于&#xf…

02.2-元素定位(XPath)

XML路径语言用来确定XML文档中某部分位置的语言XPath用于在XML文档中通过元素和属性进行导航XPath遵守W3C标准XPath节点类型&#xff1a; 元素、属性、文本、命名空间、指令处理、注释、文档 通过路径表达式从XML文档中选取节点或节点设置 表达式结果说明/xxx选取根节点xxx/xx…

android ImageView 之 android:scaleTye=

原文&#xff1a;http://juliaailse.iteye.com/blog/1409317 1、scaleType“matrix” 是保持原图大小、从左上角的点开始&#xff0c;以矩阵形式绘图。 2、scaleType“fitXY” 是将原图进行横方向&#xff08;即XY方向&#xff09;的拉伸后绘制的。 3、scaleType“fitStart…

acquire方法_Python锁类| 带有示例的acquire()方法

acquire方法Python Lock.acquire()方法 (Python Lock.acquire() Method) acquire() is an inbuilt method of the Lock class of the threading module in Python. acquisition()是Python中线程模块的Lock类的内置方法。 This method is used to acquire a lock, either block…

VSS2008 安装silverlight3.0步骤

需要的Q我359273753 我是新手不知道在哪里上传附件 汗一个转载于:https://www.cnblogs.com/ganler1988/archive/2011/03/17/1987367.html

php字符串对象,PHP字符串到对象名称

好的我有一个字符串……$a_string "Product";我想在调用这样的对象时使用这个字符串&#xff1a;$this->$a_string->some_function();狄更斯如何动态调用该对象&#xff1f;(不要以为我在PHP 5心中)解决方法:所以你要使用的代码是&#xff1a;$a_string &quo…