我正在嘗試檢測兩個圓形物體之間的角度差,如下圖 2 所示。
我正在考慮以一些小角度旋轉影像之一。每次旋轉一張影像,將計算旋轉影像和另一張影像之間的 SSIM。SSIM 最大的角度就是角度差。
但是,找到極端從來都不是一個容易的問題。所以我的問題是:在這種情況下,是否可以使用另一種演算法(opencv)?
圖片#1

圖片#2

編輯:
謝謝@Micka,我只是按照他建議的方式進行操作,并像@Yves Daoust 所說的那樣洗掉黑色區域以縮短處理時間。這是我的最終結果:
原始影像
旋轉 移位影像

uj5u.com熱心網友回復:
這是一種方法:
- 檢測圓(例如我假設圓在影像中心,半徑是影像寬度的 50%)
- 按極坐標展開圓形影像
- 確保第二張圖片在第一張圖片中完全可見,沒有“圓端溢位”
- 簡單的模板匹配
以下代碼的結果:
min: 9.54111e 07
pos: [0, 2470]
angle-right: 317.571
angle-left: -42.4286
我認為這在一般情況下應該作業得很好。
int main()
{
// load images
cv::Mat image1 = cv::imread("C:/data/StackOverflow/circleAngle/circleAngle1.jpg");
cv::Mat image2 = cv::imread("C:/data/StackOverflow/circleAngle/circleAngle2.jpg");
// generate circle information. Here I assume image center and image is filled by the circles.
// use houghCircles or a RANSAC based circle detection instead, if necessary
cv::Point2f center1 = cv::Point2f(image1.cols/2.0f, image1.rows/2.0f);
cv::Point2f center2 = cv::Point2f(image2.cols / 2.0f, image2.rows / 2.0f);
float radius1 = image1.cols / 2.0f;
float radius2 = image2.cols / 2.0f;
cv::Mat unrolled1, unrolled2;
// define a size for the unrolling. Best might be to choose the arc-length of the circle. The smaller you choose this, the less resolution is available (the more pixel information of the circle is lost during warping)
cv::Size unrolledSize(radius1, image1.cols * 2);
// unroll the circles by warpPolar
cv::warpPolar(image1, unrolled1, unrolledSize, center1, radius1, cv::WARP_POLAR_LINEAR);
cv::warpPolar(image2, unrolled2, unrolledSize, center2, radius2, cv::WARP_POLAR_LINEAR);
// double the first image (720° of the circle), so that the second image is fully included without a "circle end overflow"
cv::Mat doubleImg1;
cv::vconcat(unrolled1, unrolled1, doubleImg1);
// the height of the unrolled image is exactly 360° of the circle
double degreesPerPixel = 360.0 / unrolledSize.height;
// template matching. Maybe correlation could be the better matching metric
cv::Mat matchingResult;
cv::matchTemplate(doubleImg1, unrolled2, matchingResult, cv::TemplateMatchModes::TM_SQDIFF);
double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
cv::Point matchLoc;
cv::minMaxLoc(matchingResult, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());
std::cout << "min: " << minVal << std::endl;
std::cout << "pos: " << minLoc << std::endl;
// angles in clockwise direction:
std::cout << "angle-right: " << minLoc.y * degreesPerPixel << std::endl;
std::cout << "angle-left: " << minLoc.y * degreesPerPixel -360.0 << std::endl;
double foundAngle = minLoc.y * degreesPerPixel;
// visualizations:
// display the matched position
cv::Rect pos = cv::Rect(minLoc, cv::Size(unrolled2.cols, unrolled2.rows));
cv::rectangle(doubleImg1, pos, cv::Scalar(0, 255, 0), 4);
// resize because the images are too big
cv::Mat resizedResult;
cv::resize(doubleImg1, resizedResult, cv::Size(), 0.2, 0.2);
cv::resize(unrolled1, unrolled1, cv::Size(), 0.2, 0.2);
cv::resize(unrolled2, unrolled2, cv::Size(), 0.2, 0.2);
double startAngleUpright = 0;
cv::ellipse(image1, center1, cv::Size(100, 100), 0, startAngleUpright, startAngleUpright foundAngle, cv::Scalar::all(255), -1, 0);
cv::resize(image1, image1, cv::Size(), 0.5, 0.5);
cv::imshow("image1", image1);
cv::imshow("unrolled1", unrolled1);
cv::imshow("unrolled2", unrolled2);
cv::imshow("resized", resizedResult);
cv::waitKey(0);
}
這是中間影像和結果的樣子:
展開影像 1 / 展開 2 / 展開 1 (720°) / 展開 1 (720°) 中展開 2 的最佳匹配:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/382329.html
上一篇:在多邊形中找到最大的內接矩形
