Skip to content

Instantly share code, notes, and snippets.

@peccu
Created August 5, 2010 09:24
Show Gist options
  • Select an option

  • Save peccu/509475 to your computer and use it in GitHub Desktop.

Select an option

Save peccu/509475 to your computer and use it in GitHub Desktop.
// #include "cv.h"
// #include "highgui.h"
#include <cv.h>
#include <highgui.h>
#include <math.h>
// デバッグ出力
//#define DEBUG 1
// 縮小後の画像を表示するかどうか
// #define DOUBLE 1
int canny1 = 100,canny2 = 200;
int inc = 10;
/* 2次元の点を上から下,左から右へソートする */
static int cmp_func( const void* _a, const void* _b, void* userdata ){
CvPoint* a = (CvPoint*)_a;
CvPoint* b = (CvPoint*)_b;
int y_diff = a->y - b->y; // aの方が下で正
int x_diff = a->x - b->x; // aの方が右で正
return y_diff ? x_diff : y_diff; // 左右の位置が同じなら上下の差を返す
}
// キーボード入力コールバック
void keyboardFunc(unsigned char key){
//fprintf(stderr,"key = %c\n", key);
switch (key) {
case 'q':
case 'Q':
case '\033': // '\033' は ESC の ASCII コード
exit(0);
break;
case 0: // ↑
canny1+= inc;
fprintf(stderr,"key = ↑\n");
fprintf(stdout,"canny1(%d)++canny2(%d)\n",canny1,canny2);
break;
case 1: // ↓
canny1-= inc;
fprintf(stderr,"key = ↓\n");
fprintf(stdout,"canny1(%d)--canny2(%d)\n",canny1,canny2);
break;
case 2: // ←
canny2+= inc;
fprintf(stderr,"key = ←\n");
fprintf(stdout,"canny1(%d) canny2(%d)++\n",canny1,canny2);
break;
case 3: // →
canny2-= inc;
fprintf(stderr,"key = →\n");
fprintf(stdout,"canny1(%d) canny2(%d)--\n",canny1,canny2);
break;
default:
break;
}
}
int main(int argc, char** argv){
// カメラからのキャプチャ->frame
CvCapture* capture = 0;
IplImage* frame; // OpenCVからのキャプチャ画像
int capture_width, capture_height;
int window_width = 640,window_height = 480; // 縮小後のサイズ
int window_x = 100,window_y = 100; // ウィンドウの位置
// capture = cvCaptureFromCAM(0); // 内蔵カメラ
capture = cvCaptureFromCAM(1); // USBカメラ.なければ内蔵カメラ
if (capture){
// キャプチャ
frame = cvQueryFrame(capture);
// // 画像をファイルからグレースケールで読み込む
// img = cvLoadImage(imgfile, CV_LOAD_IMAGE_GRAYSCALE);
// カメラのキャプチャ領域サイズを取得
capture_width = (int)( cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH) );
capture_height = (int)( cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT) );
} else {
fprintf(stderr,"Could not initialize capturing...\n");
return -1;
}
// 画像のサイズが大きい時に縮小するための領域作成
printf("w:h = %d:%d\n",capture_width,capture_height);
IplImage* resize;
if((capture_width>window_width)||(capture_height>window_height)){
CvSize smallSize = cvSize(window_width,window_height);
resize = cvCreateImage(smallSize, frame->depth, frame->nChannels);
}else{
resize = frame;
}
// ハフ変換で直線の抽出
IplImage* src = cvCreateImage(cvGetSize(resize), IPL_DEPTH_8U, 1);
if( !src ) return -1;
IplImage* dst; // キャニーによるエッジ画像用の領域
IplImage* color_dst; // 線を入れたカラー画像の領域
CvMemStorage* storage = cvCreateMemStorage(0); // ハフ変換で使うメモリ領域
CvSeq* lines = 0; // ハフ変換で取り出した線のシーケンス
int i; // 線を描画する時の添字
char c; // キー入力を受け取る
//ウインドウ生成
// 画像サイズにウィンドウサイズを合わせ,固定する
#ifdef DOUBLE
cvNamedWindow( "Source", CV_WINDOW_AUTOSIZE );
cvMoveWindow( "Source",0,0);
#endif
cvNamedWindow( "Hough", CV_WINDOW_AUTOSIZE );
cvMoveWindow( "Hough", window_width,0);
fprintf(stdout,"canny1(%d) canny2(%d)\n",canny1,canny2);
// ハフラインのループ
while(1){
// キャプチャ
frame = cvQueryFrame(capture);
// 画像のリサイズ
cvResize(frame, resize);
#ifdef DOUBLE
cvShowImage( "Source", resize );
#endif
// resize->srcでグレースケールに変換
cvCvtColor(resize, src, CV_BGR2GRAY);
//画像領域の確保
// サイズ(高さと幅),色深度(色を何ビットで表現するか),チャネル
// チャネル:グレースケール->1,RGB->3,RGB+αチャネル->4
dst = cvCreateImage( cvGetSize(resize), 8, 1 );
color_dst = cvCreateImage( cvGetSize(resize), 8, 3 );
// エッジ検出(Cannyアルゴリズム)
// 二つの閾値+アパーチャサイズ
// 閾値のうち大きい方を 強エッジ,小さい方を弱エッジ
// 強→エッジ検出しやすさ(小さいと点がいっぱい.大きいと線が少し)
// 弱→つながっているかどうかの判定
// cvCanny( src, dst, canny1, canny2, 3 );
cvCanny( src, dst, 150, 200, 3 );
//エッジ画像をカラー化
cvCvtColor( dst, color_dst, CV_GRAY2BGR );
//ハフ変換で直線検出
// cvHoughLines2(入力画像, 検出された線を保存する領域,
// ハフ変換の種類(確率的ハフ変換),
// 距離解像度(1ピクセル当たりの単位),
// 角度解像度(ラジアン単位),
// しきい値(これよりも大きい時に線となる),
// 最小の線の長さ,
// 同一線上に存在する線分とする二つの最大の間隔, )
lines = cvHoughLines2( dst, storage,
CV_HOUGH_PROBABILISTIC,
1, // 解像度
CV_PI/180, 100, // 角度,閾値
50, 10 ); // 最短長,最大間隔
printf("\x1b[2J"); // 画面クリアするエスケープ文字
printf("\x1b[2Jbefore sort\n");
// ユーザーデータってなんや
cvSeqSort( lines, cmp_func, 0 /* ここではユーザーデータは使用しない */ );
printf("after sort\n");
if(lines->total != 0){
int diff = 256/lines->total;
int r,b,g;
//検出した直線を描く
for( i = 0; i < lines->total; i++ ){
CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
// 255-i*diff
if(line[0].x<window_width/2){
r = i*diff;
g = 0;
b = 0;
printf("left %2d:%4d,%4d,%4d,%4d\n",i,line[0].x,line[0].y,line[1].x,line[1].y);
// ラケットかどうかの判定はどうしようか.平均?
}else{
r = 0;
g = 0;
b = i*diff;
printf(" right %2d:%4d,%4d,%4d,%4d\n",i,line[0].x,line[0].y,line[1].x,line[1].y);
}
// ここでろうでんさんの方に渡せばいいはず
cvLine( color_dst, line[0], line[1], CV_RGB(r,g,b), 3, CV_AA, 0 );
}
}else{
printf("no line\n");
}
// ウィンドウに表示
cvShowImage( "Hough", color_dst );
// 終了キー入力待ち
// c = cvWaitKey(200); // ms秒入力を待つ
c = cvWaitKey(10); // 入力を待つ
if( c >= 0 ){
//fprintf(stderr,"key = %d, %c, \n", c, c);
if ((c == 'q')||(c == 'Q')||(c == '\033')){
break;
}
keyboardFunc(c);
}
#ifdef DEBUG
break;
#endif
}
#ifdef DEBUG
// 0 = 無限秒キー入力を待つ
cvWaitKey(0);
#endif
// メモリ開放(と思う)
cvReleaseImage(&frame);
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvReleaseImage(&color_dst);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment