查找并绘制轮廓

寻找轮廓(findContours)函数







绘制轮廓(drawContours()函数)





基础实例程序:轮廓查找

#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std; //-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
// 【1】载入原始图,且必须以二值图模式载入
Mat srcImage = imread("1.jpg", 0);
imshow("原始图", srcImage); //【2】初始化结果图
Mat dstImage = Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC3); //【3】srcImage取大于阈值119的那部分
srcImage = srcImage > 119;
imshow("取阈值后的原始图", srcImage); //【4】定义轮廓和层次结构
vector<vector<Point> > contours;
vector<Vec4i> hierarchy; //【5】查找轮廓 //此句代码的OpenCV3版为:
findContours(srcImage, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); // 【6】遍历所有顶层的轮廓, 以随机颜色绘制出每个连接组件颜色
int index = 0;
for (; index >= 0; index = hierarchy[index][0])
{
Scalar color(rand() & 255, rand() & 255, rand() & 255); drawContours(dstImage, contours, index, color, FILLED, 8, hierarchy);
} //【7】显示最后的轮廓图
imshow("轮廓图", dstImage); waitKey(0); }

综合实例程序(加blur,canny和滑动条):

#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;
Mat g_grayImage;
int g_nThresh = 80;
int g_nThresh_max = 255;
RNG g_rng(12345);
Mat g_cannyMat_output;
vector<vector<Point>> g_vContours;
vector<Vec4i> g_vHierarchy; //-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数的声明
//-----------------------------------------------------------------------------------------------
static void ShowHelpText();
void on_ThreshChange(int, void*); //-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
//【0】改变console字体颜色
system("color 1F"); //【0】显示欢迎和帮助文字
ShowHelpText(); // 加载源图像
g_srcImage = imread("1.jpg", 1);
if (!g_srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; } // 转成灰度并模糊化降噪
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
blur(g_grayImage, g_grayImage, Size(3, 3)); // 创建窗口
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME1, g_srcImage); //创建滚动条并初始化
createTrackbar("canny阈值", WINDOW_NAME1, &g_nThresh, g_nThresh_max, on_ThreshChange);
on_ThreshChange(0, 0); waitKey(0);
return(0);
} //-----------------------------------【on_ThreshChange( )函数】------------------------------
// 描述:回调函数
//----------------------------------------------------------------------------------------------
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 drawing = Mat::zeros(g_cannyMat_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, 2, 8, g_vHierarchy, 0, Point());
} // 显示效果图
imshow(WINDOW_NAME2, drawing);
} //-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本 printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n"); //输出一些帮助信息
printf("\n\n\t欢迎来到【在图形中寻找轮廓】示例程序~\n\n");
printf("\n\n\t按键操作说明: \n\n"
"\t\t键盘按键任意键- 退出程序\n\n"
"\t\t滑动滚动条-改变阈值\n");
}

寻找物体的凸包

寻找凸包(convexHull()函数)

基础示例程序:凸包检测基础

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std; //-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本 printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
//输出一些帮助信息
printf("\n\t欢迎来到【凸包检测】示例程序~\n\n");
printf("\n\t按键操作说明: \n\n"
"\t\t键盘按键【ESC】、【Q】、【q】- 退出程序\n\n"
"\t\t键盘按键任意键 - 重新生成随机点,并进行凸包检测\n"); } //--------------------------------------【main( )函数】-----------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
//改变console字体颜色
system("color 1F"); //显示帮助文字
ShowHelpText(); //初始化变量和随机值
Mat image(600, 600, CV_8UC3);
RNG& rng = theRNG(); //循环,按下ESC,Q,q键程序退出,否则有键按下便一直更新
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);
} //检测凸包
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]];
line(image, point0, point, Scalar(255, 255, 255), 2, LINE_AA);
point0 = point;
} //显示效果图
imshow("凸包检测示例", image); //按下ESC,Q,或者q,程序退出
key = (char)waitKey();
if (key == 27 || key == 'q' || key == 'Q')
break;
} return 0;
}

综合实例程序:寻找和绘制物体的凸包

#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; Mat g_grayImage;
int g_nThresh = 50;
int g_maxThresh = 255;
RNG g_rng(12345);
Mat srcImage_copy = g_srcImage.clone();
Mat g_thresholdImage_output;
vector<vector<Point> > g_vContours;
vector<Vec4i> g_vHierarchy; //-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数的声明
//----------------------------------------------------------------------------------------------- void on_ThreshChange(int, void*); //-----------------------------------【main( )函数】------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{ // 加载源图像
g_srcImage = imread("1.jpg", 1); // 将原图转换成灰度图并进行模糊降
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
blur(g_grayImage, g_grayImage, Size(3, 3)); // 创建原图窗口并显示
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME1, g_srcImage); //创建滚动条
createTrackbar(" 阈值:", WINDOW_NAME1, &g_nThresh, g_maxThresh, on_ThreshChange);
on_ThreshChange(0, 0);//调用一次进行初始化 waitKey(0);
return(0);
} //-----------------------------------【thresh_callback( )函数】----------------------------------
// 描述:回调函数
//----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void*)
{
// 对图像进行二值化,控制阈值
threshold(g_grayImage, g_thresholdImage_output, g_nThresh, 255, THRESH_BINARY); // 寻找轮廓
findContours(g_thresholdImage_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);
} // 绘出轮廓及其凸包
Mat drawing = Mat::zeros(g_thresholdImage_output.size(), CV_8UC3);
for (unsigned 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, vector<Vec4i>(), 0, Point());
drawContours(drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point());
} // 显示效果图
imshow(WINDOW_NAME2, drawing);
}

HSV学习链接https://blog.csdn.net/coldwindha/article/details/82080176

opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包的更多相关文章

  1. opencv 6 图像轮廓与图像分割修复 2 使用多边形将轮廓包围

    使用多边形将轮廓包围 返回外部矩阵边界(boundingRect()函数) 寻找最小包围矩形(minAreaRect()函数) 寻找最小包围圆形(minEnclosingCircle函数) 用椭圆拟合 ...

  2. opencv 6 图像轮廓与图像分割修复 3 图像的矩,分水岭,图像修补

    图像的矩 矩的计算:moments()函数 计算轮廓面积:contourArea()函数 #include "opencv2/highgui/highgui.hpp" #inclu ...

  3. 查找并绘制轮廓[OpenCV 笔记XX]

    好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...

  4. 查找并绘制轮廓 opencv

    findContours(): 第二个参数为一个检测到的轮廓,函数调用后的运算结果都放在这里,每个轮廓存储为1个点向量,用point类型的vector表示. 第三个参数表示轮廓数量,包含了许多元素.每 ...

  5. OpenCV——查找、绘制轮廓

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...

  6. 寻找物体的凸包 opencv

    凸包的含义: 在二维平面上给定点集,凸包就是将最外层的点连接起来构成的凸多边形.并且这个凸多边形能包含点集中所有的点.OPENCV中: convexHull函数用于寻找图像点集中的凸包.它有六个输入参 ...

  7. opencv学习之路(23)、轮廓查找与绘制(二)——访问轮廓每个点

    一.简介 二.画出每个轮廓的每个点 #include "opencv2/opencv.hpp" using namespace cv; void main() { Mat src= ...

  8. Opencv分水岭算法——watershed自动图像分割用法

    分水岭算法是一种图像区域分割法,在分割的过程中,它会把跟临近像素间的相似性作为重要的参考依据,从而将在空间位置上相近并且灰度值相近的像素点互相连接起来构成一个封闭的轮廓,封闭性是分水岭算法的一个重要特 ...

  9. 图像分割之(五)活动轮廓模型之Snake模型简介

    在"图像分割之(一)概述"中咱们简单了解了目前主流的图像分割方法.下面咱们主要学习下基于能量泛函的分割方法.这里学习下Snake模型简单的知识,Level Set(水平集)模型会在 ...

随机推荐

  1. spring boot 日志收集整理

    spring boot 日志 1. 选择那种日志框架 slf4j 是抽像的接口层.也是spring boot 默认采用的接口层. util.logging,log4j,logback,commons- ...

  2. AS报错:lambda expressions are not supported at this language level

    AS报错:lambda expressions are not supported at this language level 解决方法 打开打开 File --> Project Stuct ...

  3. [翻译]Jupyter notebook .NET Core 内核预览1

    当您想到Jupyter Notebooks时,您可能会考虑使用Python,R,Julia或Scala而不是.NET编写代码. 今天,我们很高兴宣布您可以在Jupyter Notebooks中编写.N ...

  4. 作为一名程序员,你真正了解CDN技术吗?

    本文导读: 物流仓库配送如何加速 静态资源文件部署方式 静态资源加速之CDN技术 解析过程中的名词解释 最后的总结 1.物流仓库配送如何加速 我们还是从生活中购物的例子来展开. 将时光倒回到几年前,在 ...

  5. python基础-字典dict

    字典-dict 用途: 定义方法:通过{} 来存储数据,通过key:value (键值对)来存储数据,每个键值对通过逗号分隔.在键值对中,key 是不可变的数据类型,value 是任意数据类型 def ...

  6. 使用memset初始化int数组

    memset()是一个来自于string库的函数,正规用法是初始化char类型的数组.因为char类型只占1个字节,memset按字节赋值后,会将char类型数组的所有元素变为你指定的值.但是4字节的 ...

  7. Netty学习篇④-心跳机制及断线重连

    心跳检测 前言 客户端和服务端的连接属于socket连接,也属于长连接,往往会存在客户端在连接了服务端之后就没有任何操作了,但还是占用了一个连接:当越来越多类似的客户端出现就会浪费很多连接,netty ...

  8. 关于mimikatz lazagne免杀方法

    其实现在的杀软还是玩的老一套,改改特征字符就能过了,最新的defender能用这个方法过 文章直接从笔记复制出来的,有需要的自己看情况用 git clone https://github.com/ge ...

  9. [考试反思]1028csp-s模拟测试91:预估

    这一轮是要闹哪样啊???前十都死活进不去??? 能不能不要到联赛前突然连续掉链子啊!!! 总算难得的切掉了T1.然后又一次把T2和T3的难度估反了 结果给T2剩下了30分钟,想到正解来不及打了. 然后 ...

  10. CSPS模拟 69

    $C_n^0=1$ $C_n^0=1$ $C_n^0=1$ 我怎么又双叒叕犯这种错误了啊 (咳檀) T1 WA0,大神题,不会做! T2 就是要找一个最长区间,满足左端点是区间最小值,右端点是区间最大 ...