この質問に対する答えが得られなかった後、私はいくつかの興味深い解決策に出くわしました。
この投稿の Robust Matcher と、この投稿のCanny Detectorです。
をセットアップし、Canny Edge Detector
そのドキュメントを参照して、リンクした最初のページに示されているものを実装した後Robust Matcher
、いくつかのロゴ/衣服の画像を取得し、2 つを組み合わせてある程度の成功を収めました。
しかし、他の非常によく似たケースでは、それはオフでした:
上記と「まったく」同じデザインの別のロゴ画像、同じ服の画像。
それで、与えられた画像の特定の領域を定義する画像上のいくつかの特定のポイントを一致させる方法はありますか?
したがって、画像を読み込んでからすべてのマッチングを行う代わりに、keypoints
「悪い」keypoints
などを破棄します。ある画像が別の画像とどのように関連しているかをシステムに認識keypoint
させ、ある画像で正しい一致を破棄することは可能ですか?隣り合っているのに、全く別の場所にいる?
(左の画像ではライトブルーとロイヤルブルーの「マッチ」が隣り合っていますが、右の画像では完全に別の部分でマッチしています)
編集
ミカのために
(ペイントで追加された)ホワイトボックスの中央に「長方形」が描かれています。
cv::Mat ransacTest(const std::vector<cv::DMatch>& matches, const std::vector<cv::KeyPoint>& trainKeypoints, const std::vector<cv::KeyPoint>& testKeypoints, std::vector<cv::DMatch>& outMatches){
// Convert keypoints into Point2f
std::vector<cv::Point2f> points1, points2;
cv::Mat fundemental;
for (std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it){
// Get the position of left keypoints
float x= trainKeypoints[it->queryIdx].pt.x;
float y= trainKeypoints[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints
x= testKeypoints[it->trainIdx].pt.x;
y= testKeypoints[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}
// Compute F matrix using RANSAC
std::vector<uchar> inliers(points1.size(), 0);
if (points1.size() > 0 && points2.size() > 0){
cv::Mat fundemental= cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), inliers, CV_FM_RANSAC, distance, confidence);
// matching points - match status (inlier or outlier) - RANSAC method - distance to epipolar line - confidence probability - extract the surviving (inliers) matches
std::vector<uchar>::const_iterator itIn= inliers.begin();
std::vector<cv::DMatch>::const_iterator itM= matches.begin();
// for all matches
for ( ;itIn!= inliers.end(); ++itIn, ++itM){
if (*itIn) { // it is a valid match
outMatches.push_back(*itM);
}
}
if (refineF){
// The F matrix will be recomputed with
// all accepted matches
// Convert keypoints into Point2f
// for final F computation
points1.clear();
points2.clear();
for(std::vector<cv::DMatch>::const_iterator it = outMatches.begin(); it!= outMatches.end(); ++it){
// Get the position of left keypoints
float x = trainKeypoints[it->queryIdx].pt.x;
float y = trainKeypoints[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints
x = testKeypoints[it->trainIdx].pt.x;
y = testKeypoints[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}
// Compute 8-point F from all accepted matches
if (points1.size() > 0 && points2.size() > 0){
fundemental= cv::findFundamentalMat(cv::Mat(points1),cv::Mat(points2), CV_FM_8POINT); // 8-point method
}
}
}
Mat imgMatchesMat;
drawMatches(trainCannyImg, trainKeypoints, testCannyImg, testKeypoints, outMatches, imgMatchesMat);//, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
Mat H = findHomography(points1, points2, CV_RANSAC, 3); // -- Little difference when CV_RANSAC is changed to CV_LMEDS or 0
//-- Get the corners from the image_1 (the object to be "detected")
std::vector<Point2f> obj_corners(4);
obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint(trainCannyImg.cols, 0);
obj_corners[2] = cvPoint(trainCannyImg.cols, trainCannyImg.rows); obj_corners[3] = cvPoint(0, trainCannyImg.rows);
std::vector<Point2f> scene_corners(4);
perspectiveTransform(obj_corners, scene_corners, H);
//-- Draw lines between the corners (the mapped object in the scene - image_2 )
line(imgMatchesMat, scene_corners[0] + Point2f(trainCannyImg.cols, 0), scene_corners[1] + Point2f(trainCannyImg.cols, 0), Scalar(0, 255, 0), 4);
line(imgMatchesMat, scene_corners[1] + Point2f(trainCannyImg.cols, 0), scene_corners[2] + Point2f(trainCannyImg.cols, 0), Scalar(0, 255, 0), 4);
line(imgMatchesMat, scene_corners[2] + Point2f(trainCannyImg.cols, 0), scene_corners[3] + Point2f(trainCannyImg.cols, 0), Scalar(0, 255, 0), 4);
line(imgMatchesMat, scene_corners[3] + Point2f(trainCannyImg.cols, 0), scene_corners[0] + Point2f(trainCannyImg.cols, 0), Scalar(0, 255, 0), 4);
//-- Show detected matches
imshow("Good Matches & Object detection", imgMatchesMat);
waitKey(0);
return fundemental;
}
ホモグラフィ出力
わずかに異なる入力シナリオ (絶えず変化するため、上記の画像を完全に繰り返すための正確な条件を把握するには時間がかかりすぎます) が、結果は同じです:
Object (52, 37)
Scene (219, 151)
Object (49, 47)
Scene (241,139)
Object (51, 50)
Scene (242, 141)
Object (37, 53)
Scene (228, 145)
Object (114, 37.2)
Scene (281, 162)
Object (48.96, 46.08)
Scene (216, 160.08)
Object (44.64, 54.72)
Scene (211.68, 168.48)
問題の画像: