6

Tôi muốn xác định các viên gạch lego để xây dựng một máy phân loại lego (tôi sử dụng C++ với opencv). Điều đó có nghĩa là tôi phải phân biệt giữa các đối tượng trông rất giống nhau.phân biệt đối tượng với opencv

Những viên gạch đang đến máy ảnh riêng của tôi trên băng chuyền phẳng. Nhưng họ có thể nằm trong bất kỳ cách nào có thể: lộn ngược, ở bên cạnh hoặc "bình thường".

Cách tiếp cận của tôi là dạy máy phân loại những viên gạch bằng cách chạm vào chúng bằng máy ảnh ở nhiều vị trí và phép quay khác nhau. Các tính năng của mỗi và mọi chế độ xem được tính theo tốc độ lướt sóng.

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); 
} 

Nếu có gạch không xác định (gạch mà tôi muốn sắp xếp), các tính năng của nó cũng được tính toán và khớp với các tính năng đã biết. Để tìm các tính năng phù hợp sai tôi tiến hành như mô tả trong cuốn sách OpenCV 2 Cookbook:

  1. với khớp (= cv :: BFMatcher (cv :: NORM_L2)) hai nước láng giềng gần nhất trong cả hai hướng được tìm kiếm

    matcher.knnMatch(descriptorsImage1, descriptorsImage2, 
        matches1, 
         2); 
    matcher.knnMatch(descriptorsImage2, descriptorsImage1, 
        matches2, 
        2); 
    
  2. Tôi kiểm tra tỷ lệ giữa khoảng cách của hàng xóm gần nhất được tìm thấy. Nếu hai khoảng cách rất giống nhau, có khả năng là một giá trị sai được sử dụng.

    // loop for matches1 and matches2 
    for(iterator matchIterator over all matches) 
        if(((*matchIterator)[0].distance/(*matchIterator)[1].distance) > 0.65) 
        throw away 
    
  3. Cuối cùng chỉ chấp nhận cặp kết hợp đối xứng. Đây là những kết quả phù hợp trong đó không chỉ n1 là hàng xóm gần nhất để tính năng f1, mà còn f1 là hàng xóm gần nhất với 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 
    

Bây giờ chỉ trận đấu khá tốt vẫn còn. Để lọc ra một số kết quả phù hợp xấu hơn, tôi kiểm tra xem kết quả phù hợp với phép chiếu của img1 trên img2 sử dụng ma trận cơ bản.

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 Kết quả là khá tốt. Nhưng trong trường hợp lỗi cực đoan vẫn còn xảy ra.
Trong hình trên, bạn có thể thấy rằng một viên gạch tương tự được nhận diện tốt.

bad matches Tuy nhiên trong hình thứ hai, gạch sai cũng được nhận dạng.

Bây giờ câu hỏi là làm thế nào tôi có thể cải thiện kết hợp.

tôi có hai ý kiến ​​khác nhau:

All possible brick views

  • Các trận đấu trong các dấu vết hình ảnh thứ hai trở lại các tính năng thực sự phù hợp, nhưng chỉ khi lĩnh vực thị giác được mãnh liệt thay đổi. Để nhận ra một viên gạch, tôi phải so sánh nó ở nhiều vị trí khác nhau (ít nhất là như trong hình 3). Điều này có nghĩa là tôi biết rằng tôi chỉ được phép thay đổi tối thiểu trường hình ảnh. Thông tin về mức độ mạnh mẽ của trường thị giác được thay đổi nên được ẩn trong ma trận cơ bản. Làm thế nào tôi có thể đọc ra khỏi ma trận này như thế nào đến nay vị trí trong phòng đã thay đổi?Đặc biệt là luân chuyển và quy mô mạnh nên được quan tâm; nếu viên gạch một lần được ghi âm ở phía bên trái thì điều này không quan trọng.

  • Ý tưởng thứ hai:
    Tôi đã tính ma trận cơ bản trong số 2 ảnh và lọc các tính năng không phù hợp với dự báo - không nên có cách nào để thực hiện tương tự bằng ba hoặc nhiều ảnh? (từ khóa Trifocal tensor). Bằng cách này, việc kết hợp sẽ trở nên ổn định hơn. Nhưng tôi không biết làm thế nào để làm điều này bằng cách sử dụng OpenCV cũng không phải tôi có thể tìm thấy bất kỳ thông tin về điều này trên google.

Trả lời

2

Tôi không có câu trả lời hoàn chỉnh, nhưng tôi có một vài gợi ý.

Về phía phân tích hình ảnh:

  • Dường như thiết lập máy ảnh của bạn là khá thường xuyên. Dễ dàng để chỉ tách gạch từ nền. Tôi cũng thấy các tính năng tìm kiếm hệ thống của bạn trong nền. Điều này là không cần thiết. Đặt tất cả các pixel không phải là gạch thành màu đen để xóa chúng khỏi phân tích.
  • Khi bạn đã đặt chỉ là viên gạch, bước đầu tiên của bạn nên là chỉ lọc các ứng viên có khả năng dựa trên kích thước (nghĩa là số pixel) trong khối. Bằng cách đó, ví dụ về sự phù hợp với lỗi mà bạn hiển thị đã ít có khả năng xảy ra hơn.
  • Bạn có thể lấy các tính năng khác vào tài khoản như tỷ lệ khía cạnh của khung giới hạn của gạch, các major and minor axes (eigevectors của ma trận hiệp phương sai trong những khoảnh khắc trung ương) của gạch, vv

Những tính năng đơn giản hơn sẽ cung cấp cho bạn bộ lọc đầu tiên hợp lý để giới hạn không gian tìm kiếm của bạn.

Về phía cơ khí:

  • Nếu gạch đang thực sự đi xuống một băng tải bạn sẽ có thể "thẳng" những viên gạch dọc theo một cạnh thẳng sử dụng một cái gì đó giống như một cây gậy mà nằm ở một góc để hướng của băng tải trên đai để các viên gạch đến đồng đều hơn ở máy ảnh của bạn like so.
  • Tương tự như điểm trước đó, bạn có thể sử dụng thứ gì đó giống như một bàn chải rất lỏng lơ lửng trên đai để lật đổ các viên gạch đứng lên khi chúng vượt qua.

Một lần nữa cả hai điểm này sẽ giới hạn không gian tìm kiếm của bạn.

Các vấn đề liên quan