zoukankan      html  css  js  c++  java
  • opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包

    查找并绘制轮廓

    寻找轮廓(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函数指定的图片存在~! 
    "); 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("
    
    			   当前使用的OpenCV版本为:" CV_VERSION);
    	printf("
    
      ----------------------------------------------------------------------------
    ");
    
    	//输出一些帮助信息  
    	printf("
    
    	欢迎来到【在图形中寻找轮廓】示例程序~
    
    ");
    	printf("
    
    	按键操作说明: 
    
    "
    		"		键盘按键任意键- 退出程序
    
    "
    		"		滑动滚动条-改变阈值
    ");
    }
    

    寻找物体的凸包

    寻找凸包(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("
    
    			   当前使用的OpenCV版本为:" CV_VERSION);
    	printf("
    
      ----------------------------------------------------------------------------
    ");
    	//输出一些帮助信息
    	printf("
    	欢迎来到【凸包检测】示例程序~
    
    ");
    	printf("
    	按键操作说明: 
    
    "
    		"		键盘按键【ESC】、【Q】、【q】- 退出程序
    
    "
    		"		键盘按键任意键 - 重新生成随机点,并进行凸包检测
    ");
    
    }
    
    
    //--------------------------------------【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

  • 相关阅读:
    三个录屏软件
    不用 PS 和 AI,5个网站能做出更好看的设计
    使用vue.js开发小程序
    js异步处理
    HTTP、HTTP1.0、HTTP1.1、HTTP2.0、HTTPS
    Chrome不支持css字体小于12px的解决办法
    处理CSS前缀问题的神器——AutoPrefixer
    CSS | 字体系列
    qemu-img 命令讲解
    全面理解 git
  • 原文地址:https://www.cnblogs.com/xingkongcanghai/p/11193804.html
Copyright © 2011-2022 走看看