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

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

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

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

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

フィルタ

フィルタとは、特定の条件に合わせてデータへのアクセスをブロックするプログラムやルーチンを指します。

Q&A

解決済

1回答

1837閲覧

C言語で画像ファイルを読み込み、sobelフィルタをかける

nichi_nicihi120

総合スコア2

C

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

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

フィルタ

フィルタとは、特定の条件に合わせてデータへのアクセスをブロックするプログラムやルーチンを指します。

0グッド

0クリップ

投稿2020/06/13 06:02

使用環境はubuntu18.04です。

画像ファイルを読み込んだ後に周りの端っこの1マス以外フィルタをかけたつもりなのですがとても大きい値が帰ってきます。理由が知りたいです。
sobelフィルタの横方向のフィルタを使用しました。画像からr,g,bをとりだしフィルタをかけました。```C言語
コード

#include <gd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(const int argc,const char *argv[]){ FILE *out,*in; gdImagePtr im,im_new; int width,height,i,j,color,r,g,b,pixel; int weightX[3][3]={ {-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1} }; if(argv[1]==NULL||argv[2]==NULL||!strcmp(argv[1],argv[2])){ printf("argument error\n"); exit(-1); } //第一引数で指定されたファイルを読み出し用にオープン if((in=fopen(argv[1],"r"))==NULL){ printf("file open error for %s\n",argv[1]); exit(-1); } //第二引数で指定されたファイルを書き出し用にオープン if((out=fopen(argv[2],"wb"))==NULL){ printf("file open error for %s\n",argv[2]); exit(-1); } //im に画像を読み込み im = gdImageCreateFromJpeg(in); //入力画像のサイズを取得 width=gdImageSX(im); height=gdImageSY(im); //新しい画像を用意 im_new= gdImageCreateTrueColor(width,height); for(i=0;i<width;i++){ for(j=0;j<height;j++){ int rX=0,gX=0,bX=0,p=0; if(i==0 || j==0 || i==width-1 || j==height-1){ //im の (i,j) におけるカラーインデックスの取得 pixel=gdImageGetPixel(im,i,j); //im の (i,j) における r,g,b の値を取得 r=gdImageRed(im,pixel); g=gdImageGreen(im,pixel); b=gdImageBlue(im,pixel); p=0.298912*r+0.586611*g+0.114478*b; } else{ for(int a=0;a<3;a++){ for (int b=0;b<3;b++){ pixel=gdImageGetPixel(im,i+a-1,j+b-1); r=gdImageRed(im,pixel); g=gdImageGreen(im,pixel); b=gdImageBlue(im,pixel); //フィルターをかける rX=rX+r*weightX[a][b]; gX=gX+g*weightX[a][b]; bX=bX+b*weightX[a][b]; } } rX=rX/9; gX=gX/9; bX=bX/9; rX>255?255:rX<0?0:rX; gX>255?255:gX<0?0:gX; bX>255?255:bX<0?0:bX; p=rX; if(p<gX) p=gX; if(p<bX) p=bX; printf("%d\n",p); } // p=0.298912*r+0.586611*g+0.114478*b; //r,g,b 値から color を割り当て color=gdImageColorExact(im_new,p,p,p); //im_new の (i,j) におけるピクセル値を color で設定 gdImageSetPixel(im_new,i,j,color); } } gdImageJpeg(im_new,out,-1); fclose(in); fclose(out); return 0; }

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

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

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

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

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

guest

回答1

0

ベストアンサー

とても大きい値が帰ってきます

具体的に、なにがとても大きい値になるのでしょう?

gdというライブラリを知らない(試すつもりもない)ので多少当てずっぽうになります。
gdImageColorExact(img,r,g,b)という関数は、第一バラメータのイメージオブジェクトが持っているカラーテーブルからr,g,b値の一致するものを検索し、厳密に一致するものがあればそれをintにpackして返し、一致するものがなければ-1(0xffffffff)を返す、というもののようです(違うようなら説明して下さい)。
この関数に、color=gdImageColorExact(im_new,p,p,p);として与えたred:p,green:p,blue:pという色気を持つ色がim_newのテーブルに無かった、ということではないでしょうか。0xffffffffは、unsignedで扱えば‭4294967295‬の大きな値になります。

質問が、

理由が知りたいです。

なので以下は全て余談となりますが...

  • まず、質問のコード部分を```で囲って下さい。この辺が参考になるでしょうか。こんな議論もありました。

  • RGBの各色から輝度を求める式がp=0.298912*r+0.586611*g+0.114478*bと有効数字がやたら細かいですね。確かに、映像製作用の規格等では細かく決まっていて、その細かい数字を使うのは間違いではないですが(しかし規格毎に少しずつ数値が違ったりする)、所詮人間の感覚の話なので、赤0.3緑0.6青0.1、とかで混ぜても実用上問題ない効果が得られる、というのは知っておいて損はないと思います。

  • 画面の内部はpとしてr/g/bのうちから単純に最大値を取っているのは意図通りなのですか? まぁ、エッジ検出としてはありと言えばありなのかも知れませんが。

  • for (int b=0;b<3;b++){のループの中でb=gdImageBlue(im,pixel);という操作をしているのは明らかに異常です。全黒の画像を処理しようとすると無限ループになったりしませんか?

  • 「sobelフィルタの横方向」とありますが、

C

1int weightX[3][3]={ 2{-1, 0, 1}, 3{-2, 0, 2}, 4{-1, 0, 1} 5};

では、weightX[1][0]が-2,weightX[1][2]が2になります。

C

1for(int a=0;a<3;a++){ 2for (int b=0;b<3;b++){ 3pixel=gdImageGetPixel(im,i+a-1,j+b-1); 4r=gdImageRed(im,pixel); 5g=gdImageGreen(im,pixel); 6b=gdImageBlue(im,pixel); 7//フィルターをかける 8rX=rX+r*weightX[a][b]; 9gX=gX+g*weightX[a][b]; 10bX=bX+b*weightX[a][b]; 11} 12}

で辻褄があっていますか?

投稿2020/06/14 00:38

thkana

総合スコア7629

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問