エッジ検出(Sobel,Laplacian,Canny)

18 2月 2010 Under: opencv2.x-samples

C

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

int
main (int argc, char **argv)
{
  IplImage *src_img, *sobel_img, *laplaian_img, *canny_img;
  IplImage *tmp_img;
  char *imagename;

  // (1)load a specified file as a grayscale image
  //    and allocate destination images
  imagename = argc > 1 ? argv[1] : "../image/bike_sign.png";
  src_img = cvLoadImage(imagename, CV_LOAD_IMAGE_GRAYSCALE);
  if(src_img == 0)
    return -1;
  tmp_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_32F, 1);
  sobel_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1);
  laplaian_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1);
  canny_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1);
  
  // (2)calculate the first image derivatives using an Sobel operator
  cvSobel(src_img, tmp_img, 1, 1, 3);
  cvConvertScaleAbs(tmp_img, sobel_img, 1, 0);

  // (3)calculate the Laplacian of an image
  cvLaplace(src_img, tmp_img, 3);
  cvConvertScaleAbs(tmp_img, laplaian_img, 1, 0);
  
  // (4)implement the Canny algorithm for edge detection
  cvCanny(src_img, canny_img, 50.0, 200.0, 3);

  // (5)show original gray and their edge images respectively,
  //    and quit when any key pressed
  cvNamedWindow("Original(GrayScale)", CV_WINDOW_AUTOSIZE);
  cvNamedWindow("Sobel", CV_WINDOW_AUTOSIZE);
  cvNamedWindow("Laplacian", CV_WINDOW_AUTOSIZE);
  cvNamedWindow("Canny", CV_WINDOW_AUTOSIZE);
  cvShowImage("Original(GrayScale)", src_img);
  cvShowImage("Sobel", sobel_img);
  cvShowImage("Laplacian", laplaian_img);
  cvShowImage("Canny", canny_img);
  cvWaitKey(0);
   
  cvDestroyWindow("Original");
  cvDestroyWindow("Sobel");
  cvDestroyWindow("Laplace");
  cvDestroyWindow("Canny");
  cvReleaseImage(&src_img);
  cvReleaseImage(&sobel_img);
  cvReleaseImage(&laplaian_img);
  cvReleaseImage(&canny_img);
  cvReleaseImage(&tmp_img);
  
  return 0;
}

// (1)指定ファイルをグレースケール画像として読み込みます.また,それと同サイズの出力画像領域を確保します.

このサンプルでは,エッジの検出を目的としているので(色情報は不要なので),グレースケール画像として読み込みを行います.また,それと同サイズの出力画像領域,テンポラリ画像領域を確保します.テンポラリ画像領域は,もとの8Uよりも大きいビット深度(ここでは32F,64Fでも可)でなければならないことに注意してください.

// (2)Sobelオペレータを用いて,1次微分画像を求めます.

関数 cvSobel を用いて,1次微分画像を計算します.第3,第4引数共に1を指定して,x-方向,y-方向の微分を求めます.また,オペレータのアパーチャサイズは 3 を指定しています.この計算結果を,グレースケール画像(ビット深度 8U)に変換します.

// (3)画像のラプラシアン(2次微分)を求めます.

関数 cvLaplace を用いて,2時微分画像を計算します.アパーチャサイズは 3 を指定します.この計算結果を,グレースケール画像(ビット深度 8U)に変換します.

// (4)Cannyアルゴリズムを用いて,エッジを検出します.

関数 cvCanny を用いて,エッジを検出します.第3,第4引数はそれぞれ,エッジの初期検出と,そこから続くエッジの接続に用いられる閾値を表します.この2つの引数は,数値の大小でその意味を判断されるので,順序は (50, 200) でも (200, 50) でも等価です.アパーチャサイズは,3を指定します.

// (5)元のグレースケール画像,それぞれのエッジ画像を表示します.

元画像(グレースケール),および3種の処理画像を表示します.また,何かキーが押された場合プログラムを終了します.

C++

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

using namespace cv;

int
main (int argc, char **argv)
{
  // (1)load a specified file as a grayscale image
  const char *imagename = argc > 1 ? argv[1] : "../image/bike_sign.png";
  Mat src_img = imread(imagename, 0);
  if(!src_img.data)
    return -1;

  // (2)calculate the first image derivatives using an Sobel operator
  Mat tmp_img;
  Mat sobel_img;
  Sobel(src_img, tmp_img, CV_32F, 1, 1);
  convertScaleAbs(tmp_img, sobel_img, 1, 0);

  // (3)calculate the Laplacian of an image  
  Mat laplacian_img;
  Laplacian(src_img, tmp_img, CV_32F, 3);
  convertScaleAbs(tmp_img, laplacian_img, 1, 0);
  
  // (4)implement the Canny algorithm for edge detection
  Mat canny_img;
  Canny(src_img, canny_img, 50, 200);

  // (5)show original gray and their edge images respectively, 
  //    and quit when any key pressed
  namedWindow("Original(Grayscale)", CV_WINDOW_AUTOSIZE);
  namedWindow("Sobel", CV_WINDOW_AUTOSIZE);
  namedWindow("Laplacian", CV_WINDOW_AUTOSIZE);
  namedWindow("Canny", CV_WINDOW_AUTOSIZE);
  imshow("Original(Grayscale)", src_img);
  imshow("Sobel", sobel_img);
  imshow("Laplacian", laplacian_img);
  imshow("Canny", canny_img);
  waitKey(0);

  return 0;
}

// (1)指定ファイルをグレースケール画像として読み込みます.

このサンプルでは,エッジの検出を目的としているので(色情報は不要なので),グレースケール画像として読み込みを行います.

// (2)Sobelオペレータを用いて,1次微分画像を求めます.

関数 Sobel を用いて,1次微分画像を計算します.第4,第5引数共に1を指定して,x-方向,y-方向の微分を求めます.また,オペレータのアパーチャは 3 を指定しています.この計算結果を,グレースケール画像(ビット深度 8U)に変換します.

// (3)画像のラプラシアン(2次微分)を求めます.

関数 Laplacian を用いて,2時微分画像を計算します.アパーチャサイズは 3 を指定します.この計算結果を,グレースケール画像(ビット深度 8U)に変換します.

// (4)Cannyアルゴリズムを用いて,エッジを検出します.

関数 Canny を用いて,エッジを検出します.第3,第4引数はそれぞれ,エッジの初期検出と,そこから続くエッジの接続に用いられる閾値を表します.この2つの引数は,数値の大小でその意味を判断されるので,順序は (50, 200) でも (200, 50) でも等価です.アパーチャサイズは指定せず,デフォルト値の3を利用します.

// (5)元のグレースケール画像,それぞれのエッジ画像を表示します.

元画像(グレースケール),および3種の処理画像を表示します.また,何かキーが押された場合プログラムを終了します.

実行結果例

元画像(カラー)

(左から)入力画像(グレースケール),処理結果(Sobel,Laplacian,Canny)