16- OpenCV:轮廓的发现和轮廓绘制、凸包

这篇具有很好参考价值的文章主要介绍了16- OpenCV:轮廓的发现和轮廓绘制、凸包。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、轮廓发现

1、轮廓发现(find contour in your image) 的含义

2、相关的API 以及代码演示

二、凸包

1、凸包(Convex Hull)的含义

2、Graham扫描算法- 概念介绍

3、cv::convexHull 以及代码演示

三、轮廓周围绘制矩形和圆形框


一、轮廓发现

1、轮廓发现(find contour in your image) 的含义

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法。 所以边缘提取的阈值选定会影响最终轮廓发现结果。

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

找出并画出图中的轮廓。

2、相关的API 以及代码演示

(1)轮廓发现(find contour)

cv::findContours(

InputOutputArray  binImg, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit  

OutputArrayOfArrays  contours,//  全部发现的轮廓对象

OutputArray,  hierachy// 图该的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。

int mode, //  轮廓返回的模式

int method,// 发现方法

Point offset=Point()//  轮廓像素的位移,默认(0, 0)没有位移

)

(2)轮廓绘制(draw contour):cv::findContours之后对发现的轮廓数据进行绘制显示

drawContours(

InputOutputArray  binImg, // 输出图像  

OutputArrayOfArrays  contours,//  全部发现的轮廓对象

Int contourIdx// 轮廓索引号

const Scalar & color,// 绘制时候颜色

int  thickness,// 绘制线宽

int  lineType ,// 线的类型LINE_8

InputArray hierarchy,// 拓扑结构图

int maxlevel,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓

Point offset=Point()// 轮廓位移,可选

(3)代码流程主要步骤:

- 输入图像转为灰度图像cvtColor

- 使用Canny进行边缘提取,得到二值图像

- 使用findContours寻找轮廓

- 使用drawContours绘制轮廓

(4)代码例子:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace std;
using namespace cv;

Mat src, dst;
const char* output_win = "findcontours-demo";
int threshold_value = 100;
int threshold_max = 255;
RNG rng;
void Demo_Contours(int, void*);
int main(int argc, char** argv) {
	src = imread("fish.png");
	if (src.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input-image", CV_WINDOW_AUTOSIZE);
	namedWindow(output_win, CV_WINDOW_AUTOSIZE);
	imshow("input-image", src);
	cvtColor(src, src, CV_BGR2GRAY);

	const char* trackbar_title = "Threshold Value:";
	createTrackbar(trackbar_title, output_win, &threshold_value, threshold_max, Demo_Contours);
	Demo_Contours(0, 0);

	waitKey(0);
	return 0;
}

void Demo_Contours(int, void*) {
	Mat canny_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	Canny(src, canny_output, threshold_value, threshold_value * 2, 3, false);
	findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

	dst = Mat::zeros(src.size(), CV_8UC3);
	RNG rng(12345);
	for (size_t i = 0; i < contours.size(); i++) {
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));
	}
	imshow(output_win, dst);
}

效果展示:

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

二、凸包

1、凸包(Convex Hull)的含义

在一个多变形边缘或者内部任意两个点的连线都包含在多边形边界或者内部。

正式定义: 包含点集合S中所有点的最小凸多边形称为凸包。

左边的图才是正确的凸包,右边的不算正确的

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉              16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

 凸包的检测算法是:Graham扫描法

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

2、Graham扫描算法- 概念介绍

(1)首先选择Y方向最低的点作为起始点p0;

(2)从p0开始极坐标扫描,依次添加p1….pn(排序顺序是根据极坐标的角度大小,逆时针方向);

(3)对每个点pi来说,如果添加pi点到凸包中导致一个左转向(逆时针方法)则添加该点到凸包, 反之如果导致一个右转向(顺时针方向)删除该点从凸包中;

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

3、cv::convexHull 以及代码演示

convexHull(

InputArray points,// 输入候选点,来自findContours

OutputArray hull,// 凸包

bool clockwise,// default true, 顺时针方向

bool returnPoints // true 表示返回点个数,如果第二个参数是vector<Point>则自动忽略

代码的操作主要步骤:

- 首先把图像从RGB转为灰度

- 然后再转为二值图像

- 在通过发现轮廓得到候选点

- 凸包API调用

- 绘制显示。

具体代码:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace std;
using namespace cv;
Mat src, src_gray, dst;
int threshold_value = 100;
int threshold_max = 255;
const char* output_win = "convex hull demo";
void Threshold_Callback(int, void*);
RNG rng(12345);
int main(int argc, char** argv) {
	src = imread("fish.png");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}
	const char* input_win = "input image";
	namedWindow(input_win, CV_WINDOW_AUTOSIZE);
	namedWindow(output_win, CV_WINDOW_NORMAL);
	const char* trackbar_label = "Threshold : ";

	cvtColor(src, src_gray, CV_BGR2GRAY);
	blur(src_gray, src_gray, Size(3, 3), Point(-1, -1), BORDER_DEFAULT);
	imshow(input_win, src_gray);

	createTrackbar(trackbar_label, output_win, &threshold_value, threshold_max, Threshold_Callback);
	Threshold_Callback(0, 0);
	waitKey(0);
	return 0;
}

void Threshold_Callback(int, void*) {
	Mat bin_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	
	threshold(src_gray, bin_output, threshold_value, threshold_max, THRESH_BINARY);
	findContours(bin_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

	vector<vector<Point>> convexs(contours.size());
	for (size_t i = 0; i < contours.size(); i++) {
		convexHull(contours[i], convexs[i], false, true);
	}

	// 绘制
	dst = Mat::zeros(src.size(), CV_8UC3);
	vector<Vec4i> empty(0);
	for (size_t k = 0; k < contours.size(); k++) {
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(dst, contours, k, color, 2, LINE_8, hierachy, 0, Point(0, 0));
		drawContours(dst, convexs, k, color, 2, LINE_8, empty, 0, Point(0, 0));
	}
	imshow(output_win, dst);

	return;
}

效果展示:

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

三、轮廓周围绘制矩形和圆形框

1、含义

        可以使用轮廓检测函数findContours找到图像中的轮廓,并通过绘制矩形和圆形框来突出显示这些轮廓。(如下图所示)

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

2、相关的API

(1)cv::approxPolyDP:用于对曲线进行多边形逼近的函数之一。它可以将曲线逼近为一个更简单的多边形。适用于对任意曲线进行逼近,不仅限于轮廓曲线。

基于RDP算法实现,目的是减少多边形轮廓点数。精简化得图像。


void cv::approxPolyDP(
    InputArray curve, // 输入的曲线,可以是一个包含点坐标的数组。
    OutputArray approxCurve, // 输出的逼近多边形曲线,保存了逼近后的点坐标。
    double epsilon, // 逼近精度,即逼近后的多边形与原曲线之间的最大距离。

                                两点之间最小的距离
    bool closed // 是否将曲线视为闭合曲线,如果为true,则认为曲线是闭合的,否则认为曲线是开放的。

);

通过调用approxPolyDP函数,可以将输入的曲线逼近为一个更简单的多边形,并将逼近后的多边形曲线保存在输出数组approxCurve中。逼近的精度由epsilon参数控制,较小的epsilon值会得到更接近原曲线的逼近结果。

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉

(2)cv::boundingRect(InputArray points):用于计算一组点的最小外接矩形的函数。该矩形是以水平和垂直方向为边界的最小矩形,能够完全包围所有输入点。

得到轮廓周围最小矩形左上交点坐标和右下角点坐标,绘制一个矩形。

cv::Rect cv::boundingRect(

InputArray points // 输入的点集,可以是一个包含点坐标的数组。

)

返回值:

  • cv::Rect:表示最小外接矩形的矩形对象,包含了最小外接矩形的位置和大小信息。

(3)cv::minAreaRect(InputArray  points):得到一个旋转的矩形,返回旋转矩形

(4)cv::minEnclosingCircle:用于计算一组点的最小外接圆的函数。该圆是能够完全包围所有输入点的最小圆。

cv::minEnclosingCircle(

InputArray points, //得到最小区域圆形

Point2f& center, // 输出参数,表示最小外接圆的圆心坐标。

float& radius // 输出参数,表示最小外接圆的半径。

(5)cv::fitEllipse(InputArray  points):得到最小椭圆

3、代码演示

(1)主要的处理步骤:

- 首先将图像变为灰度图像cvtColor

- 模糊(椒盐噪声多选择高斯模糊GaussianBlur,不然选择中值模糊),减低噪声

- 获得二值图像(threshold);

- 发现轮廓,找到图像轮廓;

- 通过相关API在轮廓点上找到最小包含矩形和圆,旋转矩形与椭圆;

- 绘制它们。

(2)具体代码:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace std;
using namespace cv;
Mat src, gray_src, drawImg;
int threshold_v = 170;
int threshold_max = 255;
const char* output_win = "rectangle-demo";
RNG rng(12345);
void Contours_Callback(int, void*);
int main(int argc, char** argv) {
	src = imread("fish.png");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}
	cvtColor(src, gray_src, CV_BGR2GRAY);
	blur(gray_src, gray_src, Size(3, 3), Point(-1, -1));
	
	const char* source_win = "input image";
	namedWindow(source_win, CV_WINDOW_AUTOSIZE);
	namedWindow(output_win, CV_WINDOW_AUTOSIZE);
	imshow(source_win, src);

	createTrackbar("Threshold Value:", output_win, &threshold_v, threshold_max, Contours_Callback);
	Contours_Callback(0, 0);

	waitKey(0);
	return 0;
}

void Contours_Callback(int, void*) {
	Mat binary_output;
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	threshold(gray_src, binary_output, threshold_v, threshold_max, THRESH_BINARY);
	//imshow("binary image", binary_output);
	findContours(binary_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));

	vector<vector<Point>> contours_ploy(contours.size());
	vector<Rect> ploy_rects(contours.size());
	vector<Point2f> ccs(contours.size());
	vector<float> radius(contours.size());

	vector<RotatedRect> minRects(contours.size());
	vector<RotatedRect> myellipse(contours.size());

	for (size_t i = 0; i < contours.size(); i++) {
		approxPolyDP(Mat(contours[i]), contours_ploy[i], 3, true);
		ploy_rects[i] = boundingRect(contours_ploy[i]);
		minEnclosingCircle(contours_ploy[i], ccs[i], radius[i]);
		if (contours_ploy[i].size() > 5) {
			myellipse[i] = fitEllipse(contours_ploy[i]);
			minRects[i] = minAreaRect(contours_ploy[i]);
		}
	}

	// draw it
	drawImg = Mat::zeros(src.size(), src.type());
	Point2f pts[4];
	for (size_t t = 0; t < contours.size(); t++) {
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		//rectangle(drawImg, ploy_rects[t], color, 2, 8);
		//circle(drawImg, ccs[t], radius[t], color, 2, 8);
		if (contours_ploy[t].size() > 5) {
			ellipse(drawImg, myellipse[t], color, 1, 8);
			minRects[t].points(pts);
			for (int r = 0; r < 4; r++) {
				line(drawImg, pts[r], pts[(r + 1) % 4], color, 1, 8);
			}
		}
	}

	imshow(output_win, drawImg);
	return;
}

效果展示:

16- OpenCV:轮廓的发现和轮廓绘制、凸包,OpenCV,opencv,人工智能,计算机视觉文章来源地址https://www.toymoban.com/news/detail-832029.html

到了这里,关于16- OpenCV:轮廓的发现和轮廓绘制、凸包的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV 入门教程:寻找和绘制轮廓

    寻找和绘制轮廓是图像处理中常用的技术之一,用于识别、定位和分析图像中的目标区域。在 OpenCV 中,寻找和绘制轮廓可以通过边缘检测和形态学操作实现。本文将以寻找和绘制轮廓为中心,为你介绍使用 OpenCV 进行轮廓处理的基本步骤和实例。 😃#x

    2024年02月14日
    浏览(30)
  • OpenCV查找和绘制轮廓:findContours和drawContours

    1  任务描述: 绘制图中粗线矩形的2个边界,并找到其边界的中心线 图1 原始图像  2.函数原型 findContours( InputOutputArray image, OutputArrayOfArrays contours,                               OutputArray hierarchy, int mode,                               int method, Point offset=Point()); image:图

    2024年02月07日
    浏览(36)
  • 数字图像处理【11】OpenCV-Canny边缘提取到FindContours轮廓发现

    本章主要介绍图像处理中一个比较基础的操作:Canny边缘发现、轮廓发现 和 绘制轮廓。概念不难,主要是结合OpenCV 4.5+的API相关操作,为往下 \\\"基于距离变换的分水岭图像分割\\\" 做知识储备。 在讲述轮廓之前,要花点时间学学边缘检测提取的一个著名算法——Canny边缘提取算法

    2024年02月16日
    浏览(29)
  • [C++] opencv - drawContours(绘制轮廓)函数介绍和使用场景

    OpenCV中的drawContours函数用于在图像上绘制轮廓。其函数原型如下: 比较复制插入新建 参数说明: image: 输出图像,即绘制轮廓后的图像。 contours: 轮廓集合,每个轮廓由一系列点组成。 contourIdx: 轮廓索引数组,指定要绘制哪些轮廓。如果为NULL,则绘制所有轮廓。 contourC

    2024年01月19日
    浏览(40)
  • opencv基础48-绘制图像轮廓并切割示例-cv2.drawContours()

    在 OpenCV 中,可以使用函数 cv2.drawContours()绘制图像轮廓。该函数的语法格式是: image=cv2.drawContours( image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]] ) 其中,函数的返回值为 image,表示目标图像,即绘制了边缘的原始图像。 该函数有如下参数: image:待

    2024年02月13日
    浏览(33)
  • 【OpenCV-Python】——边缘和轮廓&Laplacian/Sobel/Canny边缘检测&查找/绘制轮廓及轮廓特征&霍夫直线/圆变换

    目录 前言: 1、边缘检测 1.1 Laplacian边缘检测  1.2 Sobel边缘检测  1.3 Canny边缘检测 2、图像轮廓 2.1 查找轮廓  2.2 绘制轮廓 2.3 轮廓特征 3、霍夫变换 3.1 霍夫直线变换  3.2 霍夫圆变换 总结: 图像的边缘是指图像中灰度值急剧变化的位置,边缘检测的目的是为了绘制边缘线条。

    2024年01月23日
    浏览(39)
  • 【Python】【OpenCV】绘制外接矩形、外接圆 以及 凸轮廓和Douglas-Peucker算法

     外接矩形、外接圆:   1、cv2.boundingRect() Method 和 cv2.minAreaRect() Merhod:前者只寻找和 x、y轴 平行的矩形,后者则可以出现旋转角度。 2、cv2.drawContours() Method:第二个参数接收的是轮廓信息,但是这个轮廓信息需要以 tuple or list or set类型(或者说是iterable)才可以传入。 请注

    2024年02月05日
    浏览(36)
  • OpenCV(三十五):凸包检测

    1.凸包检测介绍       凸包检测是计算凸包的一种技术,凸包就是:给定二维平面上的点集,将最外层的点连接起来构成的凸边形,它是包含点集中所有的点。 2.凸包检测函数convexHull() void cv::convexHull ( InputArray  points, OutputArray hull, boolclockwise = false, bool   returnPoints = true ) p

    2024年02月09日
    浏览(31)
  • opencv 凸包检测 convexHull

    2024年02月12日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包