背景:
vs2015+opencv3.4.14
图像中斑点的轮廓提取、轮廓信息自定义保存和对于提取出的轮廓的连接操作。

//寻找轮廓findContours();
//绘制每个轮廓的最小外接矩形RotatedRect rect= minAreaRect(contours[i]);Point2f P[4];//初始化矩形四个顶点坐标rect.points(P);for (int i = 0; i < 4; i++){//line(imageContours, P[i], P[(i + 1) % 4], Scalar(255), 2);}

上面是轮廓提取的关键函数以及最小外接矩形的和其四个顶点的表示。
其中P四个点的位置是后面要着重注意的,弄不清楚后面的操作也就乱了,注意**的图。

1、定义结构体保存轮廓点信息

//定义结构图:轮廓信息struct P_Rect{//提取特征://最小外接矩形的质心、长宽、旋转角度//轮廓面积int px;int py;float pwidth;float pheight;float pangle;float parea;};//定义结构图:轮廓外部信息struct P_Rectout{//在一定范围内点的位置,各个距离int ox;int oy;float odistance;float oarea;};//矩形相邻的两个边的长度float length1= abs(sqrtf(powf((P[0].x - P[1].x), 2) + powf((P[0].y -            P[1].y), 2)));float length2 = abs(sqrtf(powf((P[1].x - P[2].x), 2) + powf((P[1].y - P[2].y), 2)));//正确找到长边和短边if (length1 >= length2){p_rect.pwidth = length1;p_rect.pheight = length2;p_rect.pangle = cvFastArctan(abs(P[1].y - P[0].y), abs(P[1].x -  P[0].x));//指向长的方向的角度,不是矩形原来的角度,矩形原来的角度解析可去    查找findContours函数}else{p_rect.pwidth = length2;p_rect.pheight = length1;if (P[2].x == P[1].x)//使用arctan的注意事项{p_rect.pangle = 90;}else{p_rect.pangle = -abs(cvFastArctan(abs(P[2].y - P[1].y), abs(P[2].x - P[1].x)));}}
//中心x和yp_rect.px=rect.center.x;p_rect.py = rect.center.y;
//面积,是真实面积不是最小外接矩形面积p_rect.parea = contourArea(contours[i]);
//保存到容器中P_rect.push_back(p_rect);//小于半径范围内点的集合vector<P_Rectout> p_rectOut;float r = 20;for (int j = 0; j < contours.size(); j++){RotatedRect orect = minAreaRect(contours[j]);float distance = abs(sqrtf(powf((rect.center.x - orect.center.x), 2) + powf((rect.center.x - orect.center.y), 2)));if (distance < r){P_Rectout p_rectout;p_rectout.ox = orect.center.x;p_rectout.oy = orect.center.y;p_rectout.odistance = distance;p_rectout.oarea= contourArea(contours[j]);p_rectOut.push_back(p_rectout);//line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 3);}}P_rectout.push_back(p_rectOut);}

2、以每个点一定半径范围为依据连线

//一定范围内最近点连线//以第一个点sta为起点,寻找一定半径(r)范围内的所有临近点mid[],连线,直到半径(r)内无此特征的点为止,遍历所有点float r = 500;for (int i = 0; i < P_rect.size(); i++){for (int j = 0; j < P_rect.size(); j++){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance < r){line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 2);}}}

3、最短距离连线

//最短距离连线vector<Point> yet_link;//保存以完成连线点for (int i = 0; i < (P_rect.size()-1); i++){float distance_min = 10000000000;//顺便定个大数int p_near = 0;for (int j = 0; j < P_rect.size(); j++){bool flag = 1;for (int k = 0; k < yet_link.size(); k++)//保证每个点不返回头和连过的点再次连一遍,看情况取舍{if (i == yet_link[k].y && j == yet_link[k].x){flag = 0;continue;}}if (flag){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance<distance_min){p_near = j;distance_min = distance;}}}yet_link.push_back(Point(i, p_near));line(imageContours2, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[p_near].px, P_rect[p_near].py), Scalar(255), 2);}

完整代码如下;

#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>using namespace std;
using namespace cv;//定义结构图:轮廓信息
struct P_Rect
{//提取特征://最小外接矩形的质心、长宽、旋转角度//轮廓面积int px;int py;float pwidth;float pheight;float pangle;float parea;
};//定义结构图:轮廓外部信息
struct P_Rectout
{//在一定范围内点的位置,各个距离int ox;int oy;float odistance;float oarea;
};int main()
{//读入图像Mat img_original = imread("北斗七星.bmp");//imwrite("1.bmp", img_original);Mat img_original_gray;cvtColor(img_original, img_original_gray, CV_BGR2GRAY);//转为灰度图Mat img_original_bin;threshold(img_original_gray, img_original_bin, 100, 255, CV_THRESH_BINARY);//二值化//寻找轮廓vector<vector<Point>> contours;vector<Vec4i> hierarchy;//存储查找到的第i个轮廓的后[i][0]、前[i][1]、父[i][2]、子轮廓[i][3]findContours(img_original_bin, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE, Point());Mat imageContours = Mat::zeros(img_original_bin.size(), CV_8UC1);   //画布1Mat imageContours2 = Mat::zeros(img_original_bin.size(), CV_8UC1);    //画布2//for (int i = 0; i < contours.size(); i++)//{// //绘制轮廓的最小外接正矩形//    Rect boundRect = boundingRect(Mat(contours[i]));// rectangle(imageContours, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar(255), 2, 8);//}vector<P_Rect> P_rect;vector<vector<P_Rectout> > P_rectout;for (int i = 0; i < contours.size(); i++){float area= contourArea(contours[i]);if (area < 10)continue;//******P_Rect p_rect;drawContours(imageContours, contours, i, Scalar(255), -1, 8, hierarchy);drawContours(imageContours2, contours, i, Scalar(255), -1, 8, hierarchy);//绘制每个轮廓的最小外接矩形RotatedRect rect= minAreaRect(contours[i]);Point2f P[4];//初始化矩形四个顶点坐标rect.points(P);for (int i = 0; i < 4; i++){//line(imageContours, P[i], P[(i + 1) % 4], Scalar(255), 2);}float length1= abs(sqrtf(powf((P[0].x - P[1].x), 2) + powf((P[0].y - P[1].y), 2)));float length2 = abs(sqrtf(powf((P[1].x - P[2].x), 2) + powf((P[1].y - P[2].y), 2)));if (length1 >= length2){p_rect.pwidth = length1;p_rect.pheight = length2;p_rect.pangle = cvFastArctan(abs(P[1].y - P[0].y), abs(P[1].x - P[0].x));}else{p_rect.pwidth = length2;p_rect.pheight = length1;if (P[2].x == P[1].x){p_rect.pangle = 90;}else{p_rect.pangle = -abs(cvFastArctan(abs(P[2].y - P[1].y), abs(P[2].x - P[1].x)));}}p_rect.px=rect.center.x;p_rect.py = rect.center.y;p_rect.parea = contourArea(contours[i]);P_rect.push_back(p_rect);//********vector<P_Rectout> p_rectOut;float r = 20;for (int j = 0; j < contours.size(); j++){RotatedRect orect = minAreaRect(contours[j]);float distance = abs(sqrtf(powf((rect.center.x - orect.center.x), 2) + powf((rect.center.x - orect.center.y), 2)));if (distance < r){P_Rectout p_rectout;p_rectout.ox = orect.center.x;p_rectout.oy = orect.center.y;p_rectout.odistance = distance;p_rectout.oarea= contourArea(contours[j]);p_rectOut.push_back(p_rectout);//line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 3);}}P_rectout.push_back(p_rectOut);}//一定范围内最近点连线//以第一个点sta为起点,寻找一定半径(r)范围内的所有临近点mid[],连线,直到半径(r)内无此特征的点为止,遍历所有点float r = 500;/*Point2f sta = center_each[0];vector<Point2f> mid;*/for (int i = 0; i < P_rect.size(); i++){for (int j = 0; j < P_rect.size(); j++){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance < r){//mid.push_back(center_each[j]);line(imageContours, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[j].px, P_rect[j].py), Scalar(255), 2);}}}//最短距离连线vector<Point> yet_link;for (int i = 0; i < (P_rect.size()-1); i++){float distance_min = 10000000000;int p_near = 0;for (int j = 0; j < P_rect.size(); j++){bool flag = 1;for (int k = 0; k < yet_link.size(); k++){if (i == yet_link[k].y && j == yet_link[k].x){flag = 0;continue;}}if (flag){float distance = abs(sqrtf(powf((P_rect[i].px - P_rect[j].px), 2) + powf((P_rect[i].py - P_rect[j].py), 2)));if (distance > 0 && distance<distance_min){p_near = j;distance_min = distance;}}}yet_link.push_back(Point(i, p_near));line(imageContours2, Point(P_rect[i].px, P_rect[i].py), Point(P_rect[p_near].px, P_rect[p_near].py), Scalar(255), 2);}}

opencv——图像中关于轮廓的一些操作相关推荐

  1. 使用Python,OpenCV从图像中删除轮廓

    使用Python,OpenCV从图像中删除轮廓 1. 效果图 2. 步骤 3. 源码 4. 参考 1. 使用Python.OpenCV计算轮廓的中心并标记 2. 使用Python.OpenCV检测轮廓 ...

  2. OpenCV之imgproc 模块. 图像处理(5)在图像中寻找轮廓 计算物体的凸包 创建包围轮廓的矩形和圆形边界框 为轮廓创建可倾斜的边界框和椭圆 轮廓矩 多边形测试

    在图像中寻找轮廓 目标 在这个教程中你将学到如何: 使用OpenCV函数 findContours 使用OpenCV函数 drawContours 原理 例程 教程的代码在下面给出. 你也可以从 这里 ...

  3. OpenCV演示代码以查找图像中的轮廓(附完整代码)

    OpenCV演示代码以查找图像中的轮廓 OpenCV演示代码以查找图像中的轮廓 OpenCV演示代码以查找图像中的轮廓 #include "opencv2/imgcodecs.hpp&quo ...

  4. OpenCV在图像中寻找轮廓的实例(附完整代码)

    OpenCV在图像中寻找轮廓的实例 OpenCV在图像中寻找轮廓的实例 OpenCV在图像中寻找轮廓的实例 #include "opencv2/imgcodecs.hpp" #in ...

  5. OpenCV在图像中寻找轮廓

    OpenCV在图像中寻找轮廓 在图像中寻找轮廓 目标 代码 结果 在图像中寻找轮廓 目标 在本教程中,您将学习如何: 使用OpenCV函数cv :: findContours 使用OpenCV函数cv ...

  6. ITK:从图像中提取轮廓

    ITK:从图像中提取轮廓 内容提要 输出结果 C++实现代码 内容提要 从图像中提取轮廓. 输出结果 There are 2 contoursContour 0: [10.5, 19] [10.460 ...

  7. OpenCV图像中的人脸界标检测

    OpenCV图像中的人脸界标检测 图像中的人脸界标检测 简介 命令参数的描述{tutorial_face_training_parameters} 源代码 检测结果 图像中的人脸界标检测 简介 此应用 ...

  8. 使用Python,OpenCV寻找图像中的轮廓

    使用Python和OpenCV查找图像中的形状 1. 效果图 2. 步骤 3. 源码 参考 这篇博客将讨论使用Python和OpenCV查找图像中的形状,具体是 cv2.inRange在图像中查找形状 ...

  9. 教你如何使用 OpenCV检测图像中的轮廓

    @Author:Runsen 轮廓是连接所有具有某种颜色或强度的连续点的闭合曲线,它们代表图像中发现的对象的形状.轮廓检测是一种用于形状分析和物体检测和识别的有用技术. 轮廓检测并不是图像分割的唯一算 ...

最新文章

  1. win计算机管理没有权限,Windows 7提示没有管理员权限怎么办
  2. 多线程编程1-NSThread
  3. php网络相关的扩展,文章专题扩展功能组件
  4. 微信支付(JSAPI) - chooseWXPay fail 问题解决
  5. WordCount by C# 结对编程
  6. PowerDesigner中在生成的数据库脚本中用name列替换comment列作为字段描述的方法
  7. 读jQuery之十二(删除事件核心方法)
  8. 慕课网 饿了么 vue2.0 项目
  9. C# 通过反射获取枚举类型
  10. matlab 中函数regionprops 求解区域面积的原理
  11. Size Classes with Xcode 6
  12. php 表单 sql,PHP表单发布到SQL后没有任何操作
  13. 2017年全国大学生电子设计竞赛报告(F题)调幅信号处理实验电路
  14. 5个免费商用音频素材网站
  15. GEE实战 | 计算NDVI NDWI
  16. Android面试题【高级工程师版】
  17. Android 9.0以上HTTP网络请求被限制解决方案
  18. Android 安卓开发板 读取串口
  19. 微信小程序分享功能的实现方法有两种
  20. mysql数据库网上书店实训报告_数据库.网上书店实验报告.doc

热门文章

  1. tensorflow:自定义op简单介绍
  2. 程序员的五层境界,你在哪一层?最后一层的,都是人生赢家
  3. 数据挖掘与python实践心得体会_2年数据挖掘服务工作心得体会
  4. 关于mina内部有向个线程在执行---mina源代码分析
  5. 如何引导回购和好评且不被平台抽查和处罚
  6. javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  7. 怎么对比两个mysql数据库_[实战]如何对比两个数据库之间的变化
  8. 简历——“三无”应届生怎么写简历,全是干货!(模板直接拿走)
  9. dmz和端口映射_使用DMZ主机功能代替FTP服务端口映射无法使用的问题
  10. 如何在CSDN写笔记_写笔记前的插件安装