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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

1回答

6216閲覧

sobel(ソーベル)フィルタを実装したいのですがうまくできません.

RYUi

総合スコア10

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2017/12/08 12:52

###前提・実現したいこと
微分フィルタの1つであるsobelフィルタを用いてPGM形式の濃淡画像をエッジ画像に出力したい.
###発生している問題・エラーメッセージ
画像が真っ暗になる.

###該当のソースコード

C

1 2void EdgeDetection(void){ 3 4 int iWidth = 0, iHeight = 0, iMaxValue = 0; // 画像の幅,高さ,解像度 5 int *piOutputData = NULL; // 画像処理したデータを格納 6 7 8 9 int i,j,k,l = 0; 10 int sobel_x[9]={-1,0,1, 11 -2,0,2, 12 -1,0,1}; 13 int sobel_y[9]={-1,-2,-1, 14 0, 0, 0, 15 1,2,1}; 16 double sum_x,sum_y; 17 double sum; 18 int max; 19 float para; 20//ファイル入力 21 piOutputData=ReadPgm(&iWidth,&iHeight,&iMaxValue); 22 //微分フィルタ 23 for(i=1;i<iHeight-1;i++){ 24 for(j=1;j<iWidth-1;j++){ 25 26 sum_x=0; 27 sum_y=0; 28 sum=0; 29 for(k=0;k<3;k++){ 30 for(l=0;l<3;l++){ 31 sum_x+=sobel_x[3*k+l]*piOutputData[(i+k-1)*iWidth+(j+l-1)]; 32 sum_y+=sobel_y[3*k+l]*piOutputData[(i+k-1)*iWidth+(j+l-1)]; 33 } 34 } 35 36 sum=sqrt(pow(sum_x,2.0)+pow(sum_y,2.0)); 37 // printf("%f\n",sum); 38 piOutputData[i*iWidth+j]=sum; 39 } 40 } 41 42 //最大輝度値を走査 43 max=piOutputData[0]; 44 for(i=1;i<iWidth*iHeight;i++){ 45 if(max<piOutputData[i]) 46 max=piOutputData[i]; 47 } 48 49 //スケール変換のパラメータ 50 para=255/max; 51 52 //スケール変換 53 for(j=0;j<iHeight*iWidth;j++){ 54 piOutputData[j]=para*piOutputData[j]; 55 } 56 57 //ファイルへ出力 58 WritePgm(piOutputData,iWidth,iHeight,iMaxValue); 59//ファイル領域解放 60 FreePgm(piOutputData); 61 62}

###試したこと
3,4つ目のfor文のpiOutputDataの添え字の計算方法を変更した.

###補足情報(言語/FW/ツール等のバージョンなど)
C言語により実装する.

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

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

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

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

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

guest

回答1

0

最初にpiOutputDataに入力される値の範囲がよくわかりませんが、とりあえず

para=255/max;

は、maxが256以上だとparaが0になるでしょうね。右辺は整数同士の計算なので、結果も整数になる。

para=255.0/max;

para=(float)255/max;

ではどうでしょうか。

また、4辺はsumを求めるループに含まれていないけどmaxを求めるループに含まれているのも気になります。

あと、オールゼロの画像が入力された場合、maxが0になってゼロ除算が発生したりしませんか?

投稿2017/12/08 14:47

okrt

総合スコア366

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

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

RYUi

2017/12/08 14:53

回答ありがとうございます. piOutputDataに入っているのは輝度値です.あと,オールゼロの画像は考えないことになっています.
okrt

2017/12/08 15:11

今のところ可能性として考えられるのは ・paraを求める式が整数演算になっているので、結果が小さい値(もしかすると0)になっている または ・sumの計算結果よりも4辺のpiOutputDataの最大値のほうが大きいので、結果が小さい値(もしかすると0)になっている あるいは両方、です。 まずは ・paraを求める計算式を変更する それでダメなら ・maxを求めるループも、sumを求めるループと同様に4辺を除外する ですかね。 4辺の値の出力結果は別途考えるということで。
RYUi

2017/12/08 15:42

maxとparaをdouble型に変更しpara=(double)(255/max)にしてmaxを求めるループを変更しても全画面黒色は解消されましたがエッジ画像になっていません.
okrt

2017/12/08 16:50

ああ、重要な事に気が付いてませんでした。 //微分フィルタ のループの中で、piOutputData[]にsumの計算結果を入れてますが、次のiやjのループではsumを入れたpiOutputData[]をファイルから入力したデータであるかのように扱ってますね。 画素A,B,C,Dの「微分フィルタで処理した結果」と、画素E,F,G,H,Iの「入力データ」から、画素Eの「微分フィルタで処理した結果」を求めてしまっています。 入力データの領域はpiInputData 出力データの領域はpiOutputData のように別々にして、 piInputData=ReadPgm(&iWidth,&iHeight,&iMaxValue); (途中省略) WritePgm(piOutputData,iWidth,iHeight,iMaxValue); という感じで扱うことができれば、わかりやすいですね。 あと、iMaxValueの値を触ってませんが、その値が適切かどうかは不明です。
RYUi

2017/12/09 00:44

ご指摘ありがとうございます. 新しく変数piInputDataを入れて微分フィルタの処理はInputにさせて,sumをOutputに代入し,WritePgm(piOutputdata,...)と書き,max値,para値は2146163338.000000と0.000000という表示になりました.
iwanote

2017/12/09 02:51

para=(double)255/maxではないですか?
okrt

2017/12/09 05:20

para=(double)(255/max) では、(double)を付ける意味が無いでしょうね。 ただし、maxもparaもdouble型に変更したのであれば、double型で演算されるので結果には問題無いはずです。 paraが0.000000という表示になったということですが、printfで単に%fを使うと、小さすぎる値は0.000000のようになってしまいます。 ・%eを使う ・%.10fのようにする ・paraそのままではなく、(para*1000000000)のように加工した値をprintfに渡す などの方法を使うと、ゼロではないことが確認できると思います。 さて、本題です。 私にはReadPgmやWritePgmの仕様も入力データの詳細もわからないし、現状の出力結果がどうなっているかもわからないので確実なことは何も言えませんが、仮に1つの入力値の最大値が255だとすると、maxが2146163338.000000というのは大きすぎる気がしますね。maxも10進数で3桁近辺になるのが正常だと思われます。 ・piOutputData[0]などの初期値が変な値になってないか(最初にpiOutputData全体がゼロクリアされていれば良いのですが) ・piInputDataとpiOutputDataの使い分けに間違いが無いか ・計算式に間違いが無いか 確認が必要だと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問