1

2つの画像があると想像してください。どちらも同じように見えますが、違いがあります。たとえば、image1画像にはパンフレットがありますが、image2ありませんが、image2 の他のすべては image1 と同じです。

これが私のコードです:

#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include <opencv2/nonfree/features2d.hpp>

using namespace cv;

void readme();


int main( int argc, char** argv )
{


  Mat img_object = imread( "C:/Users/Yohan/Pictures/ironManSpecial2.jpg",CV_LOAD_IMAGE_GRAYSCALE);
  Mat img_scene = imread("C:/Users/Yohan/Pictures/noIronMan.jpg",CV_LOAD_IMAGE_GRAYSCALE);

  if( !img_object.data || !img_scene.data )
  { std::cout<< " --(!) Error reading images " << std::endl; return -1; }

  //-- Step 1: Detect the keypoints using SURF Detector
  int minHessian = 400;

  SurfFeatureDetector detector( minHessian );

  std::vector<KeyPoint> keypoints_object, keypoints_scene;

  detector.detect( img_object, keypoints_object );
  detector.detect( img_scene, keypoints_scene );

  //-- Step 2: Calculate descriptors (feature vectors)
  SurfDescriptorExtractor extractor;

  Mat descriptors_object, descriptors_scene;

  extractor.compute( img_object, keypoints_object, descriptors_object );
  extractor.compute( img_scene, keypoints_scene, descriptors_scene );

  //-- Step 3: Matching descriptor vectors using FLANN matcher
  FlannBasedMatcher matcher;
  std::vector< DMatch > matches;
  matcher.match( descriptors_object, descriptors_scene, matches );

  double max_dist = 0; double min_dist = 100;

  //-- Quick calculation of max and min distances between keypoints
  for( int i = 0; i < descriptors_object.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 3*min_dist )
  std::vector< DMatch > good_matches;

  for( int i = 0; i < descriptors_object.rows; i++ )
  { if( matches[i].distance < 3*min_dist )
    { good_matches.push_back( matches[i]); }
  }  

  Mat img_matches;
  drawMatches( img_object, keypoints_object, img_scene, keypoints_scene, 
               good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), 
               vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); 


  //-- Localize the object from img_1 in img_2 
  std::vector<Point2f> obj;
  std::vector<Point2f> scene;

  for( int i = 0; i < good_matches.size(); i++ )
  {
    //-- Get the keypoints from the good matches
    obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
    scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt ); 
  }

  Mat H = findHomography( obj, scene, CV_RANSAC );

  //-- Get the corners from the image_1 ( the object to be "detected" )
  std::vector<Point2f> obj_corners(4);
  obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
  obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
  std::vector<Point2f> scene_corners(4);

  perspectiveTransform( obj_corners, scene_corners, H);


  //-- Draw lines between the corners (the mapped object in the scene - image_2 )
  line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );
  line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
  line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
  line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );

  //-- Show detected matches
  namedWindow( "Good Matches & Object detection", CV_WINDOW_NORMAL );
  imshow( "Good Matches & Object detection", img_matches );

  waitKey(0);

  return 0;
}

上記のコードは、「一致」を見つけるためのものです。その結果がこれ

ここに画像の説明を入力

image1 (左側の画像) には「Iron Man 3 Brochure」がありますが、image2 (右側の画像) にはありません。ここで、image2 に「何か」が欠けていることを見つけて、コンソールにメッセージを出力する必要があります。

考慮すべきことは、この「Iron Man 3 Brochure」は単なる例であり、実際のシナリオでは何が欠けているのかわかりません.

これどうやってするの?

4

2 に答える 2

2

画像について事前にどのような情報を取得しますか? 存在する特定のオブジェクト、向き、特性などに応じて、それらはすべて外観が似ていますか? この情報があれば、簡単なポイント マッチング アルゴリズムを使用できます (つまり、特異値分解の計算など)。

そうでない場合、最も簡単な方法は、いくつかの一般的な方法を使用して有用な統計を収集することです。

まず、いくつかの単純なノイズ除去フィルタとともに、ヒストグラムの均等化またはヒストグラムの正規化を検討します (つまり、ガウス ノイズがあり、単純な平滑化フィルタを適用する必要がありますか、またはインパルス/ソルト ペッパー ノイズで、中央値/モードを適用する必要がありますか?フィルター?)。

次に、画像に関する基本的な統計を取得します。平均強度値、およびそれぞれの分散/標準偏差を取得します。2 つの画像間のわずかな変化である場合、両方の画像のこれらの値は非常に似ているはずです。そうでない場合は、フィルタリングとイコライゼーションの段階を再検討する必要があるかもしれません。

最後に、主成分分析のようなものを検討します (つまり、共分散行列を計算し、その固有値を計算し、2 つの最大値を決定し、それらの値に関連付けられた固有ベクトルを計算します)。これにより、画像の最も暗いまたは最も明るい特徴を、位置合わせと配置 (重心) とともに見つけることができます。基本的に、両方の画像を重ね合わせ、同じ向きにすることができます。

これを配置すると、両方の画像の端をトリミング/トリミングすることができ、非常によく似た 2 つの整列した画像が得られます。ここで、しきい値フィルターを適用すると、画像が白黒に縮小され、ある画像から別の画像を差し引くことができます。2 つの画像に適用された前の操作のおかげで、2 つの画像の違いは最も明確な特徴だけになり、事実上、それをグラフィカルに定義するマスクになります。

お役に立てれば。このアプローチを検討し、正しい方向に進んでいることがわかった場合は、より多くの情報を提供できます。

幸運を!

于 2013-09-19T20:27:29.710 に答える
2

見つけたキーポイントを使用して画像を整列させてから、ピクセル単位の違いを見つけるか、テンプレート マッチング アルゴリズムを適用できます。

于 2013-09-19T20:15:16.477 に答える