opencv2D姿态估计-canny+最小包矩形围盒minAreaRect

1来源

为了实现一个简单的demo 就是拍取了物体的照片之后确定一下其具体的分布。
本文采用的方式是canny算子+闭运算+最大轮廓+最小包围矩阵的方式求解的。下面是代码。
轮廓提取参考

2代码

#include <Eigen/Dense>
#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <vector>

//opencv
#include <opencv2/core/eigen.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
//#include <opencv2/rgbd.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/calib3d/calib3d.hpp>

using namespace std;
using namespace cv;
using namespace Eigen;

float getDistance(Point2f pointO, Point2f pointA)
{
	float distance;
	distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);
	distance = sqrtf(distance);
	return distance;
}


int main()
{
	Mat image,image_edge,kernel,image_edge_close,image_copy;
	vector<vector<Point>> contours;
	image = imread("D:\\vs2019_wkplace\\2DPART\\image1.png");
	//深拷贝
	image.copyTo(image_copy);
	//imshow("test", image);
	cv::Canny(image, image_edge, 50, 400); 
	//imshow("test1", image_edge);
	//闭运算 先膨胀后腐蚀,保证是对的
	kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
	cv::morphologyEx(image_edge, image_edge_close, cv::MORPH_CLOSE, kernel, Point(-1, -1), 2);
	imshow("test1", image_edge_close);
	//寻找轮廓
	vector<Vec4i> hierarchy;
	cv::findContours(image_edge_close, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_NONE);
	double maxarea = -1;
	int maxAreaIdx = -1;
	for (int i = 0; i < contours.size(); i++)
	{
		double tmparea = contourArea(contours[i]);
		if (tmparea > maxarea)
		{
			maxarea = tmparea;
			maxAreaIdx = i;//记录最大轮廓的索引号
		}
	}
	if (maxAreaIdx != -1) {
		cv::drawContours(image, contours, maxAreaIdx, (0, 0, 255), 2, 8);
		cv::imshow("轮廓", image);
		//cv::imwrite("image_right.png", image);
	}
	vector<Point> c = contours[maxAreaIdx];
	RotatedRect rect = minAreaRect(contours[maxAreaIdx]);
	//rectangle(image, rect.boundingRect(), Scalar(200));
	//求中心
	Point2f P[4], center,CENTER;
	center.x = 0;
	center.y = 0;
	rect.points(P);
	for (int j = 0; j <= 3; j++)
	{
		line(image_copy, P[j], P[(j + 1) % 4], Scalar(0, 0, 255), 10);
		center.x = center.x+P[j].x;
		center.y = center.y+P[j].y;
		cout << center << endl;
	}
	CENTER.y = center.y / 4;
	CENTER.x = center.x / 4;
	cout << CENTER << endl;
	circle(image_copy, CENTER, 3, Scalar(0, 255, 0),-1);
	

	//求x最小的点
	vector<Point2f> P_regroup;
	int min_idx = -1;
	float min_x = 9999;
	for (int i = 0; i <= 3; i++)
	{

		if (P[i].x <min_x)
		{
			min_x = P[i].x;
			min_idx = i;
		}
	}
	cout << "x 最小点为" << min_idx << endl;

	for (int i = 0; i <4; i++)
	{
		//P_regroup[i] = P[(min_idx + i) % 4];
		P_regroup.push_back(P[(min_idx + i) % 4]);
		cout << P[(min_idx + i) % 4 ]<< endl;
	}
	//长短边测试保证短边是X 长边是Y
	vector<Point2f> P_regroup2;

	vector<float> it;
	it.push_back(getDistance(P_regroup[0], P_regroup[1]));
	it.push_back(getDistance(P_regroup[0], P_regroup[3]));
	if (it[0]<it[1])
	{
		cout << "顶点在下一个点" << endl;
		for (int i = 0; i < 4; i++)
		{
			P_regroup2.push_back(P_regroup[(i + 1) % 4]);
		}
	}
	else
	{
		cout << "顶点就是这个点" << endl;
		for (int i = 0; i < 4; i++)
		{
			P_regroup2.push_back(P_regroup[i]);
		}
	}
	float x_length = getDistance(P_regroup2[3], P_regroup2[0]);
	vector<float> x_direction = { (P_regroup2[3].x - P_regroup2[0].x)/ x_length,(P_regroup2[3].y - P_regroup2[0].y)/ x_length };
	float y_length = getDistance(P_regroup2[1], P_regroup2[0]);
	vector<float> y_direction = { (P_regroup2[1].x - P_regroup2[0].x)/ y_length,(P_regroup2[1].y - P_regroup2[0].y)/ y_length };
	//画轴
	cv::Point  frontpt_x, frontpt_y;
	frontpt_x.x = CENTER.x + x_direction[0] * 50;
	frontpt_x.y = CENTER.y + x_direction[1] * 50;

	frontpt_y.x = CENTER.x + y_direction[0] * 50;
	frontpt_y.y = CENTER.y + y_direction[1] * 50;
	line(image_copy, CENTER, frontpt_x, (0, 255, 255), 10, 1);
	line(image_copy, CENTER, frontpt_y, (255, 255, 0), 10, 1);




	cout << "width*height*channel" << image.rows << "," << image.cols << "," << image.channels() << endl;
	imshow("image", image_copy);
	waitKey(0);
}

效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_37668446/article/details/107406022