dポイントプレゼントキャンペーン実施中!

c言語で画像処理のソーベルのフィルタが作りたいのですが、どうにもうまく動きません。おかしい点をご指摘していただけないでしょうか。一次元配列で作りたいです。

/*wiは読み込んだ画素値、woは書き出す画素値、m1,m2はフィルタ係数、widthは画像の幅、heightは画像の高さ*/
void sobel(unsigned char wi[], unsigned char wo[], char m1[],char m2[],int width, int height){
int i,j,k,l,z;
unsigned char *w;
unsigned char *wo2;
w = (char*)malloc(sizeof(char)*(MW*MH));
wo2 = (char*)malloc(sizeof(char)*(MW*MH));

/*フィルタの適用*/
for(i=width+1; i<width*height; i++)
wo[i]=wi[i-1-width]*m1[0]+wi[i-width]*m1[1]+wi[i+1-width]*m1[2]+wi[i-1]*m1[3]+wi[i]*m1[4]+wi[i+1]*m1[5]+wi[i-1+width]*m1[6]+wi[i+width]*m1[7]+wi[i+1+width]*m1[8];

for(j=width+1; j<width*height; j++)
wo2[j]=wi[j-1-width]*m2[0]+wi[j-width]*m2[1]+wi[j+1-width]*m2[2]+wi[j-1]*m2[3]+wi[j]*m2[4]+wi[j+1]*m2[5]+wi[j-1+width]*m2[6]+wi[j+width]*m2[7]+wi[j+1+width]*m2[8];

for(k=width+1; k<width*height; k++)
wo[k] = (unsigned char)sqrt(wo[k]*wo[k]+wo2[k]*wo2[k]);

/*画素値を0から255に*/
for(l=width+1; l<width*height; l++){
if((unsigned char)wo[l] < 0)
w[l] = 0;
else if((unsigned char)wo[l] > 255)
w[l] = 255;
else
w[l] = wo[l];
}

for(z=width+1; z<width*height; z++)
wo[z] = w[z];

free(w);
free(wo2);

}

よろしくお願いしますm(_ _)m

A 回答 (1件)

「どうにもうまく動きません」というのが、どう「うまく動かない」のかを説明していただけないと、


何に困っているのかこちらには分かりませんので、回答のしようがないのですが、

とりあえず見てわかる範囲で。
・各forループの範囲
ループを「i < width * height」といった条件で回していますが、
wi/wo のメモリ範囲が(画像サイズ)がwidth×heightなのだとしたら、範囲を超えてアクセスしており、これではメモリ破壊が起きます。
ループ範囲は、開始が0でなくwidth+1にしているのと同様に、終了条件を「i < width*(height-1)-1」にすべきでしょう。

・/*画素値を0から255に*/ の部分
ここで判定に使っている変数 wo は unsigned char 型の配列ですから、
その前のループ内のsqrt計算で結果が計算結果が0未満や255超になったときは、
unsigned char にキャストしてwo[k]に代入した時点で、その情報は失われてしまい、
データが壊れてしまってます。

その前段階の wo/wo2のループも含めて、計算処理内では、データはunsigned char 型ではなく、int型などで持っておくべきです。

あと、4回ループを回すのはかなり無駄です。一回のループ内で全て処理すれば十分。
メモリの一時確保も不要。
実際に動作は確認してませんが、
---ここから---
void sobel(unsigned char wi[], unsigned char wo[], char m1[],char m2[],int width, int height)
{
int i;
int w, w1, w2;
/*フィルタの適用*/
for(i=width+1; i<width*(height-1)-1; i++) {
w1=wi[i-1-width]*m1[0]+wi[i-width]*m1[1]+wi[i+1-width]*m1[2]+wi[i-1]*m1[3]+wi[i]*m1[4]+wi[i+1]*m1[5]+wi[i-1+width]*m1[6]+wi[i+width]*m1[7]+wi[i+1+width]*m1[8];
w2=wi[j-1-width]*m2[0]+wi[j-width]*m2[1]+wi[j+1-width]*m2[2]+wi[j-1]*m2[3]+wi[j]*m2[4]+wi[j+1]*m2[5]+wi[j-1+width]*m2[6]+wi[j+width]*m2[7]+wi[j+1+width]*m2[8];
w = (int)(0.5+sqrt(w1*w1+w2*w2));
if (w < 0) {
w = 0;
} else if (w > 255) {
w = 255;
}
wo[i] = (unsigned char)w;
}
}
---ここまで---
こんな感じのコードで十分なはずです。
    • good
    • 2
この回答へのお礼

お礼が遅れて申し訳ありません。

>>どうにもうまく動きません」というのが、どう「うまく動かない」のかを説明していただけないと、何に困っているのかこちらには分かりません
その通りですね。以後気を付けたいと思います。

指摘していただいた部分を直したら、ちゃんと動作しました。助かりました。丁寧なご解答、ありがとうございましたm(_ _)m

お礼日時:2010/12/15 12:13

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!