Opencv 3の学習-第14章輪郭マッチング

Opencv 3の学習-第14章輪郭マッチング

Opencvプロファイルの紹介については、https://blog.csdn.net/a40850273/article/details/88063478を参照してください。

瞬間

モーメントは、次のように計算される、輪郭、画像、およびポイントの高レベルの機能です。

場合には、画像内の各ピクセルの加重和として理解することができる  x = 0、y = 0、即ち  m_ {00}、各画素の重みが1です、。バイナリイメージの場合(ピクセル値は1または0のいずれか)、  m_ {00} ゼロ以外のピクセル値の領域です。輪郭がある場合、それ  m_ {00} は輪郭の長さです。同様に、  m_ {10} sum  m_ {01} 割る  m_ {00}と、x方向とy方向の画像の平均値を意味します。

cv :: moments()は、画像のモーメントを計算するために使用されます

cv::Moments cv::moments(             // Return structure contains moments
  cv::InputArray points,             // 2-dimensional points or an "image"
  bool           binaryImage = false // false='interpret image values as "mass"'
)

パラメータの紹介:

  • 点:2次元配列(画像)または一連の点(輪郭)にすることができます。
  • binaryImage:Trueの場合、ゼロ以外のすべてのピクセル値は1として扱われます

ただし、上で取得したモーメントは、輪郭のスケーリングと回転により変化します。

並進不変性を満たす中心モーメント

画像または輪郭の場合、m_ {00} 並進不変性があります。しかし、高次モーメントにはこの機能はなくなります。中心モーメントは次のように定義されます

どこ

平行移動の不変性は、各ピクセルの中心を解くことによって正常に満たされます。その中でも、はっきりと入手でき  mu_ {00} = m_ {00}、mu_ {10} = mu_ {01} = 0ます。

同時に、スケーリング不変性を満たす正規化センターのモーメント

スケーリング不変性をさらに導入するために、正規化された中心モーメントが導入されます。これは次のように定義されます。

 

回転不変性を満たすHu不変モーメント

Huの不変モーメントは、中央のモーメントを正規化することによって線形に結合され、スケーリング、回転、および反射のh_1 不変性を実現します(反射は満たされません)。

計算例を以下に示します

void cv::HuMoments(
  const cv::Moments& moments, // Input is result from cv::moments() function
  double*            hu       // Return is C-style array of 7 Hu moments
);

cv :: HuMoments()は、cv :: Momentsのオブジェクトを渡すことにより、上記の7つのhuモーメントを計算します。

Hu Momentsを使用して一致させる

cv :: matchShapes()は、提供された2つの目標に基づいてモーメントを自動的に計算し、最後に、ユーザーが指定した基準に基づいてそれらを比較します。

double  cv::MatchShapes(
  cv::InputArray object1,      // First array of 2D points or cv:U8C1 image
  cv::InputArray object2,      // Second array of 2D points or cv:U8C1 image
  int            method,       // Comparison method (Table 14-4)
  double         parameter = 0 // Method-specific parameter
);

パラメータの説明:

  • object1、object2:2つの入力ターゲットは、グレースケールイメージまたは輪郭である必要があります
  • メソッド:一致するメソッドには次の3つが含まれ、異なるメソッドは最終的に返される一致度に影響します

その中で、\ eta_i ^ x = sign(h_i ^ x)\ cdot log(h_i ^ x)

  • パラメータ:現在のアルゴリズムは使用されず、単純に初期値を使用できます。このパラメータは、主に将来の新しいメソッドに適応するためのもので、カスタムパラメータを使用する可能性があります

シェイプコンテキストを使用してシェイプを比較する

形状の一致にモーメントを使用したのは、1980年代までさかのぼります。同時に、最新のアルゴリズムが引き続き表示されますが、現在のShapeモジュールはまだ開発中であるため、ここでは高レベルのインターフェイスを簡単に紹介します。

Shapeモジュールの構造

Shapeの構築は、抽象クラスcv :: ShapeDistanceExtractorに基づいています。負でない数を返します。2つの形状がまったく同じ場合は、0を返します。

class ShapeContextDistanceExtractor : public ShapeDistanceExtractor {
  public:
  ...
  virtual float computeDistance( InputArray contour1, InputArray contour2 ) = 0;
};

特定の形状距離抽出クラスは、この基本クラスcv :: ShapeDistanceExtractorから派生します。ここでは、2つのcv :: ShapeTransformerとcv :: HistogramCostExtractorについて簡単に紹介します。

class ShapeTransformer : public Algorithm {

public:
  virtual void estimateTransformation(
    cv::InputArray      transformingShape,
    cv::InputArray      targetShape,
    vector<cv::DMatch>& matches
  ) = 0;

  virtual float applyTransformation(
    cv::InputArray      input,
    cv::OutputArray     output      = noArray()
  ) = 0;

  virtual void warpImage(
    cv::InputArray      transformingImage,
    cv::OutputArray     output,
    int                 flags       = INTER_LINEAR,
    int                 borderMode  = BORDER_CONSTANT,
    const cv::Scalar&   borderValue = cv::Scalar()
  ) const = 0;
};

class HistogramCostExtractor : public Algorithm {

public:
  virtual void  buildCostMatrix(
    cv::InputArray      descriptors1,
    cv::InputArray      descriptors2,
    cv::OutputArray     costMatrix
  )        
                                         = 0;
  virtual void  setNDummies( int nDummies )         = 0;
  virtual int   getNDummies() const                 = 0;

  virtual void  setDefaultCost( float defaultCost ) = 0;
  virtual float getDefaultCost() const              = 0;
};

シェイプトランスフォーマーは、ポイントの1つの山から別のポイントの山へのリマッピングアルゴリズムのクラスを表します。アフィン変換と透視変換の両方は、形状変換(cv :: ThinPlateSplineShapeTransformer in Opencv)によって実現できます。

ヒストグラムコストエクストラクタは、ヒストグラム内のあるグリッドから別のグリッドにシャベルの汚れをマッピングします。一般的に使用される派生クラスは次のとおりです

各エクストラクターとトランスフォーマーには、cv :: createChiHistogramCostExtractor()などのファクトリーメソッド(createX())があります。

形状コンテキスト距離エクストラクタ

namespace cv {

  class ShapeContextDistanceExtractor : public ShapeDistanceExtractor {

    public:
    ...
    virtual float computeDistance( 
      InputArray contour1, 
      InputArray contour2 
      ) = 0;
  };

  Ptr<ShapeContextDistanceExtractor> createShapeContextDistanceExtractor(
    int   nAngularBins                          = 12,
    int   nRadialBins                           = 4,
    float innerRadius                           = 0.2f,
    float outerRadius                           = 2,
    int   iterations                            = 3,
    const Ptr<HistogramCostExtractor> &comparer 
                                        = createChiHistogramCostExtractor(),
    const Ptr<ShapeTransformer>       &transformer
                                        = createThinPlateSplineShapeTransformer()
  );
}

基本的に、Shape Contextアルゴリズムは、比較される2つ以上のオブジェクトの表現を計算します。各特性評価は、形状のエッジ上の一連のサブポイントに基づいており、サンプリングポイントごとに、特定のヒストグラムを作成して、視点からの極座標系の形状を反映します。すべてのヒストグラムのサイズは同じnAngularBins * nRadialBinsです。一致する2つのオブジェクト上の点は、カイ2乗に基づいて距離を計算します。次に、アルゴリズムは、一致する2つのオブジェクトの最適な1:1ポイントマッチングを計算して、カイ2乗距離の最小合計を取得します。このアルゴリズムは高速ではありませんが、比較的良い結果を提供できます。

#include "opencv2/opencv.hpp"
#include <algorithm>
#include <iostream>
#include <string>

using namespace std;
using namespace cv;

static vector<Point> sampleContour( const Mat& image, int n=300 ) {

  vector<vector<Point> > _contours;
  vector<Point> all_points;
  findContours(image, _contours, RETR_LIST, CHAIN_APPROX_NONE);
  for (size_t i=0; i <_contours.size(); i++) {
    for (size_t j=0; j <_contours[i].size(); j++)
      all_points.push_back( _contours[i][j] );

  // If too little points, replicate them
//
  int dummy=0;
  for (int add=(int)all_points.size(); add<n; add++)
    all_points.push_back(all_points[dummy++]);

  // Sample uniformly
  random_shuffle(all_points.begin(), all_points.end());
  vector<Point> sampled;
  for (int i=0; i<n; i++)
    sampled.push_back(all_points[i]);
  return sampled;
}

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

  string path    = "../data/shape_sample/";
  int indexQuery = 1;

  Ptr<ShapeContextDistanceExtractor> mysc = createShapeContextDistanceExtractor();

  Size sz2Sh(300,300);
  Mat img1=imread(argv[1], IMREAD_GRAYSCALE);
  Mat img2=imread(argv[2], IMREAD_GRAYSCALE);
  vector<Point> c1 = sampleContour(img1);
  vector<Point> c2 = sampleContour(img2);
  float dis = mysc->computeDistance( c1, c2 );
  cout << "shape context distance between " <<
     argv[1] << " and " << argv[2] << " is: " << dis << endl;

  return 0;
}

ハウスドルフ距離抽出器

シェイプコンテキスト距離と同様に、ハウスドルフ距離は、cv :: ShapeDistanceExtractorインターフェースに基づくシェイプの非類似性の別の尺度を提供します。

ハウスドルフ距離は、最初に画像内の各点について別の画像上の最も近い点を見つけます。最大距離はハウスドルフ距離です。ただし、ハウスドルフ距離は対称ではありません(ただし、特定の演算によって対称になる場合があります)。

H(A、B)= max(h(A、B)、h(B、A))、その中で 

ハウスドルフ距離エクストラクタは、ファクトリメソッドcv :: createHausdorffDistanceExtractor()によって生成できます。

cv::Ptr<cv::HausdorffDistanceExtractor> cv::createHausdorffDistanceExtractor(
  int   distanceFlag = cv::NORM_L2,
  float rankProp     = 0.6
);

同時に、cv :: HausdorffDistanceExtractorとShape Context距離エクストラクターは同じインターフェースを持つため、cv :: computeDistance()を使用してターゲットまでの距離を計算することもできます。

おすすめ

転載: blog.csdn.net/a40850273/article/details/107391302