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

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

ただいまの
回答率

91.36%

  • C

    2525questions

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

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

受付中

回答 1

投稿 2017/12/08 21:52

  • 評価
  • クリップ 0
  • VIEW 80

RYUi

score 2

前提・実現したいこと

微分フィルタの1つであるsobelフィルタを用いてPGM形式の濃淡画像をエッジ画像に出力したい.

発生している問題・エラーメッセージ

画像が真っ暗になる.

該当のソースコード

void EdgeDetection(void){

  int iWidth = 0, iHeight = 0, iMaxValue = 0; // 画像の幅,高さ,解像度               
  int *piOutputData = NULL;         // 画像処理したデータを格納                      



  int i,j,k,l = 0;
  int sobel_x[9]={-1,0,1,
                  -2,0,2,
                  -1,0,1};
  int sobel_y[9]={-1,-2,-1,
                  0, 0, 0,
                  1,2,1};
  double sum_x,sum_y;
  double sum;
  int max;
  float para;
//ファイル入力
  piOutputData=ReadPgm(&iWidth,&iHeight,&iMaxValue);
 //微分フィルタ                                                                      
  for(i=1;i<iHeight-1;i++){
    for(j=1;j<iWidth-1;j++){

      sum_x=0;
      sum_y=0;
      sum=0;
      for(k=0;k<3;k++){
        for(l=0;l<3;l++){
          sum_x+=sobel_x[3*k+l]*piOutputData[(i+k-1)*iWidth+(j+l-1)];
          sum_y+=sobel_y[3*k+l]*piOutputData[(i+k-1)*iWidth+(j+l-1)];
        }
      }

      sum=sqrt(pow(sum_x,2.0)+pow(sum_y,2.0));
      //     printf("%f\n",sum);                                                      
      piOutputData[i*iWidth+j]=sum;
    }
  }

    //最大輝度値を走査                                                                
  max=piOutputData[0];
  for(i=1;i<iWidth*iHeight;i++){
    if(max<piOutputData[i])
      max=piOutputData[i];
  }

  //スケール変換のパラメータ                                                          
  para=255/max;

  //スケール変換                                                                      
  for(j=0;j<iHeight*iWidth;j++){
    piOutputData[j]=para*piOutputData[j];
  }

  //ファイルへ出力                                                                    
  WritePgm(piOutputData,iWidth,iHeight,iMaxValue);
//ファイル領域解放
  FreePgm(piOutputData);

}

試したこと

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

補足情報(言語/FW/ツール等のバージョンなど)

C言語により実装する.

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 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 23:47

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/08 23:53

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

    キャンセル

  • 2017/12/09 00:11

    今のところ可能性として考えられるのは
    ・paraを求める式が整数演算になっているので、結果が小さい値(もしかすると0)になっている
    または
    ・sumの計算結果よりも4辺のpiOutputDataの最大値のほうが大きいので、結果が小さい値(もしかすると0)になっている
    あるいは両方、です。

    まずは
    ・paraを求める計算式を変更する
    それでダメなら
    ・maxを求めるループも、sumを求めるループと同様に4辺を除外する
    ですかね。

    4辺の値の出力結果は別途考えるということで。

    キャンセル

  • 2017/12/09 00:42

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

    キャンセル

  • 2017/12/09 01: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の値を触ってませんが、その値が適切かどうかは不明です。

    キャンセル

  • 2017/12/09 09:44

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

    キャンセル

  • 2017/12/09 11:51

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

    キャンセル

  • 2017/12/09 14: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の使い分けに間違いが無いか
    ・計算式に間違いが無いか
    確認が必要だと思います。

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

  • 受付中

    OpenCVで動画の読み込みがうまくできません。

    以前別のプログラムで動画の読み込みができましたが、今現在取り組んでいるプログラムではうまくいきません。 言語はC++でopencv2.4.9を使用しています。 Os windo

  • 解決済

    合計、平均の出しかた

    class Art{ public static void main(String[] args){ //argを初期化 String a

  • 解決済

    プログラムの改善

    前提・実現したいこと C言語で数値計算のプログラムを書きました。 効率が悪いところや、他の書き方がありましたら、アドバイスしていただけると助かります。 該当のソースコード

  • 受付中

    解決策が分かりません・・・

    5人の点数をキーボードから読み込んで、合計点、平均点、最高点、最低点を表示したいのですが(点数は0以上100以下)、 実行例 5人の点数を入力してください。 1番:95 2

  • 解決済

    結果の表示について

    課題で、 キーボードから入力された数値の平均を計算して表示し、平均以上の数値、平均より小さい数値を表示するプログラムを考えているのですが、 実行例 ./a.out

  • 解決済

    準備された入力ファイルをもとに、合計、平均、偏差値を表示(合計点降順)させたプログラム作成

    レポート課題でわからない問題があります。 問題:入力ファイルmotofile.datを事前に用意し、出力ファイルresult.datを生成するC言語ソースプログラムファイルhen

  • 解決済

    テスト点などの得点率を計算し表示する方法

    前提・実現したいこと Java8で配列の勉強のために得点等を計算するシステムを作っています。 合計点、平均点、得点率を表示する機能を実装中に以下の問題が発生しました。 発

  • 解決済

    無限ループしてしまうようになった

    解決したいこと 一度はうまくいったのですが、作り直したらなぜか無限ループしてしまうようになってしまいましたのですが、わかる方いますか。コンパイルも通っているのですが。 追記 #

同じタグがついた質問を見る

  • C

    2525questions

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