レゴ選別機を構築するためのレゴ ブロックを特定したいと考えています (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 の説明に従って進めます。
マッチャー (=cv::BFMatcher(cv::NORM_L2)) を使用すると、両方向の 2 つの最近傍が検索されます
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
最後に、対称的な一致ペアのみが受け入れられます。これらは、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 でこれに関する情報を見つけることもできませんでした。