2016-03-11 37 views
6

Trong dự án opencv của tôi, tôi muốn phát hiện giả mạo sao chép trong một hình ảnh. Tôi biết cách sử dụng FLANN opencv cho tính năng phù hợp trong 2 hình ảnh khác nhau, nhưng tôi trở nên quá bối rối về cách sử dụng FLANN để phát hiện sự giả mạo sao chép-di chuyển trong một hình ảnh.Cách sử dụng tính năng đối sánh opencv để phát hiện giả mạo di chuyển sao chép

P.S1: Tôi nhận được điểm sift và mô tả hình ảnh và bị mắc kẹt khi sử dụng lớp đối sánh đối tượng địa lý.

P.S2: loại đối sánh đối tượng địa lý không quan trọng đối với tôi.

Xin cảm ơn trước.

Cập nhật:

Những hình ảnh là một ví dụ về những gì tôi cần

Input Image

Result

Và Có một mã mà phù hợp với đặc điểm của hai hình ảnh và làm một cái gì đó giống như nó trên hai hình ảnh (không phải là một hình duy nhất), mã ở định dạng opencv gốc android giống như sau:

vector<KeyPoint> keypoints; 
     Mat descriptors; 

     // Create a SIFT keypoint detector. 
     SiftFeatureDetector detector; 
     detector.detect(image_gray, keypoints); 
     LOGI("Detected %d Keypoints ...", (int) keypoints.size()); 

     // Compute feature description. 
     detector.compute(image, keypoints, descriptors); 
     LOGI("Compute Feature ..."); 


     FlannBasedMatcher matcher; 
     std::vector<DMatch> matches; 
     matcher.match(descriptors, descriptors, matches); 

     double max_dist = 0; double min_dist = 100; 

     //-- Quick calculation of max and min distances between keypoints 
      for(int i = 0; i < descriptors.rows; i++) 
      { double dist = matches[i].distance; 
      if(dist < min_dist) min_dist = dist; 
      if(dist > max_dist) max_dist = dist; 
      } 

      printf("-- Max dist : %f \n", max_dist); 
      printf("-- Min dist : %f \n", min_dist); 

      //-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist, 
      //-- or a small arbitary value (0.02) in the event that min_dist is very 
      //-- small) 
      //-- PS.- radiusMatch can also be used here. 
      std::vector<DMatch> good_matches; 

      for(int i = 0; i < descriptors.rows; i++) 
      { if(matches[i].distance <= max(2*min_dist, 0.02)) 
      { good_matches.push_back(matches[i]); } 
      } 

      //-- Draw only "good" matches 
      Mat img_matches; 
      drawMatches(image, keypoints, image, keypoints, 
         good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), 
         vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); 

      //-- Show detected matches 
//   imshow("Good Matches", img_matches); 
      imwrite(imgOutFile, img_matches); 
+1

Hiển thị mã và mẫu của hình ảnh mà bạn đang làm việc với hiện tại của bạn chắc chắn sẽ rất hữu ích. – alexisrozhkov

+0

@ user3896254 cảm ơn lời khuyên của bạn, tôi chỉnh sửa bài đăng của mình và thêm ví dụ và mã số – Evil

Trả lời

2

Tôi không biết có nên sử dụng các điểm chính cho vấn đề này hay không. Tôi muốn thử nghiệm template matching (sử dụng cửa sổ trượt trên hình ảnh của bạn làm bản vá). So với các điểm chính, phương pháp này có nhược điểm là hợp lý với luân chuyển và quy mô.

Nếu bạn muốn sử dụng keypoint, bạn có thể:

  • tìm một tập hợp các keypoint (SURF, SIFT, hoặc bất cứ điều gì bạn muốn),
  • tính toán số điểm phù hợp với tất cả các keypoint khác, với knnMatch chức năng của Brute Force Matcher (cv::BFMatcher),
  • giữ kết quả khớp giữa các điểm phân biệt, tức là các điểm có khoảng cách lớn hơn 0 (hoặc ngưỡng).

    int nknn = 10; // max number of matches for each keypoint 
    double minDist = 0.5; // distance threshold 
    
    // Match each keypoint with every other keypoints 
    cv::BFMatcher matcher(cv::NORM_L2, false); 
    std::vector< std::vector<cv::DMatch> > matches; 
    matcher.knnMatch(descriptors, descriptors, matches, nknn); 
    
    double max_dist = 0; double min_dist = 100; 
    
    //-- Quick calculation of max and min distances between keypoints 
    for(int i = 0; i < descriptors.rows; i++) 
    { 
        double dist = matches[i].distance; 
        if(dist < min_dist) min_dist = dist; 
        if(dist > max_dist) max_dist = dist; 
    } 
    
    // Compute distance and store distant matches 
    std::vector<cv::DMatch> good_matches; 
    for (int i = 0; i < matches.size(); i++) 
    { 
        for (int j = 0; j < matches[i].size(); j++) 
        { 
         // The METRIC distance 
         if(matches[i][j].distance> max(2*min_dist, 0.02)) 
          continue; 
    
         // The PIXELIC distance 
         Point2f pt1 = keypoints[queryIdx].pt; 
         Point2f pt2 = keypoints[trainIdx].pt; 
    
         double dist = cv::norm(pt1 - pt2); 
         if (dist > minDist) 
          good_matches.push_back(matches[i][j]); 
        } 
    } 
    
    Mat img_matches; 
    drawMatches(image_gray, keypoints, image_gray, keypoints, good_matches, img_matches); 
    
+1

@Vào đây là lời khuyên tôi sẽ làm theo. Nếu bạn có một hình ảnh của những gì cần phải được phát hiện sau đó sử dụng phù hợp với mẫu. Nếu không, hãy đi với ví dụ được hiển thị bởi Gwen. – John

+0

@Gwen Tôi đã rất bận rộn trong tuần này, tôi sẽ cố gắng giải pháp của bạn và cho bạn biết những gì đã xảy ra, BTW cảm ơn câu trả lời của bạn và cảm ơn cho giải pháp thay thế nhưng tôi cần phải sử dụng keypoints. – Evil

+0

@Gwen Tôi đã thử mã mẫu của bạn, nhưng cuối cùng nó không cho tôi kết quả tôi cần, nó cho tôi rất nhiều kết hợp và không hiển thị trong một hình ảnh duy nhất !!! (hiển thị trên cùng một hình ảnh bên cạnh nhau ...), Có sự trợ giúp nào khác không? cảm ơn trước. – Evil

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