6

我想識別用於構建樂高分揀機(我使用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食譜描述:

  1. 與匹配(= CV :: BFMatcher(CV :: NORM_L2))兩個方向的兩個最近的鄰居搜索

    matcher.knnMatch(descriptorsImage1, descriptorsImage2, 
        matches1, 
         2); 
    matcher.knnMatch(descriptorsImage2, descriptorsImage1, 
        matches2, 
        2); 
    
  2. 我檢查找到的最近鄰居的距離之間的比例。如果兩個距離非常相似,那麼可能會使用錯誤的值。

    // loop for matches1 and matches2 
    for(iterator matchIterator over all matches) 
        if(((*matchIterator)[0].distance/(*matchIterator)[1].distance) > 0.65) 
        throw away 
    
  3. 最終只接受配對匹配對。這些匹配不僅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 

good matches 結果是相當不錯的。但在極端相似的情況下仍然會出現故障。
在上圖中,您可以看到類似的磚塊被很好地識別出來。

bad matches 但是,在第二張圖片中,錯誤的磚也被識別出來。

現在的問題是如何改善匹配。

我有兩個不同的想法:

All possible brick views

  • 在第二張圖片追溯至真是恰如其分特徵的匹配,但前提是視場激烈的改變。要認出磚頭,我必須在許多不同的位置比較它(至少如圖3所示)。這意味着我知道我只允許最小限度地改變視野。視野如何變化的信息應該隱藏在基本矩陣中。我怎麼能讀出這個矩陣在房間裏的位置變化了多遠?特別是旋轉和強壯的比例應該是有趣的;如果磚塊一旦被錄製在左側,這應該沒有關係。

  • 設想二:
    我計算的基本矩陣出2張圖片和過濾掉不適合的投影功能 - 不應該有一種方法做同樣的使用三個或更多的圖片? (關鍵詞三焦張量)。這樣匹配應該變得更加穩定。但我不知道如何使用OpenCV來做到這一點,我也不能在谷歌上找到關於此的任何信息。

回答

2

我沒有一個完整的答案,但我有一些建議。

圖像分析方面:

  • 它看起來像你的相機設置是相當恆定的。輕鬆將磚塊從背景中分離出來。我也看到你的系統在後臺查找功能。這是不必要的。將所有非磚像素設置爲黑色以將其從分析中移除。
  • 當你找到磚塊時,你的第一步應該是根據磚塊中的大小(即像素數量)過濾可能的候選項。這樣你顯示的錯誤匹配的例子已經不太可能了。
  • 可以採取其它的特徵考慮在內,如磚的邊界框的高寬比,磚等

這些簡單的功能的major and minor axes(中心矩的協方差矩陣的eigevectors)會給你一個合理的第一個過濾器來限制你的搜索空間。

在機械方面:

  • 如果磚塊實際上下來的傳送帶,你應該能夠一起使用類似的東西就在於一個角度的方向杆的直線邊緣「拉直」磚頭輸送帶穿過皮帶,以便磚更加均勻地到達您的相機like so
  • 與前一點相似,您可以使用類似於懸掛在皮帶上的非常鬆散的刷子,以便在磚塊通過時將磚塊翻倒。

這兩個點再次限制您的搜索空間。