特徴検出 ============ .. highlight:: cpp .. index:: Canny cv::Canny --------- `id=0.821832627353 Comments from the Wiki `__ .. cfunction:: void Canny( const Mat\& image, Mat\& edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false ) Cannyアルゴリズムを用いて,画像のエッジを検出します. :param image: 8ビット,シングルチャンネルの入力画像. :param edges: 出力されるエッジのマップ. ``image`` と同じサイズ,同じ型です. :param threshold1: ヒステリシスが存在する処理の,1番目の閾値. :param threshold2: ヒステリシスが存在する処理の,2番目の閾値. :param apertureSize: :func:`Sobel` オペレータのアパーチャサイズ. :param L2gradient: 画像勾配の強度を求めるために,より精度の高い :math:`L_2` ノルム :math:`=\sqrt{(dI/dx)^2 + (dI/dy)^2}` を利用するか, :math:`L_1` ノルム :math:`=|dI/dx|+|dI/dy|` で十分( ``L2gradient=false`` )かを指定します. 関数 ``Canny`` は,Cannyアルゴリズムを用いて入力画像 ``image`` 中のエッジを検出し,マップ ``edges`` に出力します. ``threshold1`` と ``threshold2`` の内,小さい方の値がエッジの接続に利用され,大きい方の値が明確なエッジの初期セグメントを検出するのに利用されます.詳しくは, http://en.wikipedia.org/wiki/Canny_edge_detector を参照してください. .. index:: cornerEigenValsAndVecs cv::cornerEigenValsAndVecs -------------------------- `id=0.941266594433 Comments from the Wiki `__ .. cfunction:: void cornerEigenValsAndVecs( const Mat\& src, Mat\& dst, int blockSize, int apertureSize, int borderType=BORDER_DEFAULT ) コーナーを検出するために,画像ブロックの固有値と固有ベクトルを求めます. :param src: 8ビットまたは浮動小数点型,シングルチャンネルの入力画像. :param dst: 結果を格納する画像. ``src`` と同じサイズで,型は ``CV_32FC(6)`` です. :param blockSize: 近傍領域のサイズ(説明を参照してください). :param apertureSize: :func:`Sobel` オペレータで利用するアパーチャパラメータ. :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください. 関数 ``cornerEigenValsAndVecs`` は,各ピクセル :math:`p` に対して, ``blockSize`` :math:`\times` ``blockSize`` サイズの近傍領域 :math:`S(p)` を考えます.そして,この近傍領域の微分画像の共変動行列を次のように求めます: .. math:: 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} ここで,微分画像は :func:`Sobel` オペレータを利用して求められます. その後,行列 :math:`M` の固有値と固有ベクトルを求め,それを出力画像に :math:`(\lambda_1, \lambda_2, x_1, y_1, x_2, y_2)` という形式で格納します.ここで, :math:`(\lambda_1, \lambda_2, x_1, y_1, x_2, y_2)` where * [ :math:`\lambda_1, \lambda_2` ] :math:`M` の固有値.格納されません. * [ :math:`x_1, y_1` ] :math:`\lambda_1` に対する固有ベクトル. * [ :math:`x_2, y_2` ] :math:`\lambda_2` に対する固有ベクトル. となります. この関数の出力は,ロバストなエッジ検出やコーナー検出に利用できます. 参考: :func:`cornerMinEigenVal` , :func:`cornerHarris` , :func:`preCornerDetect` .. index:: cornerHarris cv::cornerHarris ---------------- `id=0.378551439919 Comments from the Wiki `__ .. cfunction:: void cornerHarris( const Mat\& src, Mat\& dst, int blockSize, int apertureSize, double k, int borderType=BORDER_DEFAULT ) Harris エッジ検出器. :param src: 8ビットまたは浮動小数点型,シングルチャンネルの入力画像. :param dst: Harris検出器の応答が格納される画像.型は ``CV_32FC1`` で, ``src`` と同じサイズです. :param blockSize: 近傍領域のサイズ( :func:`cornerEigenValsAndVecs` の説明を参照してください). :param apertureSize: :func:`Sobel` オペレータで利用するアパーチャパラメータ. :param k: Harris 検出器のフリーパラメータ.以下の式を参照してください. :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください. 関数 ``cornerHarris`` は,画像に対して Harris エッジ検出器を適用します. :func:`cornerMinEigenVal` や :func:`cornerEigenValsAndVecs` と同様に, :math:`\texttt{blockSize} \times \texttt{blockSize}` サイズの近傍領域全体に渡って勾配の積和を計算することで,ピクセル :math:`(x, y)` における :math:`2\times2` の勾配の共変動行列 :math:`M^{(x,y)}` を求めます.そして,そこから次の特徴量を計算します: .. math:: \texttt{dst} (x,y) = \mathrm{det} M^{(x,y)} - k \cdot \left ( \mathrm{tr} M^{(x,y)} \right )^2 画像中のコーナーは,この応答マップの極大点として検出されます. .. index:: cornerMinEigenVal cv::cornerMinEigenVal --------------------- `id=0.443522333903 Comments from the Wiki `__ .. cfunction:: void cornerMinEigenVal( const Mat\& src, Mat\& dst, int blockSize, int apertureSize=3, int borderType=BORDER_DEFAULT ) コーナーを検出するために,勾配行列の最小の固有値を求めます. :param src: 8ビットまたは浮動小数点型,シングルチャンネルの入力画像. :param dst: 最小固有値が格納される画像.型は ``CV_32FC1`` で, ``src`` と同じサイズです. :param blockSize: 近傍領域のサイズ( :func:`cornerEigenValsAndVecs` の説明を参照してください). :param apertureSize: :func:`Sobel` オペレータで利用するアパーチャパラメータ. :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください. 関数 ``cornerMinEigenVal`` は, :func:`cornerEigenValsAndVecs` と似ていますが,微分画像の共変動行列の最小固有値だけを求めます.つまり, :func:`cornerEigenValsAndVecs` の説明にある式の :math:`\min(\lambda_1, \lambda_2)` だけを求めます. .. index:: cornerSubPix cv::cornerSubPix ---------------- `id=0.728476123476 Comments from the Wiki `__ .. cfunction:: void cornerSubPix( const Mat\& image, vector\& corners, Size winSize, Size zeroZone, TermCriteria criteria ) コーナー位置を高精度化します. :param image: 入力画像. :param corners: 入力コーナーの初期座標.これが高精度化されたものが,再びここに出力されます. :param winSize: 探索窓のサイズの半分.例えば ``winSize=Size(5,5)`` の場合,5*2+1 :math:`\times` 5*2+1 = 11 :math:`\times` 11 サイズの探索窓が利用されます. :param zeroZone: 探索領域の中心に存在する対象外領域(後述の式において総和を計算する際に含まれない)の半分のサイズ.この値は,自己相関行列において発生しうる特異点を避けるために用いられます. 値が (-1,-1) の場合は,そのようなサイズはないということを意味します. :param criteria: コーナー位置高精度化のための繰り返し処理の停止基準.つまり,この繰り返し処理は,規定回数に達するか要求精度に達したときに終了します. ``criteria`` は,最大反復数と要求精度のどちらか,あるいは両方を指定します. 関数 ``cornerSubPix`` は,以下の図に示されるような,サブピクセル精度のコーナー,あるいは鞍点を検出するために繰り返し処理を行います. .. image:: ../../pics/cornersubpix.png サブピクセル精度のコーナー位置決めは,近傍領域の中心 :math:`q` から,その領域内に位置する点 :math:`p` に向かう各ベクトルが, :math:`p` における(画像自身と観測ノイズに従う)画像勾配と直交する,という考えに基づいています.これは,以下の式で表現されます: .. math:: \epsilon _i = {DI_{p_i}}^T \cdot (q - p_i) ここで :math:`{DI_{p_i}}` は,近傍領域 :math:`q` 内の点 :math:`p_i` における画像勾配を表します. :math:`q` は,この :math:`\epsilon_i` を最小にする値として求められます. :math:`\epsilon_i` を 0 とすることで連立方程式が得られます: .. math:: \sum _i(DI_{p_i} \cdot {DI_{p_i}}^T) - \sum _i(DI_{p_i} \cdot {DI_{p_i}}^T \cdot p_i) ここで,画像勾配は :math:`q` の近傍領域(「探索窓」)での総和をとられます.1次勾配を :math:`G` ,2次勾配を :math:`b` とすると,以下の関係が得られます: .. math:: q = G^{-1} \cdot b このアルゴリズムは,探索窓の中心をこの新しい値 :math:`q` に再設定し,値の変化量が与えられた閾値内に収まるようになるまで繰り返し計算を行います. .. index:: goodFeaturesToTrack cv::goodFeaturesToTrack ----------------------- `id=0.629520624692 Comments from the Wiki `__ .. cfunction:: void goodFeaturesToTrack( const Mat\& image, vector\& corners, int maxCorners, double qualityLevel, double minDistance, const Mat\& mask=Mat(), int blockSize=3, bool useHarrisDetector=false, double k=0.04 ) 画像内の強いコーナーを検出します. :param image: 8ビットまたは浮動小数点型,シングルチャンネルの入力画像. :param corners: 検出されたコーナーが出力されるベクトル. :param maxCorners: 出力されるコーナーの最大数.これより多い数のコーナーが検出された場合,より強いコーナーが出力されます. :param qualityLevel: 許容される画像コーナーの最低品質を決定します.このパラメータ値を,最良のコーナーを示す測度( :func:`cornerMinEigenVal` で述べた最小固有値や, :func:`cornerHarris` で述べた Harris 関数の応答)に乗じます.その掛け合わされた値よりも品質度が低いコーナーは,棄却されます.例えば,コーナーの最高品質度 = 1500, ``qualityLevel=0.01`` である場合,品質度が15より小さいすべてのコーナーが棄却されます. :param minDistance: 出力されるコーナー間で許容される,最小ユークリッド距離. :param mask: オプションのROI.これが空ではない場合(型は ``CV_8UC1`` で,サイズは ``image`` と同じ必要があります),それはコーナーの検出対象となる領域を示します. :param blockSize: ピクセル近傍領域における微分画像の共変動行列を求める際に利用されます,平均化ブロックサイズ. :func:`cornerEigenValsANdVecs` を参照してください. :param useHarrisDetector: Harris オペレータ,または :func:`cornerMinEigenVal` のどちらを利用するかを示します. :param k: Harris 検出器のフリーパラメータ. この関数は, Shi94 で述べられるように,画像中または画像の指定領域内の最も強いコーナーを検出します: #. この関数はまず, :func:`cornerMinEigenVal` または :func:`cornerHarris` を利用して,入力画像の全ピクセルにおけるコーナー品質度を求めます. #. 次に,non-maxima suppression を行います(つまり :math:`3\times 3` の近傍領域における極大値のみを残します). #. 次のステップでは, :math:`\texttt{qualityLevel} \cdot \max_{x,y} qualityMeasureMap(x,y)` よりも小さい最小固有値をもつコーナーを棄却します. #. 残ったコーナーは,品質度の高い順番に保持されます. #. 最後に,この関数は,距離 ``minDistance`` 以内に,自分よりも強いコーナー :math:`pt_i` ( :math:`i < j` ) が存在するようなコーナー :math:`pt_j` を削除します. この関数は,点ベースの物体追跡器を初期化するために利用できます. この関数が,パラメータ ``qualityLevel`` に異なる値 ``A`` と ``B`` を与えられて呼び出され,その時に ``A`` > {B} であるとします.その場合,出力コーナー配列において ``qualityLevel=A`` で求められたコーナーの配列が, ``qualityLevel=B`` で求められたものよりも前に位置することに注意してください. 参考: :func:`cornerMinEigenVal` , :func:`cornerHarris` , :func:`calcOpticalFlowPyrLK` , :func:`estimateRigidMotion` , :func:`PlanarObjectDetector` , :func:`OneWayDescriptor` .. index:: HoughCircles cv::HoughCircles ---------------- `id=0.386288598453 Comments from the Wiki `__ .. cfunction:: void HoughCircles( Mat\& image, vector\& circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 ) ハフ変換を用いて,グレースケール画像から円を検出します. :param image: 8ビット,シングルチャンネル,グレースケールの入力画像. :param circles: 検出された円を出力するベクトル.各ベクトルは,3要素の浮動小数点型ベクトル :math:`(x, y, radius)` としてエンコードされます. :param method: 現在のところ, ``CV_HOUGH_GRADIENT`` メソッドのみが実装されています.基本的には *2段階ハフ変換* で,これについては Yuen90 で述べられています. :param dp: 画像分解能に対する投票分解能の比率の逆数.例えば, ``dp=1`` の場合は,投票空間は入力画像と同じ分解能をもちます.また ``dp=2`` の場合は,投票空間の幅と高さは半分になります. :param minDist: 検出される円の中心同士の最小距離.このパラメータが小さすぎると,正しい円の周辺に別の円が複数誤って検出されることになります.逆に大きすぎると,検出できない円がでてくる可能性があります. :param param1: 手法依存の 1 番目のパラメータ. ``CV_HOUGH_GRADIENT`` の場合は, :func:`Canny` エッジ検出器に渡される2つの閾値の内,大きい方の閾値を表します(小さい閾値は,この値の半分になります). :param param2: 手法依存の 2 番目のパラメータ. ``CV_HOUGH_GRADIENT`` の場合は,円の中心を検出する際の投票数の閾値を表します.これが小さくなるほど,より多くの誤検出が起こる可能性があります.より多くの投票を獲得した円が,最初に出力されます. :param minRadius: 円の半径の最小値. :param maxRadius: 円の半径の最大値. 関数 ``houghCircles`` は,ハフ変換の改良版を用いてグレースケール画像から円を検出します.ここでは,簡単な利用例を示します: .. code-block:: c #include #include #include 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 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; } .. 通常,この関数は円の中心を上手く検出しますが,円の半径については失敗することもある点に注意してください.もし事前知識があれば,半径の範囲( ``minRadius`` と ``maxRadius`` )を指定することで,これの補助ができます.または,出力された半径は無視して中心だけを利用し,別の追加処理によって正しい半径を求めることもできます. 参考: :func:`fitEllipse` , :func:`minEnclosingCircle` .. index:: HoughLines cv::HoughLines -------------- `id=0.936094876539 Comments from the Wiki `__ .. cfunction:: void HoughLines( Mat\& image, vector\& lines, double rho, double theta, int threshold, double srn=0, double stn=0 ) 標準ハフ変換を用いて,2値画像から直線を検出します. :param image: 8ビット,シングルチャンネルの2値入力画像.この画像は関数により書き換えられる可能性があります. :param lines: 検出された直線が出力されるベクトル.各直線は,2要素のベクトル :math:`(\rho, \theta)` で表現されます. :math:`\rho` は原点(画像の左上コーナー)からの距離, :math:`\theta` はラジアン単位で表される直線の回転角度(0 :math:`\sim` 垂直線, :math:`\pi/2 \sim` 水平線)です. :param rho: ピクセル単位で表される投票空間の距離分解能. :param theta: ラジアン単位で表される投票空間の角度分解能. :param threshold: 投票の閾値パラメータ.十分な票( :math:`>\texttt{threshold}` )を得た直線のみが出力されます. :param srn: マルチスケールハフ変換において,距離分解能 ``rho`` の除数となる値.投票空間の粗い距離分解能は ``rho`` となり,細かい分解能は ``rho/srn`` となります.もし ``srn=0`` かつ ``stn=0`` の場合は,古典的ハフ変換が利用されます.そうでない場合は,両方のパラメータが正値である必要があります. :param stn: マルチスケールハフ変換において,角度分解能 ``theta`` の除数となる値. 関数 ``HoughLines`` は,直線検出のためのハフ変換,またはマルチスケールハフ変換の実装です.コードの例については, :func:`HoughLinesP` を参照してください. .. index:: HoughLinesP cv::HoughLinesP --------------- `id=0.507264051577 Comments from the Wiki `__ .. cfunction:: void HoughLinesP( Mat\& image, vector\& lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 ) 確率的ハフ変換を利用して,2値画像から線分を検出します. :param image: 8ビット,シングルチャンネルの2値入力画像.この画像は関数により書き換えられる可能性があります. :param lines: 検出された線分が出力されるベクトル.各線分は,4要素のベクトル :math:`(x_1, y_1, x_2, y_2)` で表現されます.ここで :math:`(x_1,y_1)` および :math:`(x_2, y_2)` は,検出された各線分の端点です. :param rho: ピクセル単位で表される投票空間の距離分解能. :param theta: ラジアン単位で表される投票空間の角度分解能. :param threshold: 投票の閾値パラメータ.十分な票( :math:`>\texttt{threshold}` )を得た直線のみが出力されます. :param minLineLength: 最小の線分長.これより短い線分は棄却されます. :param maxLineGap: 2点が同一線分上にあると見なす場合に許容される最大距離. 関数 ``HoughLinesP`` は, Matas00 で述べられている,直線検出のための確率的ハフ変換アルゴリズムの実装です.以下に直線検出の例を示します: .. code-block:: c /* これは,単独で動作するプログラムです.プログラムの最初の引数として画像ファイル名を渡します. "#if 1" を "#if 0" に変更したり戻したりすることで, 標準的ハフ変換と確率的ハフ変換を切り替えることができます. */ #include #include #include 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 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 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; } .. サンプル画像.上記のプログラムはこの画像用にパラメータを調整しています: .. image:: ../../pics/building.jpg 上記のプログラムにおいて確率的ハフ変換を行った結果: .. image:: ../../pics/houghp.png .. index:: preCornerDetect cv::preCornerDetect ------------------- `id=0.447531725122 Comments from the Wiki `__ .. cfunction:: void preCornerDetect( const Mat\& src, Mat\& dst, int apertureSize, int borderType=BORDER_DEFAULT ) コーナー検出のための特徴マップを求めます. :param src: 8ビットまたは浮動小数点型,シングルチャンネルの入力画像. :param dst: タイプが ``CV_32F`` で ``src`` と同じサイズの出力画像. :param apertureSize: :func:`Sobel` のアパーチャサイズ. :param borderType: ピクセル外挿手法. :func:`borderInterpolate` を参照してください. 関数 ``preCornerDetect`` は,入力画像の,複合偏微分に基づいた写像を求めます. .. math:: \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} ここで :math:`D_x` , :math:`D_y` は画像の1次微分, :math:`D_{xx}` , :math:`D_{yy}` は画像の2次微分, :math:`D_{xy}` は混合微分です. 次に示すように,コーナーは,この写像の極大値として得られます: .. code-block:: c Mat corners, dilated_corners; preCornerDetect(image, corners, 3); // 3x3 の矩形構造要素で膨張させます. dilate(corners, dilated_corners, Mat(), 1); Mat corner_mask = corners == dilated_corners; ..