Opencv 3の学習-第14章輪郭マッチング
Opencvプロファイルの紹介については、https://blog.csdn.net/a40850273/article/details/88063478を参照してください。
瞬間
モーメントは、次のように計算される、輪郭、画像、およびポイントの高レベルの機能です。
場合には、画像内の各ピクセルの加重和として理解することができる 、即ち 、各画素の重みが1です、。バイナリイメージの場合(ピクセル値は1または0のいずれか)、 ゼロ以外のピクセル値の領域です。輪郭がある場合、それ は輪郭の長さです。同様に、 sum で 割る と、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として扱われます
ただし、上で取得したモーメントは、輪郭のスケーリングと回転により変化します。
並進不変性を満たす中心モーメント
画像または輪郭の場合、 並進不変性があります。しかし、高次モーメントにはこの機能はなくなります。中心モーメントは次のように定義されます
どこで
平行移動の不変性は、各ピクセルの中心を解くことによって正常に満たされます。その中でも、はっきりと入手でき ます。
同時に、スケーリング不変性を満たす正規化センターのモーメント
スケーリング不変性をさらに導入するために、正規化された中心モーメントが導入されます。これは次のように定義されます。
回転不変性を満たすHu不変モーメント
Huの不変モーメントは、中央のモーメントを正規化することによって線形に結合され、スケーリング、回転、および反射の 不変性を実現します(反射は満たされません)。
計算例を以下に示します
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つが含まれ、異なるメソッドは最終的に返される一致度に影響します
その中で、
- パラメータ:現在のアルゴリズムは使用されず、単純に初期値を使用できます。このパラメータは、主に将来の新しいメソッドに適応するためのもので、カスタムパラメータを使用する可能性があります
シェイプコンテキストを使用してシェイプを比較する
形状の一致にモーメントを使用したのは、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インターフェースに基づくシェイプの非類似性の別の尺度を提供します。
ハウスドルフ距離は、最初に画像内の各点について別の画像上の最も近い点を見つけます。最大距離はハウスドルフ距離です。ただし、ハウスドルフ距離は対称ではありません(ただし、特定の演算によって対称になる場合があります)。
、その中で
ハウスドルフ距離エクストラクタは、ファクトリメソッドcv :: createHausdorffDistanceExtractor()によって生成できます。
cv::Ptr<cv::HausdorffDistanceExtractor> cv::createHausdorffDistanceExtractor(
int distanceFlag = cv::NORM_L2,
float rankProp = 0.6
);
同時に、cv :: HausdorffDistanceExtractorとShape Context距離エクストラクターは同じインターフェースを持つため、cv :: computeDistance()を使用してターゲットまでの距離を計算することもできます。