第31课 轮廓周围绘制矩形框和圆形框

1. 步骤

  1. 首先将图像变为二值图像threshold()
  2. 发现轮廓,找到图像轮廓canny()
  3. 通过相关API在轮廓点上找到最小包含矩形和 圆,旋转矩形与椭圆。
  4. 绘制它们。rectangle()或circle()

2. 相关API

2.1 approxPolyDP()

  • 基于RDP算法实现,目的是减少多边形轮廓点数

2.2 cv::boundingRect()

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

2.3 cv::minAreaRect()

得到一个旋转的矩形,返回旋转矩形。

2.4 cv::minEnclosingCircle()

  • 得到最小区域圆形

2.5 cv::fitEllipse()

  • 得到最小椭圆

3. 例程

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

using namespace cv;
using namespace std;
void CallBack(int, void*);
Mat src, dst, binout, src_gray;
int Threshold = 40;

int main() {
	
	//输入图像并转化为灰度
	src = imread("D:/resource/images/硬币.jpg");
	if (src.empty()) {
		printf("src  couldn't be loaded...");
		return -1;
	}
	imshow("input", src);
	
	cvtColor(src, src_gray, COLOR_BGR2GRAY);
	medianBlur(src_gray, src_gray, 21);
	blur(src_gray, src_gray, Size(21, 21));


	//设置阈值后执行CallBack()
	namedWindow("output");
	createTrackbar("Threshold", "output", &Threshold, 255, CallBack);
	CallBack(0, 0);

	waitKey(0);
	return 0;
}

void CallBack(int, void*) {

	//二值化
	threshold(src_gray, binout, Threshold, 255, THRESH_BINARY);
	//Canny(src_gray, binout, Threshold, Threshold * 2);
	imshow("binary", ~binout);
	//寻找边缘
	vector<vector<Point>> contours;
	vector<Vec4i> hierachy;
	findContours(binout, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	 
	//得到矩形框和圆形框和椭圆框的的相关参数
	vector<vector<Point>> polies(contours.size());//减少后的多边形边缘上的点
	vector<Rect> rects(contours.size());//矩形框
	vector<Point2f> ccs(contours.size());//圆心
	vector<float> radius(contours.size());//圆的半径
	vector<RotatedRect> rotatedRects(contours.size());//旋转矩形框
	vector<RotatedRect> rotatedEllipces(contours.size());//旋转椭圆框
	for (size_t i = 0; i < contours.size(); i++) {
		approxPolyDP(Mat(contours[i]), polies[i], 3, true);//减少多边形边缘点
		rects[i] = boundingRect(polies[i]);
		minEnclosingCircle(polies[i], ccs[i], radius[i]);
		if (polies[i].size() > 5) {//旋转矩形和椭圆检测点至少需要5个
			rotatedEllipces[i] = fitEllipse(polies[i]);
			rotatedRects[i] = minAreaRect(polies[i]);
		}
	}
		//绘制他们
		Point2f pts[4];
		for (size_t i = 0; i < contours.size(); i++) {
			rectangle(src, rects[i], Scalar(255, 0, 0), 2);//画矩形框
			circle(src, ccs[i], radius[i], Scalar(0, 255, 255), 2, 8);//画圆
			if (polies.size() > 5) {
				ellipse(src, rotatedEllipces[i], Scalar(0, 0, 255), 2, 8);//画旋转椭圆

				rotatedRects[i].points(pts);//画旋转矩形
				for (int k = 0; k < 4; k++)
					line(src, pts[k], pts[(k + 1) % 4], Scalar(255, 255, 0), 2, 8);

			}

		}
		
	
    imshow("output", src);
	return;

		

}

在这里插入图片描述

发布了31 篇原创文章 · 获赞 12 · 访问量 2751

猜你喜欢

转载自blog.csdn.net/weixin_42877426/article/details/104399376