• 締切済み

教えてください!C言語で画像の直線検出

お世話になります。 C言語で画像処理を勉強してます。今直線検出がたいへんです。 例の画像があります(ここはjpgですけど、実際使っているのはppmです):http://www.xiaochuncnjp.com/bbs/attachments/month_0711/20071112_ea2afaf31222783dfbc9datB3cLMcy7H.jpg ご覧の通り傾きの違う3種類の直線があります。それぞれの傾きを検出し、後面の垂直に近い直線は前面の水平に近い直線に遮られる時、後面の直線の画素値を使って、前面の直線の画素を埋めたいです。どうすればいいでしょうか?今全然わかりません。 そのアルゴリズム、教えていただければ幸いです。

みんなの回答

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.2

パターン認識は机上だけでいくら考えてもダメで, 実際に動かしてみながら試行錯誤しないとなかなかうまくいきません. (1)~(5) のプログラムを全部書いてから動かすのではなく, (1),(2),…,(5) を順番に作っては動かしてみて, うまくいけば次に進むようにした方がいいでしょう. たぶん (2) がなかなかうまくいかず,色々試行錯誤することになると思います. ノイズにより本来のエッジにヒゲが生えたり,途切れたりして追跡中に迷う可能性があります. (4) のピーク検出にも少し工夫が必要かも.

remember11
質問者

お礼

noocyteさん、いつもご解答いただきどうもありがとうございます。返事遅れまして申し訳ございません。noocyteさんのおかげさまで、大体目標達成しました。 傾きを調べた後、私はその傾きにあるすべての画素の分散値を計算し、閾値判定の方法(もし一本の直線だったら、分散値は小さいわけ)で、直線を検出し、その後ろの画素値で一番前の直線埋めました。 6日間がんばって、このような結果を得ました。ご覧ください。 もとの画像: http://www.xiaochuncnjp.com/bbs/attachments/month_0711/20071128_ee90d0311393057524d7gQlddHvLwucT.jpg 前の直線を検出した画像: http://www.xiaochuncnjp.com/bbs/attachments/month_0711/20071128_7b95db96813d76499c48xrPHAX4PGhDO.jpg 最後の結果、処理した画像: http://www.xiaochuncnjp.com/bbs/attachments/month_0711/20071128_416abe213e8e01032448l0zO40HnVtvk.jpg 大体できましたけど、処理した画像にはまだ違和感が有ります。綺麗じゃない部分はまだ残ってます。直線判定と画素を埋める手法のアルゴリズムの問題なんですか?まだ考えてます。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.1

とりあえず画像の描き変えはおいといて,線分検出と傾き判定の方法について. (1) エッジ検出フィルタでエッジを検出する. (2) エッジを追跡して線分を検出し,両端点の座標を記憶する. (3) 検出した各線分の傾きを求め,ヒストグラムを作成する. (4) 画像の直線の傾きは2つだけなので,   ヒストグラムに2つの大きなピークが出るはず.   ⇒ それらのピークの位置から2つの傾きの値を求める. (5) (3) で検出した各線分について,どちらの傾きに近いかを判定する. ディジタル信号処理講座 (エッジ検出) http://www.f-kmr.com/dsp_edge.htm 1次微分(差分)によるエッジ検出 http://www.mis.med.akita-u.ac.jp/~kata/image/sobelprew.html Visual C++ 2005 Express Edition を用いた易しい画像処理(13) ――――エッジ検出と画像ファイルの読み書き ―――― http://homepage3.nifty.com/ishidate/vcpp05_g13/vcpp05_g13.htm

remember11
質問者

お礼

noocyteさん、親切なご解答どうもありがとうございます。とりあえず私はnoocyteさんの言ったことに従ってやってみます。そして結果をここで報告します。そのときもよろしくお願いいたします。

関連するQ&A

  • 検出限界(DL)を求める方法

    HPLC初心者です。イソフラボンの分析を行っていますが、色々調べても検出限界の求め方が分かりません。初歩的な質問ですみません。 『ブランク試料又は検出限界付近の分析対象物を含む試料の測定値の標準偏差及び検出限界付近の検量線の傾きから算出される。例えば検出限界は測定値が正規分布し連続な場合には、検出限界付近の検量線の傾き及びブランク試料の測定値の標準偏差から、次式により求めることができる。DL=3.3σ/Slope』 ・ブランク試料というのはイソフラボンのスタンダードのことでしょうか。 ・この検量線はイソフラボンの濃度をいくつか変えて(1ppm,2ppm,3ppm・・・)測定した値で回帰直線を求めたものでしょうか。 宜しくお願い致します。

  • 画像情報処理についてです。(Hough変換です。)

    お忙しいところ申し訳ありません。大学の工学部の学生の者です。 大学の「画像情報処理」の講義で次のような課題が出題されました。 1.「画像内に平行な2直線が存在する。その2直線の中心に位置する直線を検出するアルゴリズムを考案せよ」 2.「画像内に中心の位置を同じくする幾つかの円と、それらの円と中心位置が異なる円が存在する(それらは交わっていない)。この時、中心の位置を同じくする幾つかの円の中心位置のみを検出するアルゴリズムを考案せよ(即ち、同心円でない円の中心は検出しない)。」 Hough変換を用いればいいというのは何となく分かるのですが、具体的なアルゴリズムが分かりません。 教えて頂けると幸いです。

  • 【Photoshop】又はillustratorで分度器機能はありませんか?

    フォトショップ7・イラストレータCS2(Win-XP)使用者です。 画像を編集するときその傾きを補正したいことがあります。撮影した商品画像がわずかに傾いたいたりしたら回転させるわけですが、あらかじめ何度傾ければいいか、水平垂直から対象の直線が傾いているか測定できれば便利だと思います。そんな角度を測る方法はありませんでしょうか? お詳しい方よろしくお願いいたします。

  • openCVの画像処理について

    画像の中にある粒子の位置を検出し、座標の値の取得をどうしてもOpenCVをつかって、出したいと考えております。 プログラミングが実行したら、すべて0と表示されたり、エラーが出たりします。 現在、画像を読み込み、2値化し、2値化した画像の画素数を列ごとに足して、垂直方向の画素数の最大値の検出、2値化した画像の画素数を行ごとに足して、水平方向の画素数の最大値の検出を行っています。 使用した画像を添付させていただきますので、もしアドバイスなどいただけたらよろしくお願い致します。 #include <stdio.h> #include <math.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #define X 640 #define Y 480 IplImage *grayImage; //グレースケール画像用IplImage IplImage *binaryImage; //2値画像用IplImage char windowNameBinarization[] = "Binarization";//2値化した画像を表示するウィンドウの名前 int levels = 115; //トラックバーの値(2値化の際の閾値) static int h[X][Y]; int main( /*int argc, char **argv*/ ){ // 画像を読み込む IplImage *sourceImage = cvLoadImage( "C:/Documents and Settings/Owner/My Documents/My Pictures/Logicool Webcam/Picture 10.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 *binaryImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 ); //2値画像用IplImage // BGRからグレースケールに変換する cvCvtColor( sourceImage, grayImage, CV_BGR2GRAY ); // グレースケールから2値に変換する cvThreshold( grayImage, binaryImage, levels, 255, CV_THRESH_BINARY ); /*グラフ値の取得*/ IplImage *img; img = cvCloneImage (binaryImage); //画像をコピー int bytes_per_pixel = ((img->depth & 255) / 8) * img->nChannels; // (1)画素値を順次取得 int i,j,k,t; int Hy[Y],Hx[X]; //宣言 //垂直方向の画素値 for(k = 0; k <Y /*img->height*/; k++) { Hy[k] = 0;//初期化 } if((unsigned char)img->imageData>levels){ for(j = 0;j < Y/*img->height*/; j++) { for(i = 0; i < X; i++) {Hy[j] += *(img->imageData + (img->widthStep*j) + (i*bytes_per_pixel)); } }} //水平方向の画素値 for(t = 0; t < X/*img->width*/; t++) { Hx[t]=0; //初期化 } if((unsigned char)img->imageData>levels){ for(i = 0;i < X/*img->width*/; i++) { for(j = 0;j < Y; j++) { Hx[i] = Hx[i]+h[i][j]; } }} //Hy[j]の最大値の座標を調べる int MY = Hy[0]; int my = 0; for(int j=0; j< Y-1; j++){ if(Hy[j]<Hy[j+1]){ MY = Hy[j+1]; my = j+1; } } //Hx[i]の最大値の座標を調べる int MX = Hx[0]; int mx = 0; for(int i=0; i< X-1; i++){ if(Hx[i]<Hx[i+1]){ MX = Hx[i+1]; mx = i+1; } } printf("垂直方向の最大値 %d , 垂直方向の最大値になるときのy軸の値 %d \n", MY,my); printf("水平方向の最大値 %d , 水平方向の最大値になるときのx軸の値 %d \n", MX,mx); int cvWaitKey(int delay=10); //どこでとめるかをあらわす cvReleaseImage( &sourceImage ); cvReleaseImage( &grayImage ); cvReleaseImage( &binaryImage ); cvDestroyWindow( windowNameBinarization); return 0 ; }

  • インスタンスからはみ出ている部分を非表示にしたい

    自分のわかる範囲で色々ためしてみましたが、上手くいかなかったので質問させていただきます。 文章では上手く説明できないと思いますので、試しで作ったFLASHと画像も一緒に見ていただければわかりやすいと思います。 http://azu.moo.jp/t1.swf http://azu.moo.jp/t1.jpg 今「Tシャツに自分の好きなパーツをくっつけることができるFLASH」を作ろうとしています。 そこで、Tシャツにパーツを乗せた時、Tシャツからはみ出ている部分のパーツを表示されないようにしたいのですが、なかなか上手く出来ないので、方法を教えてくださると嬉しいです。 (↑のFLASHですと、ハートのパーツが赤いTシャツと重なっている部分のみ見えるようにしたい) また、Tシャツ前面の脇や肩からはみ出たパーツの部分を、Tシャツの後面に表示させる方法を知りたいです。 Tシャツの画像は前後のみで、配置は縦にしようと思っています。 (こちらは画像を見ていただければ意味がわかりやすいかと思います。) 質問は以上になります。 ちょっとわかりにくい文章かもしれませんが、回答よろしくおねがいします。

    • ベストアンサー
    • Flash
  • 大学レベルの物理の問題です。

    よろしくお願いいたします。 われわれは、重い荷物を持つとき、身体が荷物と一緒に倒れないようにするために、無意識にある 動作をする。その動作によって、倒れることを防ぐことができる。 それはどんな動作か。また、その動作の物理的根拠を述べよ。 ただし、簡単にするために、図においてからだと荷物の重さは等しく 体の重心G1 と荷物の重心G2は同じ高さにあり、全体の重心Gは G1とG2の中間にあるものをする。 http://www.okn.jp/~ackey/cgi-bin/gazou_bbs/imge2/608.jpg 画像は鮮明ではなくて申し訳ございません。 印っぽいものがついています。それが 左から順に G1 G G2の順番です。 動作 物理的根拠 2.背筋をまっすぐに垂直にのばしていすに深く下肢を垂直にして腰掛けている。 このままの姿勢(背筋を垂直に、下肢も垂直のまま)で立ち上がることができるか。 立ち上がるとき、我々は無意識にどんな動作をするか。また、その動作の物理的根拠をのべよ 動作 物理的根拠 お願いします。

  • 買って1年でHDDから不良セクタが

    色々と不具合があるようなので、HDDをチェックした所不良セクタが検出されました。(SATA接続 80G) 3度程検査しましたが、結果は同じでした。 画像↓ http://image40.bannch.com/bbs/86925/img/0109471030.jpg 不良セクタのあるHDDをリカバリもしくはフォーマットしても破損した部分は治ることはありえませんよね?(修復もできるようですが…) 先日、質問した内容もご覧いただければ幸いです。 http://oshiete1.goo.ne.jp/qa4339816.html 説明不足でしたらご指摘ください。お願いします。

  • OPEN

    画像の中にある粒子の位置を検出し、座標の値の取得をどうしてもOpenCVをつかって、出したいと考えております。 プログラミングが実行したら、すべて0と表示されたり、エラーが出たりします。 現在、画像を読み込み、2値化し、2値化した画像の画素数を列ごとに足して、垂直方向の画素数の最大値の検出、2値化した画像の画素数を行ごとに足して、水平方向の画素数の最大値の検出を行っています。 使用した画像を添付させていただきますので、もしアドバイスなどいただけたらよろしくお願い致します。 #include <stdio.h> #include <math.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #define X 640 #define Y 480 IplImage *grayImage; //グレースケール画像用IplImage IplImage *binaryImage; //2値画像用IplImage char windowNameBinarization[] = "Binarization";//2値化した画像を表示するウィンドウの名前 int levels = 115; //トラックバーの値(2値化の際の閾値) static int h[X][Y]; int main( /*int argc, char **argv*/ ){ // 画像を読み込む IplImage *sourceImage = cvLoadImage( "C:/Documents and Settings/Owner/My Documents/My Pictures/Logicool Webcam/Picture 10.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 *binaryImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 ); //2値画像用IplImage // BGRからグレースケールに変換する cvCvtColor( sourceImage, grayImage, CV_BGR2GRAY ); // グレースケールから2値に変換する cvThreshold( grayImage, binaryImage, levels, 255, CV_THRESH_BINARY ); /*グラフ値の取得*/ IplImage *img; img = cvCloneImage (binaryImage); //画像をコピー int bytes_per_pixel = ((img->depth & 255) / 8) * img->nChannels; // (1)画素値を順次取得 int i,j,k,t; int Hy[Y],Hx[X]; //宣言 //垂直方向の画素値 for(k = 0; k <Y /*img->height*/; k++) { Hy[k] = 0;//初期化 } if((unsigned char)img->imageData>levels){ for(j = 0;j < Y/*img->height*/; j++) { for(i = 0; i < X; i++) {Hy[j] += *(img->imageData + (img->widthStep*j) + (i*bytes_per_pixel)); } }} //水平方向の画素値 for(t = 0; t < X/*img->width*/; t++) { Hx[t]=0; //初期化 } if((unsigned char)img->imageData>levels){ for(i = 0;i < X/*img->width*/; i++) { for(j = 0;j < Y; j++) { Hx[i] = Hx[i]+h[i][j]; } }} //Hy[j]の最大値の座標を調べる int MY = Hy[0]; int my = 0; for(int j=0; j< Y-1; j++){ if(Hy[j]<Hy[j+1]){ MY = Hy[j+1]; my = j+1; } } //Hx[i]の最大値の座標を調べる int MX = Hx[0]; int mx = 0; for(int i=0; i< X-1; i++){ if(Hx[i]<Hx[i+1]){ MX = Hx[i+1]; mx = i+1; } } printf("垂直方向の最大値 %d , 垂直方向の最大値になるときのy軸の値 %d \n", MY,my); printf("水平方向の最大値 %d , 水平方向の最大値になるときのx軸の値 %d \n", MX,mx); int cvWaitKey(int delay=10); //どこでとめるかをあらわす cvReleaseImage( &sourceImage ); cvReleaseImage( &grayImage ); cvReleaseImage( &binaryImage ); cvDestroyWindow( windowNameBinarization); return 0 ; }

  • C言語において2バイト文字を検出するには?

    こんにちは。 C言語において、char型ポインタが指している文字が、2バイト文字の1バイト目かどうかを確認する事ができれば、文字列から2バイト文字を検出できると思うのですが、やり方が分かりません。 検索してみても、ややこしい事ばかり書かれていて、すっきりとした答えが見つかりませんでした。 何かいい方法を知っておられる方がいらっしゃれば、是非アドバイスを頂きたいと思います。 では、よろしくお願い致します。

  • C言語 C++ においての画像参照が分からなくて困っています。

    C言語やC++で画像を表示するプログラムを 検索エンジン等で調べているのですが、 コンパイルした後で、画像を差し替える事が出来るようにするには、 どうすればいいのか分かりません。 C言語大全500の極意という本は持っているので試しましたが、 ここに書かれてあるのは一度ヘッダーに取り込んでから表示するもので、後から差し替える事が出来ませんでした。