Cannyアルゴリズムを用いて,画像のエッジを検出します.
| パラメタ: | 
 | 
|---|
関数 Canny は,Cannyアルゴリズムを用いて入力画像 image 中のエッジを検出し,マップ edges に出力します. threshold1 と threshold2 の内,小さい方の値がエッジの接続に利用され,大きい方の値が明確なエッジの初期セグメントを検出するのに利用されます.詳しくは, http://en.wikipedia.org/wiki/Canny_edge_detector を参照してください.
コーナーを検出するために,画像ブロックの固有値と固有ベクトルを求めます.
| パラメタ: | 
 | 
|---|
関数
cornerEigenValsAndVecs
は,各ピクセル
 に対して,
blockSize
に対して,
blockSize
 blockSize
サイズの近傍領域
blockSize
サイズの近傍領域
 を考えます.そして,この近傍領域の微分画像の共変動行列を次のように求めます:
を考えます.そして,この近傍領域の微分画像の共変動行列を次のように求めます:

ここで,微分画像は Sobel() オペレータを利用して求められます.
その後,行列
 の固有値と固有ベクトルを求め,それを出力画像に
の固有値と固有ベクトルを求め,それを出力画像に
 という形式で格納します.ここで,
という形式で格納します.ここで,
 where
where
 ]
]
 の固有値.格納されません.
の固有値.格納されません. ]
]
 に対する固有ベクトル.
に対する固有ベクトル. ]
]
 に対する固有ベクトル.
に対する固有ベクトル.となります.
この関数の出力は,ロバストなエッジ検出やコーナー検出に利用できます.
参考: cornerMinEigenVal() , cornerHarris() , preCornerDetect()
Harris エッジ検出器.
| パラメタ: | 
 | 
|---|
関数
cornerHarris
は,画像に対して Harris エッジ検出器を適用します.
cornerMinEigenVal()
や
cornerEigenValsAndVecs()
と同様に,
 サイズの近傍領域全体に渡って勾配の積和を計算することで,ピクセル
サイズの近傍領域全体に渡って勾配の積和を計算することで,ピクセル
 における
における
 の勾配の共変動行列
の勾配の共変動行列
 を求めます.そして,そこから次の特徴量を計算します:
を求めます.そして,そこから次の特徴量を計算します:

画像中のコーナーは,この応答マップの極大点として検出されます.
コーナーを検出するために,勾配行列の最小の固有値を求めます.
| パラメタ: | 
 | 
|---|
関数
cornerMinEigenVal
は,
cornerEigenValsAndVecs()
と似ていますが,微分画像の共変動行列の最小固有値だけを求めます.つまり,
cornerEigenValsAndVecs()
の説明にある式の
 だけを求めます.
だけを求めます.
コーナー位置を高精度化します.
| パラメタ: | 
 | 
|---|
関数 cornerSubPix は,以下の図に示されるような,サブピクセル精度のコーナー,あるいは鞍点を検出するために繰り返し処理を行います.
 
サブピクセル精度のコーナー位置決めは,近傍領域の中心
 から,その領域内に位置する点
から,その領域内に位置する点
 に向かう各ベクトルが,
に向かう各ベクトルが,
 における(画像自身と観測ノイズに従う)画像勾配と直交する,という考えに基づいています.これは,以下の式で表現されます:
における(画像自身と観測ノイズに従う)画像勾配と直交する,という考えに基づいています.これは,以下の式で表現されます:

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

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

このアルゴリズムは,探索窓の中心をこの新しい値
 に再設定し,値の変化量が与えられた閾値内に収まるようになるまで繰り返し計算を行います.
に再設定し,値の変化量が与えられた閾値内に収まるようになるまで繰り返し計算を行います.
画像内の強いコーナーを検出します.
| パラメタ: | 
 | 
|---|
この関数は, Shi94 で述べられるように,画像中または画像の指定領域内の最も強いコーナーを検出します:
 の近傍領域における極大値のみを残します).
の近傍領域における極大値のみを残します). よりも小さい最小固有値をもつコーナーを棄却します.
よりも小さい最小固有値をもつコーナーを棄却します. (
(
 ) が存在するようなコーナー
) が存在するようなコーナー
 を削除します.
を削除します.この関数は,点ベースの物体追跡器を初期化するために利用できます.
この関数が,パラメータ qualityLevel に異なる値 A と B を与えられて呼び出され,その時に A > {B} であるとします.その場合,出力コーナー配列において qualityLevel=A で求められたコーナーの配列が, qualityLevel=B で求められたものよりも前に位置することに注意してください.
参考: cornerMinEigenVal() , cornerHarris() , calcOpticalFlowPyrLK() , estimateRigidMotion() , PlanarObjectDetector() , OneWayDescriptor()
ハフ変換を用いて,グレースケール画像から円を検出します.
| パラメタ: | 
 | 
|---|
関数 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;
}
通常,この関数は円の中心を上手く検出しますが,円の半径については失敗することもある点に注意してください.もし事前知識があれば,半径の範囲( minRadius と maxRadius )を指定することで,これの補助ができます.または,出力された半径は無視して中心だけを利用し,別の追加処理によって正しい半径を求めることもできます.
参考: fitEllipse() , minEnclosingCircle()
標準ハフ変換を用いて,2値画像から直線を検出します.
| パラメタ: | 
 | 
|---|
関数 HoughLines は,直線検出のためのハフ変換,またはマルチスケールハフ変換の実装です.コードの例については, HoughLinesP() を参照してください.
確率的ハフ変換を利用して,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;
}
サンプル画像.上記のプログラムはこの画像用にパラメータを調整しています:
 
上記のプログラムにおいて確率的ハフ変換を行った結果:
 
コーナー検出のための特徴マップを求めます.
| パラメタ: | 
 | 
|---|
関数 preCornerDetect は,入力画像の,複合偏微分に基づいた写像を求めます.

ここで
 ,
,
 は画像の1次微分,
は画像の1次微分,
 ,
,
 は画像の2次微分,
は画像の2次微分,
 は混合微分です.
は混合微分です.
次に示すように,コーナーは,この写像の極大値として得られます:
Mat corners, dilated_corners;
preCornerDetect(image, corners, 3);
// 3x3 の矩形構造要素で膨張させます.
dilate(corners, dilated_corners, Mat(), 1);
Mat corner_mask = corners == dilated_corners;