OpenGL de プログラミング - エッジ検出
現在地 >> メニュー >> サンプルコード::OpenCV >> エッジ検出


問題


カラー画像を濃淡画像にして、エッジ検出せよ。

その他条件:
 ソーベルフィルタによるエッジ検出を用いる。
 X,Y,それぞれの方向でフィルタをかける。

サンプル画像


 ⇒エッジ検出2(スケール変換の関数を用いる場合)


答え


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

using namespace std;

int main( int argc, char **argv)
{

IplImage *image = cvLoadImage( "test.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
if(image == NULL)
{
cout << "Can't load image."<<endl;
std::exit(0);
}

IplImage *gray = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
if(gray == NULL)
{
cout << "Can't create image."<<endl;
std::exit(0);
}

cvCvtColor(image, gray, CV_BGR2GRAY);

cvReleaseImage( & image );


/** エッジ画像の作業用にメモリ確保 **/
IplImage *edgeX = cvCreateImage( cvGetSize(gray), IPL_DEPTH_16S, 1 );
IplImage *edgeY = cvCreateImage( cvGetSize(gray), IPL_DEPTH_16S, 1 );

/** 結果画像保存用 メモリ確保 **/
IplImage *imgrDX = cvCreateImage( cvGetSize(gray), IPL_DEPTH_8U, 1 );
IplImage *imgrDY = cvCreateImage( cvGetSize(gray), IPL_DEPTH_8U, 1 );

/** ソーベルフィルタによるエッジ検出 **/
cvSobel( gray, edgeX, 1, 0, 3);
cvSobel( gray, edgeY, 0, 1, 3);


/** 出力用に値の範囲を変換(0〜255にスケール変換)**/
for ( int i=0; i < (gray->height)*(gray->width); i++ )
{imgrDX->imageData[i]=(unsigned char)((((short*)edgeX->imageData)[i])/8+128);
imgrDY->imageData[i] = (unsigned char)((((short*)edgeY->imageData)[i])/8+128);
}

cvReleaseImage( &edgeX );
cvReleaseImage( &edgeY );


cvNamedWindow("Gray Image",CV_WINDOW_AUTOSIZE);
cvShowImage("Gray Image",gray);

cvNamedWindow("X edge",CV_WINDOW_AUTOSIZE);
cvShowImage("X edge",imgrDX);

cvNamedWindow("Y edge",CV_WINDOW_AUTOSIZE);
cvShowImage("Y edge",imgrDY);

cvWaitKey(0); // 0秒待つ => ずっと入力待ち

cvReleaseImage( &imgrDX );
cvReleaseImage( &imgrDY );

return 0;
}

メモ


「画素値」が「0〜255」の範囲をとる濃淡画像では、
「濃淡画像」を「3x3のマスク」で「エッジ検出」すると
「エッジ強度」は「-4*255〜4*255」の値をとる。


よって、内部計算用のメモリは、
 IPL_DEPTH_16S
を使用する。

出力時は、「0〜255」にスケール変換して出力している。


※ここは、

「エッジ強度」は「-4*255〜4*255」。
つまり、上下で(4+4)倍=8倍となっている。
故に8で割る。


次に、
128だけ底上げしてucharに入るようにしている