質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

2188閲覧

ビルド正常終了した。デバッグできません

jiaxiaoyue

総合スコア12

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2016/06/03 06:43

編集2016/06/03 08:44

###前提・実現したいこと
pmb画像を読んで、人が閾値を決め、ソーベルでエッジ検出します。
(例)visual studio 2008でopencvのc++を作っています。
実装中に以下のエラーメッセージが発生しました。

###発生している問題・エラーメッセージ
デバッグするとエラーメッセージがなく、画像のウィンドウが出ましたが、処理できずに止まりました。

###該当のソースコード
// kadai6-2.2.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

IplImage *img;//, *img_out;,img
int width,height;
int edge_thresh_sobel = 0; // 閾値の初期値

IplImage *gray_sobel, *edge_sobel, *edgeX, *edgeY;

int sobel(int t) {
int i, j, dx, dy, W, H;
double mag;

W = img->width; H = img->height; for(i=0;i<(W*H);i++) { j = i * 2; dx = (int)edgeX->imageData[j]; dy = (int)edgeY->imageData[j]; mag = (double)(dx*dx + dy*dy); mag = sqrt(mag); if(mag >= (double)t) edge_sobel->imageData[i] = (unsigned char)255; else edge_sobel->imageData[i] = 0; return t; }

}

int _tmain(int argc, _TCHAR* argv[])
{
img = 0; // 画像ファイル読み込み
img = cvLoadImage( "airplane-gray.bmp");

// 画像表示窓の準備 cvNamedWindow("入力画像", 1); // 画像表示 cvShowImage("入力画像", img); //平滑化処理 cvSmooth(img,img,CV_GAUSSIAN,3); // 画像表示窓の準備 cvNamedWindow("平滑化", 1); // 画像表示 cvShowImage("平滑化", img); // エッジ点画像用データを作成 edge_sobel = cvCreateImage( cvSize(img->width,img->height), IPL_DEPTH_8U, 1 ); // X方向,Y方向のエッジ強度を保存するバッファを確保する. // バッファのDEPTHはsigned short(IPL_DEPTH_16S)を指定する. // (画素値が[0,255]の濃淡画像から3x3のマスクでエッジを検出すると // エッジ強度は[-4*255,4*255]の値をとるため) edgeX = cvCreateImage( cvSize(img->width,img->height), IPL_DEPTH_16S, 1 ); edgeY = cvCreateImage( cvSize(img->width,img->height), IPL_DEPTH_16S, 1 ); printf("閾値を入れてください:"); scanf("%d",edge_thresh_sobel); // エッジ強度処理 sobel(edge_thresh_sobel); //画像表示窓の準備 cvNamedWindow("sobel", 1); // 結果を表示 cvShowImage("sobel",edge_sobel); // 終了処理 cvWaitKey(0); cvReleaseImage(&gray_sobel); cvReleaseImage(&edgeX); cvReleaseImage(&edgeY); cvReleaseImage(&edge_sobel); cvDestroyWindow("入力画像"); cvDestroyWindow("平滑化"); cvDestroyWindow("sobel"); return 0;

}

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報
イメージ説明

/---------------------------------------------------------------------------------------/

// kadai6-2.2.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

IplImage *img;//, *img_out;,img
int width,height;
//int edge_thresh_sobel = 0; // 閾値の初期値

IplImage *gray_sobel, *edge_sobel, *edgeX, *edgeY;

int sobel(int t) {
int i, j, dx, dy, W, H;
double mag;
//t=edge_thresh_sobel;
W = img->width; H = img->height;
for(i=0;i<(WH);i++) {
j = i * 2;
dx = (int)edgeX->imageData[j];
dy = (int)edgeY->imageData[j];
mag = (double)(dx
dx + dy*dy);
mag = sqrt(mag);

if(mag >= (double)t) edge_sobel->imageData[i] = (unsigned char)255; else edge_sobel->imageData[i] = 0; return t; }

}

int _tmain(int argc, _TCHAR* argv[])
{
img = 0; // 画像ファイル読み込み
img = cvLoadImage( "airplane-gray.bmp");

// 画像表示窓の準備 cvNamedWindow("入力画像", 1); // 画像表示 cvShowImage("入力画像", img);

printf("1");

//平滑化処理 cvSmooth(img,img,CV_GAUSSIAN,3); // 画像表示窓の準備 cvNamedWindow("平滑化", 1); // 画像表示 cvShowImage("平滑化", img); printf("2"); // エッジ点画像用データを作成 edge_sobel = cvCreateImage( cvSize(img->width,img->height), IPL_DEPTH_8U, 1 ); // X方向,Y方向のエッジ強度を保存するバッファを確保する. // バッファのDEPTHはsigned short(IPL_DEPTH_16S)を指定する. // (画素値が[0,255]の濃淡画像から3x3のマスクでエッジを検出すると // エッジ強度は[-4*255,4*255]の値をとるため) printf("3"); edgeX = cvCreateImage( cvSize(img->width,img->height), IPL_DEPTH_16S, 1 ); edgeY = cvCreateImage( cvSize(img->width,img->height), IPL_DEPTH_16S, 1 );

printf("4");

sobel(200); //呼び出し
//画像表示窓の準備
cvNamedWindow("sobel", 1);
printf("7");
// 結果を表示
cvShowImage("sobel",edge_sobel);

printf("8");

// 終了処理 cvWaitKey(0); cvReleaseImage(&gray_sobel); cvReleaseImage(&edgeX); cvReleaseImage(&edgeY); cvReleaseImage(&edge_sobel); cvDestroyWindow("入力画像"); cvDestroyWindow("平滑化"); cvDestroyWindow("sobel"); printf("9"); return 0;

}

/-----------------------------------------------------------------------------------/
またこういうように単純に閾値を代入すると、ソーベルオペレータが使えない。。。
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

私もChironian様と同意見で、Sobelはまともに動いていないと思います。
理由は2点あります。

C

1printf("閾値を入れてください:"); 2scanf("%d",edge_thresh_sobel); 3scanf("%d",&edge_thresh_sobel); 4「&」が無いので、ここでソフトが落ちてませんか?

もう1点目は既に上述されていますが

C

1for(i=0;i<(W*H);i++) { 2 j = i * 2; 3 dx = (int)edgeX->imageData[j]; 4 dy = (int)edgeY->imageData[j]; 5 mag = (double)(dx*dx + dy*dy); 6 mag = sqrt(mag); 7 8 if(mag >= (double)t) edge_sobel->imageData[i] = (unsigned char)255; 9 else edge_sobel->imageData[i] = 0; 10 return t; 11} 12 13returnはfor文の外では無いでしょうか? 14このままですと直ぐにループが終わりませんか?

投稿2016/06/03 08:50

eleanor2352011

総合スコア44

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

いろいろツッコミどころはありますが、絞ります。
1.BMP画像は1ライン毎に4の倍数となってるはずですが、そこは考慮されてますか?
2.そもそもですが、SOBELオペレータって差分ですよね。自乗平均とっても意味がないように思えます。
3.画像深度が16ビットとされてるので、255でフィルタすると真っ黒に近い画像が表示されるはずです。
流れとしては、多分SOBELオペレータだけ作れという事だと思うので、まずは、sobel(edge_thresh_sobel); これをリマークして普通に画像が表示されるか確認されてはどうでしょうか。

投稿2016/06/03 07:15

pochi0701

総合スコア210

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

sobel(int t)関数がi=0の最初のループで単純にreturn t;しているようです。
でも、入力画像が表示されないのは、これが原因ではないですね。

airplane-gray.bmpは、ビルドしたプログラムのexeファイルと同じフォルダにおいてますか?
恐らく、これを読み出せてないです。
例えば、C:\airplane-gray.bmpへコピーしておき、img = cvLoadImage( "C:\\airplane-gray.bmp");としてみたらどうなりますか?(\\に注意下さい。""の中では\\と書いて初めて\へ展開されます。)

投稿2016/06/03 06:55

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jiaxiaoyue

2016/06/03 07:03

回答ありがとうございます。画像ファイルは正しいところに置いていましたと思っています。なぜなら、printf("閾値を入れてください:"); 前のプログラムが通常に動いています。ソーベルを呼び出しを/**/で隠したら、入力画像と平滑化画像が出ることができます。入力した値の代入が問題になったと思っています。つまりソーベル関数がどこかいけないではないかと思っています。今必死探す中(すみません、文法的な間違いがあったら許してくださいT^T)
Chironian

2016/06/03 07:23

> ソーベルを呼び出しを/**/で隠したら、入力画像と平滑化画像が出る 質問の画像と矛盾しているように見えます。 質問の画像は、「閾値を入れて下さい」に対してまだ閾値を入力していないように見えます。ですので、この時点でsobel()は呼ばれていない筈です。従って、sobel()関数呼び出しをコメントアウトするかどうか関係無い筈なのです。 Visual Studio上で実行する場合と、exeを直接叩く場合でカレント・フォルダが異なりますので、仮に前者で画像が読めても後者では読めないです。(逆も真です。) exeの起動の仕方は統一されてますか? 後、sobel()関数について、回答の冒頭で指摘させて頂いた不具合があると思います。
Chironian

2016/06/03 09:28

質問文を修正されたようですね。 soble()関数に多数の不具合があります。 ①edgeX, edgeYは恐らく、縦方向と横方向の微分値を入れていることが期待されている雰囲気が漂っていますが、単純にcvCreateImage()しているだけで微分しているコードが存在しません。 従って、dx, dyの値は常に0となります。 ②最初に指摘したようにreturn t;の位置がまずいままです。 ③一般的なソーベル・フィルタのアルゴリズムとは異なる実装になっているようです。 http://www.mvision.co.jp/WebHelpIM/_RESOURCE/Filter_Mvc_Sobel.html dx, dyを適切に計算していれば、期待しているものに近い結果はでそうですが。 後、元のプログラムのscanf()は、eleanor2352011さんも指摘されているように、&がないので期待通りに動作しないと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問