應用程序的要點是從已設置的圖像列表中識別圖像。圖像列表已將其SIFT描述符提取並保存在文件中。這裏沒有什麼有趣的:使用FLANN匹配從OpenCV SIFT列表中識別圖像
std::vector<cv::KeyPoint> detectedKeypoints;
cv::Mat objectDescriptors;
// Extract data
cv::SIFT sift;
sift.detect(image, detectedKeypoints);
sift.compute(image, detectedKeypoints, objectDescriptors);
// Save the file
cv::FileStorage fs(file, cv::FileStorage::WRITE);
fs << "descriptors" << objectDescriptors;
fs << "keypoints" << detectedKeypoints;
fs.release();
然後設備拍攝一張照片。 SIFT描述符以相同的方式提取。現在的想法是將描述符與文件中的描述符進行比較。我正在使用OpenCV的FLANN匹配器。我試圖量化相似度,逐個圖像。完成整個清單後,我應該有最好的匹配。
const cv::Ptr<cv::flann::IndexParams>& indexParams = new cv::flann::KDTreeIndexParams(1);
const cv::Ptr<cv::flann::SearchParams>& searchParams = new cv::flann::SearchParams(64);
// Match using Flann
cv::Mat indexMat;
cv::FlannBasedMatcher matcher(indexParams, searchParams);
std::vector<cv::DMatch> matches;
matcher.match(objectDescriptors, readDescriptors, matches);
匹配後,我明白,我得到的特徵向量之間的最近距離發現的列表。我發現的最小距離,並使用它,我可以指望「精彩的比賽」,甚至得到了各點的列表:
// Count the number of mathes where the distance is less than 2 * min_dist
int goodCount = 0;
for (int i = 0; i < objectDescriptors.rows; i++)
{
if (matches[i].distance < 2 * min_dist)
{
++goodCount;
// Save the points for the homography calculation
obj.push_back(detectedKeypoints[matches[i].queryIdx].pt);
scene.push_back(readKeypoints[matches[i].trainIdx].pt);
}
}
我展示的代碼的簡單的部分只是爲了使這更容易跟隨,我知道它不需要在這裏。
繼續,我希望簡單地計算這樣的好匹配的數量就足夠了,但事實證明,大多數情況下只是指向具有最多描述符的圖像。我在此之後嘗試的是計算單應性。目的是計算它,看看它是否是一個有效的homoraphy或不。希望是一場精彩的比賽,而且只有一場精彩的比賽,纔會有一個很好的轉變。創造了單應做簡單的使用CV :: findHomography在OBJ和現場這是的std ::矢量< CV :: Point2f>。
bool niceHomography(cv::Mat H)
{
std::cout << H << std::endl;
const double det = H.at<double>(0, 0) * H.at<double>(1, 1) - H.at<double>(1, 0) * H.at<double>(0, 1);
if (det < 0)
{
std::cout << "Homography: bad determinant" << std::endl;
return false;
}
const double N1 = sqrt(H.at<double>(0, 0) * H.at<double>(0, 0) + H.at<double>(1, 0) * H.at<double>(1, 0));
if (N1 > 4 || N1 < 0.1)
{
std::cout << "Homography: bad first column" << std::endl;
return false;
}
const double N2 = sqrt(H.at<double>(0, 1) * H.at<double>(0, 1) + H.at<double>(1, 1) * H.at<double>(1, 1));
if (N2 > 4 || N2 < 0.1)
{
std::cout << "Homography: bad second column" << std::endl;
return false;
}
const double N3 = sqrt(H.at<double>(2, 0) * H.at<double>(2, 0) + H.at<double>(2, 1) * H.at<double>(2, 1));
if (N3 > 0.002)
{
std::cout << "Homography: bad third row" << std::endl;
return false;
}
return true;
}
我不明白這背後的數學如此,在測試時,我有時會取代此功能和簡單的檢查是否同形的決定:我使用一些代碼,我在網上找到的檢查單應的有效性是積極的。問題是我在這裏一直有問題。這些單應性要麼不好,要麼不好(當我只檢查行列式時)。
我想我實際上應該使用單應性和許多點,只是使用它們在源圖像中的位置計算它們在目標圖像中的位置。然後我會比較這些平均距離,如果圖像正確,理想情況下我會得到一個非常明顯的較小平均距離。這完全不起作用根本就是。所有的距離都是巨大的。我想我可能已經用其他方式來計算正確的位置,但切換obj和場景彼此給出了類似的結果。
我想其它事情都不SURF描述符,而不是SIFT,BFMatcher(強力),而不是FLANN,得到ñ最小距離爲每一個圖像,而不是取決於最短距離的數字,或讓距離取決於全球最大距離。這些方法都沒有給我明確的好結果,我現在感覺卡住了。
我唯一的下一個策略是銳化圖像,甚至使用一些局部閾值或一些用於分割的算法將它們變成二值圖像。我正在尋找任何可以在我的工作中看到的建議或錯誤。
我不知道這是否相關,但我添加了一些我正在測試的圖像。在測試圖像中很多時候,大多數SIFT矢量都來自畫面(高對比度)。這就是爲什麼我認爲銳化圖像可能會奏效,但我不想更深入,以防我以前做的事情是錯誤的。
圖片庫是here與標題中的描述。這些圖片的分辨率相當高,請在查看時可能會給出一些提示。
嘿,我試圖做類似你的應用程序。你有沒有找到解決問題的辦法? – definera
邏輯很好,你可以按照它。你可能想查閱單應性,我想我必須改變它。但是,我無法再分享代碼,抱歉。 – octafbr