6

レゴ選別機を構築するためのレゴ ブロックを特定したいと考えています (opencv で c++ を使用しています)。つまり、非常によく似たオブジェクトを区別する必要があります。

レンガは平らなコンベアで個別にカメラに届きます。しかし、逆さま、横向き、または「通常」など、あらゆる方法で横たわる可能性があります。

私のアプローチは、さまざまな位置と回転でカメラを使ってレンガをテープで留めることで、選別機にレンガを教えることです。すべてのビューの特徴は、サーフ アルゴリズムによって計算されます。

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 Cookbook の説明に従って進めます。

  1. マッチャー (=cv::BFMatcher(cv::NORM_L2)) を使用すると、両方向の 2 つの最近傍が検索されます

    matcher.knnMatch(descriptorsImage1, descriptorsImage2,
      matches1,
          2);
    matcher.knnMatch(descriptorsImage2, descriptorsImage1,
      matches2,
      2);
    
  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
    

今ではかなり良い試合だけが残っています。いくつかの悪い一致を除外するために、基礎行列を使用して、どの一致が img2 上の img1 の射影に適合するかを確認します。

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

良い試合 結果はかなり良いです。ただし、極端な類似性障害の場合でも発生します。
上の写真では、同様のレンガがよく認識されていることがわかります。

悪い一致 ただし、2 番目の図では、間違ったレンガも認識されています。

ここで問題は、マッチングをどのように改善できるかです。

私には2つの異なるアイデアがありました:

すべての可能なブリック ビュー

  • 2 番目の写真の一致は、視野が大幅に変更された場合にのみ、機能が実際に適合していることを示しています。レンガを認識するためには、とにかく多くの異なる位置でそれを比較する必要があります (少なくとも図 3 に示されているように)。これは、視野を最小限に変更することしか許可されていないことを知っていることを意味します。視野がどれだけ激しく変化するかという情報は、基本マトリックスに隠されているはずです。部屋の位置がどれだけ変化したか、このマトリックスからどのように読み取ることができますか? 特に、回転と強力なスケーリングが重要です。レンガが一度左側にテープで留められていても、これは問題ではありません。

  • 2 番目のアイデア:
    2 つの写真から基本行列を計算し、投影に適合しない機能を除外しました。3 つ以上の写真を使用して同じことを行う方法はありませんか? (キーワード Trifocal tensor)。これにより、マッチングがより安定するはずです。しかし、OpenCV を使用してこれを行う方法も、Google でこれに関する情報を見つけることもできませんでした。

4

1 に答える 1

2

完全な答えはありませんが、いくつかの提案があります。

画像解析側:

  • カメラの設定はほぼ一定のようです。レンガを背景から分離するのは簡単です。また、システムがバックグラウンドで機能を見つけていることもわかります。これは不要です。レンガ以外のすべてのピクセルを黒に設定して、分析から除外します。
  • ブリックだけを見つけたら、最初のステップは、ブリック内のサイズ (つまり、ピクセル数) に基づいて可能性の高い候補をフィルタリングすることです。そうすれば、あなたが示す不完全な一致の例はすでに可能性が低くなります.
  • ブリックのバウンディング ボックスの縦横比、ブリックの長軸と短軸(中心モーメントの共分散行列の固有ベクトル)など、他の機能を考慮することができます。

これらのより単純な機能は、検索スペースを制限するための妥当な最初のフィルターを提供します。

機械的な側面:

  • レンガが実際にコンベヤーを下って来る場合は、ベルトを横切るコンベヤーの方向に対してある角度であるロッドのようなものを使用して、まっすぐな端に沿ってレンガを「まっすぐにする」ことができるはずです。カメラのように
  • 前のポイントと同様に、ベルト全体に吊り下げられた非常に緩いブラシのようなものを使用して、通り過ぎるときに立っているレンガを倒すことができます.

繰り返しますが、これらの両方の点により、検索スペースが制限されます。

于 2013-09-26T21:25:45.467 に答える