特徴検出

cv::Canny

Comments from the Wiki

void Canny(const Mat& image, Mat& edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)

Cannyアルゴリズムを用いて,画像のエッジを検出します.

パラメタ:
  • image – 8ビット,シングルチャンネルの入力画像.
  • edges – 出力されるエッジのマップ. image と同じサイズ,同じ型です.
  • threshold1 – ヒステリシスが存在する処理の,1番目の閾値.
  • threshold2 – ヒステリシスが存在する処理の,2番目の閾値.
  • apertureSizeSobel() オペレータのアパーチャサイズ.
  • L2gradient – 画像勾配の強度を求めるために,より精度の高い L_2 ノルム =\sqrt{(dI/dx)^2 + (dI/dy)^2} を利用するか, L_1 ノルム =|dI/dx|+|dI/dy| で十分( L2gradient=false )かを指定します.

関数 Canny は,Cannyアルゴリズムを用いて入力画像 image 中のエッジを検出し,マップ edges に出力します. threshold1threshold2 の内,小さい方の値がエッジの接続に利用され,大きい方の値が明確なエッジの初期セグメントを検出するのに利用されます.詳しくは, http://en.wikipedia.org/wiki/Canny_edge_detector を参照してください.

cv::cornerEigenValsAndVecs

Comments from the Wiki

void cornerEigenValsAndVecs(const Mat& src, Mat& dst, int blockSize, int apertureSize, int borderType=BORDER_DEFAULT)

コーナーを検出するために,画像ブロックの固有値と固有ベクトルを求めます.

パラメタ:
  • src – 8ビットまたは浮動小数点型,シングルチャンネルの入力画像.
  • dst – 結果を格納する画像. src と同じサイズで,型は CV_32FC(6) です.
  • blockSize – 近傍領域のサイズ(説明を参照してください).
  • apertureSizeSobel() オペレータで利用するアパーチャパラメータ.
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください.

関数 cornerEigenValsAndVecs は,各ピクセル p に対して, blockSize \times blockSize サイズの近傍領域 S(p) を考えます.そして,この近傍領域の微分画像の共変動行列を次のように求めます:

M =  \begin{bmatrix} \sum _{S(p)}(dI/dx)^2 &  \sum _{S(p)}(dI/dx dI/dy)^2  \\ \sum _{S(p)}(dI/dx dI/dy)^2 &  \sum _{S(p)}(dI/dy)^2 \end{bmatrix}

ここで,微分画像は Sobel() オペレータを利用して求められます.

その後,行列 M の固有値と固有ベクトルを求め,それを出力画像に (\lambda_1, \lambda_2, x_1, y_1, x_2, y_2) という形式で格納します.ここで, (\lambda_1, \lambda_2, x_1, y_1, x_2, y_2) where

  • [ \lambda_1, \lambda_2 ] M の固有値.格納されません.
  • [ x_1, y_1 ] \lambda_1 に対する固有ベクトル.
  • [ x_2, y_2 ] \lambda_2 に対する固有ベクトル.

となります.

この関数の出力は,ロバストなエッジ検出やコーナー検出に利用できます.

参考: cornerMinEigenVal() , cornerHarris() , preCornerDetect()

cv::cornerHarris

Comments from the Wiki

void cornerHarris(const Mat& src, Mat& dst, int blockSize, int apertureSize, double k, int borderType=BORDER_DEFAULT)

Harris エッジ検出器.

パラメタ:
  • src – 8ビットまたは浮動小数点型,シングルチャンネルの入力画像.
  • dst – Harris検出器の応答が格納される画像.型は CV_32FC1 で, src と同じサイズです.
  • blockSize – 近傍領域のサイズ( cornerEigenValsAndVecs() の説明を参照してください).
  • apertureSizeSobel() オペレータで利用するアパーチャパラメータ.
  • k – Harris 検出器のフリーパラメータ.以下の式を参照してください.
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください.

関数 cornerHarris は,画像に対して Harris エッジ検出器を適用します. cornerMinEigenVal()cornerEigenValsAndVecs() と同様に, \texttt{blockSize} \times \texttt{blockSize} サイズの近傍領域全体に渡って勾配の積和を計算することで,ピクセル (x, y) における 2\times2 の勾配の共変動行列 M^{(x,y)} を求めます.そして,そこから次の特徴量を計算します:

\texttt{dst} (x,y) =  \mathrm{det} M^{(x,y)} - k  \cdot \left ( \mathrm{tr} M^{(x,y)} \right )^2

画像中のコーナーは,この応答マップの極大点として検出されます.

cv::cornerMinEigenVal

Comments from the Wiki

void cornerMinEigenVal(const Mat& src, Mat& dst, int blockSize, int apertureSize=3, int borderType=BORDER_DEFAULT)

コーナーを検出するために,勾配行列の最小の固有値を求めます.

パラメタ:
  • src – 8ビットまたは浮動小数点型,シングルチャンネルの入力画像.
  • dst – 最小固有値が格納される画像.型は CV_32FC1 で, src と同じサイズです.
  • blockSize – 近傍領域のサイズ( cornerEigenValsAndVecs() の説明を参照してください).
  • apertureSizeSobel() オペレータで利用するアパーチャパラメータ.
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください.

関数 cornerMinEigenVal は, cornerEigenValsAndVecs() と似ていますが,微分画像の共変動行列の最小固有値だけを求めます.つまり, cornerEigenValsAndVecs() の説明にある式の \min(\lambda_1, \lambda_2) だけを求めます.

cv::cornerSubPix

Comments from the Wiki

void cornerSubPix(const Mat& image, vector<Point2f>& corners, Size winSize, Size zeroZone, TermCriteria criteria)

コーナー位置を高精度化します.

パラメタ:
  • image – 入力画像.
  • corners – 入力コーナーの初期座標.これが高精度化されたものが,再びここに出力されます.
  • winSize – 探索窓のサイズの半分.例えば winSize=Size(5,5) の場合,5*2+1 \times 5*2+1 = 11 \times 11 サイズの探索窓が利用されます.
  • zeroZone – 探索領域の中心に存在する対象外領域(後述の式において総和を計算する際に含まれない)の半分のサイズ.この値は,自己相関行列において発生しうる特異点を避けるために用いられます. 値が (-1,-1) の場合は,そのようなサイズはないということを意味します.
  • criteria – コーナー位置高精度化のための繰り返し処理の停止基準.つまり,この繰り返し処理は,規定回数に達するか要求精度に達したときに終了します. criteria は,最大反復数と要求精度のどちらか,あるいは両方を指定します.

関数 cornerSubPix は,以下の図に示されるような,サブピクセル精度のコーナー,あるいは鞍点を検出するために繰り返し処理を行います.

_images/cornersubpix5.png

サブピクセル精度のコーナー位置決めは,近傍領域の中心 q から,その領域内に位置する点 p に向かう各ベクトルが, p における(画像自身と観測ノイズに従う)画像勾配と直交する,という考えに基づいています.これは,以下の式で表現されます:

\epsilon _i = {DI_{p_i}}^T  \cdot (q - p_i)

ここで {DI_{p_i}} は,近傍領域 q 内の点 p_i における画像勾配を表します. q は,この \epsilon_i を最小にする値として求められます. \epsilon_i を 0 とすることで連立方程式が得られます:

\sum _i(DI_{p_i}  \cdot {DI_{p_i}}^T) -  \sum _i(DI_{p_i}  \cdot {DI_{p_i}}^T  \cdot p_i)

ここで,画像勾配は q の近傍領域(「探索窓」)での総和をとられます.1次勾配を G ,2次勾配を b とすると,以下の関係が得られます:

q = G^{-1}  \cdot b

このアルゴリズムは,探索窓の中心をこの新しい値 q に再設定し,値の変化量が与えられた閾値内に収まるようになるまで繰り返し計算を行います.

cv::goodFeaturesToTrack

Comments from the Wiki

void goodFeaturesToTrack(const Mat& image, vector<Point2f>& corners, int maxCorners, double qualityLevel, double minDistance, const Mat& mask=Mat(), int blockSize=3, bool useHarrisDetector=false, double k=0.04)

画像内の強いコーナーを検出します.

パラメタ:
  • image – 8ビットまたは浮動小数点型,シングルチャンネルの入力画像.
  • corners – 検出されたコーナーが出力されるベクトル.
  • maxCorners – 出力されるコーナーの最大数.これより多い数のコーナーが検出された場合,より強いコーナーが出力されます.
  • qualityLevel – 許容される画像コーナーの最低品質を決定します.このパラメータ値を,最良のコーナーを示す測度( cornerMinEigenVal() で述べた最小固有値や, cornerHarris() で述べた Harris 関数の応答)に乗じます.その掛け合わされた値よりも品質度が低いコーナーは,棄却されます.例えば,コーナーの最高品質度 = 1500, qualityLevel=0.01 である場合,品質度が15より小さいすべてのコーナーが棄却されます.
  • minDistance – 出力されるコーナー間で許容される,最小ユークリッド距離.
  • mask – オプションのROI.これが空ではない場合(型は CV_8UC1 で,サイズは image と同じ必要があります),それはコーナーの検出対象となる領域を示します.
  • blockSize – ピクセル近傍領域における微分画像の共変動行列を求める際に利用されます,平均化ブロックサイズ. cornerEigenValsANdVecs() を参照してください.
  • useHarrisDetector – Harris オペレータ,または cornerMinEigenVal() のどちらを利用するかを示します.
  • k – Harris 検出器のフリーパラメータ.

この関数は, Shi94 で述べられるように,画像中または画像の指定領域内の最も強いコーナーを検出します:

  1. この関数はまず, cornerMinEigenVal() または cornerHarris() を利用して,入力画像の全ピクセルにおけるコーナー品質度を求めます.
  2. 次に,non-maxima suppression を行います(つまり 3\times 3 の近傍領域における極大値のみを残します).
  3. 次のステップでは, \texttt{qualityLevel} \cdot \max_{x,y} qualityMeasureMap(x,y) よりも小さい最小固有値をもつコーナーを棄却します.
  4. 残ったコーナーは,品質度の高い順番に保持されます.
  5. 最後に,この関数は,距離 minDistance 以内に,自分よりも強いコーナー pt_i ( i < j ) が存在するようなコーナー pt_j を削除します.

この関数は,点ベースの物体追跡器を初期化するために利用できます.

この関数が,パラメータ qualityLevel に異なる値 AB を与えられて呼び出され,その時に A > {B} であるとします.その場合,出力コーナー配列において qualityLevel=A で求められたコーナーの配列が, qualityLevel=B で求められたものよりも前に位置することに注意してください.

参考: cornerMinEigenVal() , cornerHarris() , calcOpticalFlowPyrLK() , estimateRigidMotion() , PlanarObjectDetector() , OneWayDescriptor()

cv::HoughCircles

Comments from the Wiki

void HoughCircles(Mat& image, vector<Vec3f>& circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0)

ハフ変換を用いて,グレースケール画像から円を検出します.

パラメタ:
  • image – 8ビット,シングルチャンネル,グレースケールの入力画像.
  • circles – 検出された円を出力するベクトル.各ベクトルは,3要素の浮動小数点型ベクトル (x, y, radius) としてエンコードされます.
  • method – 現在のところ, CV_HOUGH_GRADIENT メソッドのみが実装されています.基本的には 2段階ハフ変換 で,これについては Yuen90 で述べられています.
  • dp – 画像分解能に対する投票分解能の比率の逆数.例えば, dp=1 の場合は,投票空間は入力画像と同じ分解能をもちます.また dp=2 の場合は,投票空間の幅と高さは半分になります.
  • minDist – 検出される円の中心同士の最小距離.このパラメータが小さすぎると,正しい円の周辺に別の円が複数誤って検出されることになります.逆に大きすぎると,検出できない円がでてくる可能性があります.
  • param1 – 手法依存の 1 番目のパラメータ. CV_HOUGH_GRADIENT の場合は, Canny() エッジ検出器に渡される2つの閾値の内,大きい方の閾値を表します(小さい閾値は,この値の半分になります).
  • param2 – 手法依存の 2 番目のパラメータ. CV_HOUGH_GRADIENT の場合は,円の中心を検出する際の投票数の閾値を表します.これが小さくなるほど,より多くの誤検出が起こる可能性があります.より多くの投票を獲得した円が,最初に出力されます.
  • minRadius – 円の半径の最小値.
  • maxRadius – 円の半径の最大値.

関数 houghCircles は,ハフ変換の改良版を用いてグレースケール画像から円を検出します.ここでは,簡単な利用例を示します:

#include <cv.h>
#include <highgui.h>
#include <math.h>

using namespace cv;

int main(int argc, char** argv)
{
    Mat img, gray;
    if( argc != 2 && !(img=imread(argv[1], 1)).data)
        return -1;
    cvtColor(img, gray, CV_BGR2GRAY);
    // 平滑化を行います.これがないと誤検出が起こりやすくなります.
    GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
    vector<Vec3f> circles;
    HoughCircles(gray, circles, CV_HOUGH_GRADIENT,
                 2, gray->rows/4, 200, 100 );
    for( size_t i = 0; i < circles.size(); i++ )
    {
         Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
         int radius = cvRound(circles[i][2]);
         // 円の中心を描画します.
         circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
         // 円を描画します.
         circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
    }
    namedWindow( "circles", 1 );
    imshow( "circles", img );
    return 0;
}

通常,この関数は円の中心を上手く検出しますが,円の半径については失敗することもある点に注意してください.もし事前知識があれば,半径の範囲( minRadiusmaxRadius )を指定することで,これの補助ができます.または,出力された半径は無視して中心だけを利用し,別の追加処理によって正しい半径を求めることもできます.

参考: fitEllipse() , minEnclosingCircle()

cv::HoughLines

Comments from the Wiki

void HoughLines(Mat& image, vector<Vec2f>& lines, double rho, double theta, int threshold, double srn=0, double stn=0)

標準ハフ変換を用いて,2値画像から直線を検出します.

パラメタ:
  • image – 8ビット,シングルチャンネルの2値入力画像.この画像は関数により書き換えられる可能性があります.
  • lines – 検出された直線が出力されるベクトル.各直線は,2要素のベクトル (\rho, \theta) で表現されます. \rho は原点(画像の左上コーナー)からの距離, \theta はラジアン単位で表される直線の回転角度(0 \sim 垂直線, \pi/2 \sim 水平線)です.
  • rho – ピクセル単位で表される投票空間の距離分解能.
  • theta – ラジアン単位で表される投票空間の角度分解能.
  • threshold – 投票の閾値パラメータ.十分な票( >\texttt{threshold} )を得た直線のみが出力されます.
  • srn – マルチスケールハフ変換において,距離分解能 rho の除数となる値.投票空間の粗い距離分解能は rho となり,細かい分解能は rho/srn となります.もし srn=0 かつ stn=0 の場合は,古典的ハフ変換が利用されます.そうでない場合は,両方のパラメータが正値である必要があります.
  • stn – マルチスケールハフ変換において,角度分解能 theta の除数となる値.

関数 HoughLines は,直線検出のためのハフ変換,またはマルチスケールハフ変換の実装です.コードの例については, HoughLinesP() を参照してください.

cv::HoughLinesP

Comments from the Wiki

void HoughLinesP(Mat& image, vector<Vec4i>& lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0)

確率的ハフ変換を利用して,2値画像から線分を検出します.

パラメタ:
  • image – 8ビット,シングルチャンネルの2値入力画像.この画像は関数により書き換えられる可能性があります.
  • lines – 検出された線分が出力されるベクトル.各線分は,4要素のベクトル (x_1, y_1, x_2, y_2) で表現されます.ここで (x_1,y_1) および (x_2, y_2) は,検出された各線分の端点です.
  • rho – ピクセル単位で表される投票空間の距離分解能.
  • theta – ラジアン単位で表される投票空間の角度分解能.
  • threshold – 投票の閾値パラメータ.十分な票( >\texttt{threshold} )を得た直線のみが出力されます.
  • minLineLength – 最小の線分長.これより短い線分は棄却されます.
  • maxLineGap – 2点が同一線分上にあると見なす場合に許容される最大距離.

関数 HoughLinesP は, Matas00 で述べられている,直線検出のための確率的ハフ変換アルゴリズムの実装です.以下に直線検出の例を示します:

/* これは,単独で動作するプログラムです.プログラムの最初の引数として画像ファイル名を渡します.
   "#if 1" を "#if 0" に変更したり戻したりすることで,
   標準的ハフ変換と確率的ハフ変換を切り替えることができます.  */
#include <cv.h>
#include <highgui.h>
#include <math.h>

using namespace cv;

int main(int argc, char** argv)
{
    Mat src, dst, color_dst;
    if( argc != 2 || !(src=imread(argv[1], 0)).data)
        return -1;

    Canny( src, dst, 50, 200, 3 );
    cvtColor( dst, color_dst, CV_GRAY2BGR );

#if 0
    vector<Vec2f> lines;
    HoughLines( dst, lines, 1, CV_PI/180, 100 );

    for( size_t i = 0; i < lines.size(); i++ )
    {
        float rho = lines[i][0];
        float theta = lines[i][1];
        double a = cos(theta), b = sin(theta);
        double x0 = a*rho, y0 = b*rho;
        Point pt1(cvRound(x0 + 1000*(-b)),
                  cvRound(y0 + 1000*(a)));
        Point pt2(cvRound(x0 - 1000*(-b)),
                  cvRound(y0 - 1000*(a)));
        line( color_dst, pt1, pt2, Scalar(0,0,255), 3, 8 );
    }
#else
    vector<Vec4i> lines;
    HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
    for( size_t i = 0; i < lines.size(); i++ )
    {
        line( color_dst, Point(lines[i][0], lines[i][1]),
            Point(lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 );
    }
#endif
    namedWindow( "Source", 1 );
    imshow( "Source", src );

    namedWindow( "Detected Lines", 1 );
    imshow( "Detected Lines", color_dst );

    waitKey(0);
    return 0;
}

サンプル画像.上記のプログラムはこの画像用にパラメータを調整しています:

_images/building5.jpg

上記のプログラムにおいて確率的ハフ変換を行った結果:

_images/houghp5.png

cv::preCornerDetect

Comments from the Wiki

void preCornerDetect(const Mat& src, Mat& dst, int apertureSize, int borderType=BORDER_DEFAULT)

コーナー検出のための特徴マップを求めます.

パラメタ:
  • src – 8ビットまたは浮動小数点型,シングルチャンネルの入力画像.
  • dst – タイプが CV_32Fsrc と同じサイズの出力画像.
  • apertureSizeSobel() のアパーチャサイズ.
  • borderType – ピクセル外挿手法. borderInterpolate() を参照してください.

関数 preCornerDetect は,入力画像の,複合偏微分に基づいた写像を求めます.

\texttt{dst} = (D_x  \texttt{src} )^2  \cdot D_{yy}  \texttt{src} + (D_y  \texttt{src} )^2  \cdot D_{xx}  \texttt{src} - 2 D_x  \texttt{src} \cdot D_y  \texttt{src} \cdot D_{xy}  \texttt{src}

ここで D_x , D_y は画像の1次微分, D_{xx} , D_{yy} は画像の2次微分, D_{xy} は混合微分です.

次に示すように,コーナーは,この写像の極大値として得られます:

Mat corners, dilated_corners;
preCornerDetect(image, corners, 3);
// 3x3 の矩形構造要素で膨張させます.
dilate(corners, dilated_corners, Mat(), 1);
Mat corner_mask = corners == dilated_corners;

目次

前のトピックへ

モーション解析と物体追跡

次のトピックへ

物体検出

このページ