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이 요리 책에 설명 된대로 내가 계속 잘못 일치하는 기능을 찾으려면 :

  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. 마지막에만 symmatrical 일치 쌍은 허용됩니다. 이것은 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 

good matches 결과는 꽤 좋다. 그러나 극단적 인 alikeness 결함의 경우에는 여전히 발생합니다.
위의 그림에서 비슷한 벽돌이 잘 인식되어 있음을 알 수 있습니다.

bad matches 그러나 두 번째 그림에서 잘못된 벽돌이 인식됩니다.

이제는 일치를 향상시킬 수있는 방법이 있습니다.

나는 두 개의 서로 다른 생각이 있었다 : 다시 정말 피팅 기능에 대한 두 번째 사진의 추적에

All possible brick views

  • 성냥을하지만, 시야가 강렬하게 변경되는 경우에만 가능합니다. 벽돌을 인식하기 위해서는 어쨌든 (그림 3과 같이) 여러 다른 위치에서 비교해야합니다. 즉, 시각 필드를 최소한으로 변경할 수 있음을 알고 있습니다. 시야가 얼마나 강하게 변화하는지에 대한 정보는 기본 매트릭스에 숨겨져 있어야합니다. 이 매트릭스에서 방의 위치가 얼마나 바뀌 었는지 어떻게 알 수 있습니까?특히 회전과 강한 스케일링이 중요합니다. 벽돌이 한 번 왼쪽에 더 가볍게 찍혀 있다면 이것은 중요하지 않습니다.

  • 두 번째 아이디어 :
    내가이 사진에서 기본 행렬을 계산 돌기에 맞지 않는 기능 필터링 -이 세 개 이상의 사진을 사용하여 동일한 작업을 수행 할 수있는 방법 안을? (키워드 Trifocal tensor). 이 방법은 매칭이 더 안정적이어야합니다. 하지만 OpenCV를 사용하여이 작업을 수행하는 방법을 알지 못하거나이 정보를 Google에서 찾을 수 없었습니다.

답변

2

나는 완전한 대답이 없지만 몇 가지 제안 사항이 있습니다. 이미지 분석 측면에서

는 : 카메라 설정이 꽤 상수처럼

  • 것 같습니다. 벽돌을 배경과 분리하기 쉽습니다. 또한 백그라운드에서 기능을 찾는 시스템을 볼 수 있습니다. 이것은 불필요합니다. 분석에서 제거하려면 모든 비 벽돌 픽셀을 검정색으로 설정하십시오. 당신은 단지 벽돌을 찾았 으면
  • , 당신의 첫 번째 단계는 벽돌의 크기 (픽셀 즉, 수)에 따라 후보들을 필터링 할 수 있어야합니다. 그런 식으로 당신이 보여주는 불완전한 일치는 이미 덜 가능성이 있습니다.
  • 당신은 벽돌의 경계 상자의 가로 세로 비율, 벽돌 등

이 단순한 기능의 major and minor axes (중앙 순간의 공분산 행렬의 eigevectors)로 계정에 다른 기능을 할 수 있습니다 검색 공간을 제한하는 합리적인 첫 번째 필터를 제공합니다. 벽돌 실제로 컨베이어 내려 오는 경우

  • 것은 당신이 방향과 각도에 자리 잡고 막대 같은 것을 사용하여 직선 가장자리를 따라 벽돌을 "똑바로"할 수 있어야한다 : 기계적인 측면에서

    브릭이 카메라에보다 균일하게 도달하도록 벨트를 가로 지르는 컨베이어의 길이를 조절하십시오. like so. 이전 점과 유사
  • , 당신은 그들이 통과 벽돌 서서 전복 벨트에 걸쳐 중단 매우 느슨한 붓 같은 것을 사용할 수 있습니다.

다시이 두 지점은 검색 공간을 제한합니다.