Opencv4 cpp 求两个轮廓的最小距离

两种方案对比:
方案一:针对轮廓1做距离变换求轮廓2对应位置的最小值
方案二:轮廓点集最小距离

#include<iostream>
#include<opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int plan1(Mat img1, Mat img2, double & distRes) {
	Mat labels;
	connectedComponents(img1, labels, 8, CV_16U);//连通域提取
	Mat result(img1.size(), CV_32FC1, Scalar::all(0));
	for (int i = 0; i <= 0; i++)
	{
		Mat mask1 = labels == 1 + i;//提取标签信息,当满足条件返回255,不满足返回0
		//Mat mask2 = labels == 1 + (1 - i);
		Mat masknot;
		bitwise_not(mask1, masknot);
		Mat dist;
		distanceTransform(masknot, dist, DIST_L2, 5, CV_8U);
		dist.copyTo(result, img2); //核心一句,直接提取距离信息
	}
	//FileStorage fs("distCtr.yml", FileStorage::WRITE);
	//fs << "Image" << result;
	//fs.release();

	/*vector<vector<Point>> contours;
	findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	if (contours.size() != 2)return -1;
	Mat contourView1 = Mat::zeros(img.size(), CV_8UC1);
	Mat contourView2 = Mat::zeros(img.size(), CV_8UC1);
	drawContours(contourView1, contours, 0, Scalar(255), -1);
	drawContours(contourView2, contours, 1, Scalar(255), -1);*/

	cv::Point minLoc1, maxLoc1;
	double minVal1, maxVal1;
	cv::minMaxLoc(result, &minVal1, &maxVal1, &minLoc1, &maxLoc1, img2);
	distRes = minVal1;
	/*if (0) {
		cv::Point minLoc1, maxLoc1;
		double minVal1, maxVal1;
		cv::minMaxLoc(result, &minVal1, &maxVal1, &minLoc1, &maxLoc1, contourView1);

		cv::Point minLoc2, maxLoc2;
		double minVal2, maxVal2;
		cv::minMaxLoc(result, &minVal2, &maxVal2, &minLoc2, &maxLoc2, contourView2);

		Mat resultView = Mat::zeros(img.size(), CV_8UC3);
		resultView.setTo(Scalar(255, 255, 255), img);
		line(resultView, minLoc1, minLoc2, Scalar(0, 0, 255), 2);
	}*/
	return 0;
}

int plan2(Mat img1, Mat img2, double & distRes) {
	vector<vector<Point>> contours1;
	findContours(img1, contours1, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	vector<vector<Point>> contours2;
	findContours(img2, contours2, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	//if (contours.size() != 2)return-1;
	double distResMin = DBL_MAX;
	for (int i = 0; i < contours1[0].size(); ++i) {
		for (int j = 0; j < contours2[0].size(); ++j) {
			double distResTmp = pow(contours1[0][i].x - contours2[0][j].x, 2) + pow(contours1[0][i].y - contours2[0][j].y, 2);
			distResMin = min(distResTmp, distResMin);
		}
	}
	distRes = sqrt(distResMin);
	return 0;
}

int main() {
	Mat img = imread("twoContourView.png", IMREAD_GRAYSCALE);
	threshold(img, img, 200, 255, THRESH_BINARY); // to delete some noise

	vector<vector<Point>> contours;
	findContours(img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	if (contours.size() != 2)return -1;
	Mat contourView1 = Mat::zeros(img.size(), CV_8UC1);
	Mat contourView2 = Mat::zeros(img.size(), CV_8UC1);
	drawContours(contourView1, contours, 0, Scalar(255), -1);
	drawContours(contourView2, contours, 1, Scalar(255), -1);

	double distRes1 = 0;
	double distRes2 = 0;

	std::chrono::steady_clock::time_point start, end;
	std::chrono::duration<double> elapsed_seconds;
	start = std::chrono::steady_clock::now();

	plan1(contourView1, contourView2, distRes1);

	end = std::chrono::steady_clock::now();
	elapsed_seconds = end - start;
	double time = elapsed_seconds.count() * 1000;
	std::cout << "timePlan1: " << time << endl;
	std::cout << "distRes1: " << distRes1 << endl;

	start = std::chrono::steady_clock::now();

	plan2(contourView1, contourView2, distRes2);

	end = std::chrono::steady_clock::now();
	elapsed_seconds = end - start;
	time = elapsed_seconds.count() * 1000;
	std::cout << "timePlan2: " << time << endl;
	std::cout << "distRes2: " << distRes2 << endl;

	getchar();
	return 0;
}

参考:https://www.jianshu.com/p/33728ba5827d

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值