//---------------------------------------------------------
// 概要      : ハフ変換
// File Name : houghlines.cpp
// Library   : OpenCV for MS-Windows 1.0
//---------------------------------------------------------

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

//	cvCanny用定数
#define	CANNY_THRESHOLD1	50	//	1番目の閾値 (リファレンス参照)
#define CANNY_THRESHOLD2	80	//	2番目の閾値 (リファレンス参照)
#define	APERTURE_SIZE		3	//	Sobelオペレータのサイズ (リファレンス参照)

//	cvHoughLines2用定数
#define RHO					1						//	パラメータ空間におけるρ軸の分解能(ピクセル単位)
#define THETA				( CV_PI / 180 )			//	パラメータ空間におけるθ軸の分解能(ラジアン単位)
#define HOUGHLINE_METHOD	CV_HOUGH_PROBABILISTIC	//	ハフ変換の手法 (リファレンス参照)
#define HOUGHLINE_THRESHOLD	50						//	直線を抽出する際のパラメータ空間での投票数の閾値
#define HOUGHLINE_PARAM1	50						//	手法に応じた1番目のパラメータ (リファレンス参照)
#define HOUGHLINE_PARAM2	10						//	手法に応じた2番目のパラメータ (リファレンス参照)

//	cvLine用定数
#define LINE_THICKNESS	2	//	線の太さ
#define LINE_TYPE		8	//	線の種類
#define SHIFT			0	//	座標の小数点以下の桁を表すビット数

int main( int argc, char **argv ) {
	char windowNameSource[] = "Source";	//	元画像を表示するウィンドウの名前
	char windowNameHough[] = "Hough";	//	ハフ変換により抽出された直線を表示するウィンドウの名前

	CvMemStorage *storage = cvCreateMemStorage( 0 );//	ハフ変換に必要なメモリ領域
	CvSeq *lines = NULL;							//	ハフ変換により抽出された直線

	//	画像を読み込む
    IplImage *sourceImage = cvLoadImage( "image/source.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR );

	if ( sourceImage == NULL ) {
		//	画像が見つからなかった場合
		printf( "画像が見つかりません\n" );
		return -1;
	}
    
	//	画像を生成する
    IplImage *grayImage = cvCreateImage( cvGetSize( sourceImage ), IPL_DEPTH_8U, 1 );	//	グレースケール画像用IplImage
	IplImage *edgeImage = cvCreateImage( cvGetSize( sourceImage ), IPL_DEPTH_8U, 1 );	//	エッジ抽出した画像用IplImage
    IplImage *houghImage = cvCreateImage( cvGetSize( sourceImage ), IPL_DEPTH_8U, 3 );	//	ハフ変換用IplImage
	
	//	BGRからグレースケールに変換する
    cvCvtColor( sourceImage, grayImage, CV_BGR2GRAY );

	//	エッジ抽出を行う
    cvCanny( grayImage, edgeImage, CANNY_THRESHOLD1, CANNY_THRESHOLD2, APERTURE_SIZE );

	//	グレースケールからBGRに変換する
    cvCvtColor( edgeImage, houghImage, CV_GRAY2BGR );

	//	ハフ変換により直線の抽出を行う
    lines = cvHoughLines2( edgeImage, storage, HOUGHLINE_METHOD, RHO, THETA, HOUGHLINE_THRESHOLD, HOUGHLINE_PARAM1, HOUGHLINE_PARAM2 );

	//	抽出された直線を描く
    for ( int i = 0; i < lines->total; i++ ) {
        CvPoint *line = ( CvPoint* )cvGetSeqElem( lines, i );
        cvLine( houghImage, line[0], line[1], CV_RGB( 255, 0, 0 ), LINE_THICKNESS, LINE_TYPE, SHIFT );
    }

	//	ウィンドウを生成する
    cvNamedWindow( windowNameSource, CV_WINDOW_AUTOSIZE );
	cvNamedWindow( windowNameHough, CV_WINDOW_AUTOSIZE );

	//	画像を表示する
    cvShowImage( windowNameSource, sourceImage );
    cvShowImage( windowNameHough, houghImage );

	//	キー入力を待つ
    cvWaitKey( 0 );

	//	メモリを解放する
	cvReleaseImage( &sourceImage );
	cvReleaseImage( &grayImage );
	cvReleaseImage( &edgeImage );
	cvReleaseImage( &houghImage );
	//	ウィンドウを破棄する
	cvDestroyWindow( windowNameSource );
	cvDestroyWindow( windowNameHough );

    return 0;
}

