我想識別用於構建樂高分揀機(我使用opencv的C++)的樂高積木。 這意味着我必須區分看起來非常相似的物體。使用opencv區分對象
這些磚塊正在我的相機單獨在平板輸送機上。但他們可能會以任何可能的方式:顛倒,側面或「正常」。
我的方法是通過用相機拍攝很多不同的位置和旋轉來教給分揀機磚塊。每個視圖的特徵都是通過surf-algorythm來計算的。
void calculateFeatures(const cv::Mat& image,
std::vector<cv::KeyPoint>& keypoints,
cv::Mat& descriptors)
{
// detector == cv::SurfFeatureDetector(10)
detector->detect(image,keypoints);
// extractor == cv::SurfDescriptorExtractor()
extractor->compute(image,keypoints,descriptors);
}
如果有一個未知的磚(即我要排序的磚)其功能也得到計算,並與人們已知的匹配。 要找到錯誤匹配的特徵我繼續在書中OpenCV的2食譜描述:
與匹配(= CV :: BFMatcher(CV :: NORM_L2))兩個方向的兩個最近的鄰居搜索
matcher.knnMatch(descriptorsImage1, descriptorsImage2, matches1, 2); matcher.knnMatch(descriptorsImage2, descriptorsImage1, matches2, 2);
我檢查找到的最近鄰居的距離之間的比例。如果兩個距離非常相似,那麼可能會使用錯誤的值。
// loop for matches1 and matches2 for(iterator matchIterator over all matches) if(((*matchIterator)[0].distance/(*matchIterator)[1].distance) > 0.65) throw away
最終只接受配對匹配對。這些匹配不僅n1是特徵f1的最近鄰,而且f1也是n1的最近鄰。
for(iterator matchIterator1 over all matches) for(iterator matchIterator2 over all matches) if ((*matchIterator1)[0].queryIdx == (*matchIterator2)[0].trainIdx && (*matchIterator2)[0].queryIdx == (*matchIterator1)[0].trainIdx) // good Match
現在只有相當不錯的比賽依然存在。爲了濾除更多不良匹配,我使用基本矩陣檢查了哪些匹配符合img1在img2上的投影。
std::vector<uchar> inliers(points1.size(),0);
cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matching points
inliers,
CV_FM_RANSAC,
3,
0.99);
std::vector<cv::DMatch> goodMatches
// extract the surviving (inliers) matches
std::vector<uchar>::const_iterator itIn= inliers.begin();
std::vector<cv::DMatch>::const_iterator itM= allMatches.begin();
// for all matches
for (;itIn!= inliers.end(); ++itIn, ++itM)
if (*itIn)
// it is a valid match
結果是相當不錯的。但在極端相似的情況下仍然會出現故障。
在上圖中,您可以看到類似的磚塊被很好地識別出來。
但是,在第二張圖片中,錯誤的磚也被識別出來。
現在的問題是如何改善匹配。
我有兩個不同的想法:
在第二張圖片追溯至真是恰如其分特徵的匹配,但前提是視場激烈的改變。要認出磚頭,我必須在許多不同的位置比較它(至少如圖3所示)。這意味着我知道我只允許最小限度地改變視野。視野如何變化的信息應該隱藏在基本矩陣中。我怎麼能讀出這個矩陣在房間裏的位置變化了多遠?特別是旋轉和強壯的比例應該是有趣的;如果磚塊一旦被錄製在左側,這應該沒有關係。
設想二:
我計算的基本矩陣出2張圖片和過濾掉不適合的投影功能 - 不應該有一種方法做同樣的使用三個或更多的圖片? (關鍵詞三焦張量)。這樣匹配應該變得更加穩定。但我不知道如何使用OpenCV來做到這一點,我也不能在谷歌上找到關於此的任何信息。