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

http://image.onishi-lab.jp/002.html#1
ここを参考にsobelオペレータによるエッジ検出をしようとしています。
fxとfyのところを考えるのですが、とりあえず1にして出力したら文字化けしました。
文字化けの原因を教えてください。
読み込む画像は横160ピクセル、縦70ピクセルのP2形式のpgmファイルです。
#include <stdio.h>
#include <stdlib.h>

int pgm_read(char *filename, unsigned char *pimage){
FILE *fp;
if((fp=fopen(filename,"rb"))==NULL){
printf("ファイル%sが開けません\n",filename);
exit(-1);
}
fscanf(fp,"P2\n160 70\n255\n"); //ヘッダを読み飛ばす
fread(pimage,sizeof(char),160*70,fp);
fclose(fp);
return 0;
}

int pgm_write(char *filename, unsigned char *pimage){
FILE *fp;
fp=fopen(filename,"wb");
fprintf(fp,"P2\n160 70\n255\n");
fwrite(pimage,sizeof(char),160*70,fp);
fclose(fp);
return 0;
}

main(){
unsigned char *image; //取り込む画像
unsigned char *edge; //エッジ画像
int x,y;
int fx,fy; //オペレータグラジエントの強度
FILE *fp;

image = malloc(sizeof(char)*160*70); //メモリの確保
edge = malloc(sizeof(char)*160*70);
pgm_read("input.pgm", image); //ファイルの読み込み

for(y=1;y<70-1;y++){ //Sobel オペレータ
for(x=1;x<160-1;x++){
fx = 1;// ここを考える
fy = 1;// ここを考える
if(fx*fx+fy*fy>500) *(edge+160*y+x) = 0x00; //閾値より大きいところは黒
else *(edge+160*y+x) = 0xff; //それ以外は白
}
}

pgm_write("output.pgm", edge); //ファイルの書き込み
free(image); //メモリの開放
free(edge);
}


文字化けの様子は
P2
160 70
255
^@^@^@^@^@^@^@^@・・・
^@\377\377\377・・・

みたいな感じです。

A 回答 (4件)

>平滑化してからsobelフィルタをかけたものも作ったのですが、


>平滑化だけのものと、その後にsobelフィルタをかけたもので、
>差がありませんでしたなぜなのでしょうか・・・

今度まともにソースすら見ていません
ブログラムを2つに分けてみてください
平滑化のみを行った画像
平滑化を行った画像を使ってそーべる処理を行った結果
これを比較してください
多分動いてるんじゃないですか?

両方まとめて処理した時に動いていないのは
動いていないのではなくて両方の処理したデータだけを
連続的に同じファイルに書いているからです

この回答への補足

それは既にしてみたのですが、あなたがそう仰るなら、たぶんそこに原因はなく、フィルタ自体に原因があるとみて、焦点を絞って調べようと思います。

補足日時:2013/06/30 08:31
    • good
    • 0
この回答へのお礼

解決しました。元々違和感はあったのですが、*rに、フィルタリングした数値を一々入れていたのが原因でした。これではエッジ検出できないわけです。tmpに直接代入したらいけました。

前回同様デバッグが苦手です・・・隅から隅まで見たらどうでもいいところばかり試行錯誤し、焦点を絞ったら初歩的ミスや盲点を見逃す・・・

ご回答ありがとうございました。

お礼日時:2013/06/30 08:58

No2 の補足に関して  (質問文と合わせて全文ちゃんと見てません)



if(fprintf(fp,"%d\n",tmp) < 0)
tmpに値を代入してる部分がどこにもないようですが・・・・
デバックモードなどでたまたま0になってるってだけの話ではないですか?

この回答への補足

うっかりしていました。
tmpもいれ、sobelフィルタを3×3にして作りました。
するとQRコードみたいな画像が出力されました・・・。
また、平滑化してからsobelフィルタをかけたものも作ったのですが、平滑化だけのものと、その後にsobelフィルタをかけたもので、差がありませんでした。
なぜなのでしょうか・・・

以下、平滑化→sobelフィルタをかけるプログラムです。
/*平滑化ここから*/~/*平滑化ここまで*/を取り除いたプログラムが、sobelフィルタだけのプログラム(QRコードが出力)です。

Picture* edge(FILE* fp,Picture* pPic,int type){
int i,j,k; /* ループ用変数 */
unsigned char tmp; /* 作業用変数 */
unsigned char *r,*g,*b; /* 作業に使用するポインタ */

if(fp == NULL ||
pPic == NULL ||
(type < 1 || type >6)) /* 引数が異常 */
return NULL;
r = pPic->r;
g = pPic->g;
b = pPic->b;
/* ファイルヘッダの出力 */
if(fprintf(fp,"P%d\n%d %d\n",type,pPic->x,pPic->y) < 0)
return NULL;
if(type == 2 || type == 3 || type == 5 || type == 6){
if(fprintf(fp,"255\n") < 0)
return NULL;
}
/* 画像データの出力 */
/* 2値ascii形式 */
/*平滑化ここから*/
for(i=0 ; i<pPic->y ; i++){
for(j=0 ; j<pPic->x ; j++){
*r =(*(r-1)+*r+*(r+1))/3; //平滑化
tmp=*r;
r++;
if(fprintf(fp,"%d\n",tmp) < 0)
return NULL;
}
}
r=r-(pPic->x*pPic->y);
/*平滑化ここまで*/
for(i=0 ; i<pPic->y ; i++){
for(j=0 ; j<pPic->x ; j++){
*r=*(r-1-(pPic->x))*(-1)+*(r+1-(pPic->x))+*(r-1)*(-2)+*(r+1)*2+*(r-1+(pPic->x))*(-1)+*(r+1+(pPic->x));
tmp = (int)sqrt(*r**r);
r++;
//printf("%d\n",tmp);
if(fprintf(fp,"%d\n",tmp) < 0)
return NULL;
}
}
return pPic;
}
int main(void)
{
FILE *fpi,*fpo;
char *fnamei = "input.pgm";
char *fnameo = "output.pgm";

fpi = fopen( fnamei, "r" );
if( fpi == NULL ){
printf( "%s error", fnamei );
return -1;
}
fpo=fopen(fnameo,"w");
edge(fpo,getPpm(fpi),2);
fclose;
return 0;
}

補足日時:2013/06/30 06:21
    • good
    • 0

そのpgmファイルをcatしたのですか?


このコードから察するに、pgmファイルは端末に出力して読める形式ではなく、ビットマップ画像を表示できる類の専用のソフトを用いなければならないバイナリファイルになっているはずです。
端末に出力してその結果になった場合、恐らく^@は0x00を、\377は0xffを指します。動作は正常です。
不安であればbviやhexdump等のバイナリビュワーを用いて見てみましょう。

あるいは、専用の画像ビュワーを用いてpgmファイルを開いてみてはどうでしょう?

この回答への補足

バイナリ形式なのが問題だったのですね。みなさんご回答ありがとうございます。
今度は
http://www.mm2d.net/c/c-08.shtml
を参考に、アスキー形式で作りました。
しかし出力が全部0になってしまい、画像は真っ黒です。
なにが原因なのか教えていただけないでしょうか。
sobelオペレータをかけた関数部とmain関数だけ抜粋しました(字数上)
getPpmとputPpmは、入力関数と出力関数です。
*gとか*bとかtypeとかはいらないですが気にしないでください・・・

Picture* edge(FILE* fp,Picture* pPic,int type){
int i,j,k; /* ループ用変数 */
unsigned char tmp; /* 作業用変数 */
unsigned char *r,*g,*b; /* 作業に使用するポインタ */

if(fp == NULL ||
pPic == NULL ||
(type < 1 || type >6)) /* 引数が異常 */
return NULL;
r = pPic->r;
g = pPic->g;
b = pPic->b;
/* ファイルヘッダの出力 */
if(fprintf(fp,"P%d\n%d %d\n",type,pPic->x,pPic->y) < 0)
return NULL;
if(type == 2 || type == 3 || type == 5 || type == 6){
if(fprintf(fp,"255\n") < 0)
return NULL;
}

/*処理*/
for(i=0 ; i<pPic->y ; i++){
for(j=0 ; j<pPic->x ; j++){
*(r++) =*(r-1)*(-1)+*(r+1); //-1 0 1のsobelフィルタにかけたつもり…
if(fprintf(fp,"%d\n",tmp) < 0)
return NULL;
}
}
return pPic;
}
int main(void)
{
FILE *fpi,*fpo;
char *fnamei = "input.pgm";
char *fnameo = "output.pgm";

fpi = fopen( fnamei, "r" );
if( fpi == NULL ){
printf( "%s error", fnamei );
return -1;
}
fpo=fopen(fnameo,"w");
edge(fpo,getPpm(fpi),2);
fclose;
return 0;
}

補足日時:2013/06/30 01:55
    • good
    • 0

>

http://image.onishi-lab.jp/002.html#1

参考にされているurlに書かれているプログラムはP5やP6のバイナリファーマット用なのに、それをほぼそのままASCII形式のP2で使用してるからです。
    • good
    • 0

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