两种方案对比:
方案一:针对轮廓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