• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:誤差拡散法のプログラミング)

誤差拡散法のプログラミングで真っ白になる原因は?

このQ&Aのポイント
  • プログラミング課題でグレースケール画像の誤差拡散法を用いた二値化を行っているが、書いたコードを実行すると画像が真っ白になってしまう。
  • コード内の誤差の計算や二値化に関する処理は正しいが、誤差拡散の計算方法に問題がある可能性がある。
  • プログラミングのループ処理において誤差が累積されることで、画像の全体が真っ白になってしまうのかもしれない。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

#3です。 アルゴリズム間違ってませんか? 【二値化 誤差拡散法】で検索かけたら 「Floyd & Steinberg型」と「Javis,Judice,& Ninke型」というのが見つかりました。 そこのサンプルと比較すると、 ・誤差の計算方法 ・誤差の分散方法 が提示したソースと異なっているようです。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.3

画像処理の手法については知識が無いのですが 提示されたソースを見て。 f[i+1] += 5/16*e; のところだけ1次元配列になっていますが これは転記ミスでしょうか?

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

このままだと正確な判断ができませんので、 1.使用している変数の型をすべて提示してください。 2.使用しているOS及びコンパイラを提示してください。 3.念のため確認しますが、このソースは、実際のプログラムのソースをコピーして、張りつけたものでしょうか。(手で入力して転記ミスはないですね) 上記の補足をお願いします。

kiki28
質問者

補足

OSはLinuxのRedHutです(つづり間違ってたらすいません) コンパイラはわかりませんがmakeを使いました。 無知で申し訳ないです。 補足します。実際のソースコードは以下のとおりです。 いろいろ関数使ってるんですけど // 入力データ(piInputmData)を誤差拡散方を用いて二値化して、 // 出力データ(piOutputData)に保存 のところから誤差拡散法に入ります。 問題は一次元配列になっているところです。理由はわかりませんが位置次元でやれとのことなので・・・。 void Error_diffusion_method(void){ int iWidth, iHeight, iMaxValue; // 画像の幅,高さ,解像度 int * piInputData; // 入力データの格納 int * piOutputData; // 画像処理したデータを格納 int e; // 誤差を格納 int i; // ループカウンタ // 二値画像 printf("\n**** Error diffusin method Image *****\n"); // PGM形式の入力データの読み込み piInputData = ReadPgm(&iWidth, &iHeight, &iMaxValue); // 出力データ(1次元)のメモリ領域の確保 // piOutputData[iWidth*iHeight] piOutputData = (int *)malloc(iWidth*iHeight*sizeof(int)); // 入力データ(piInputmData)を誤差拡散方を用いて二値化して、 // 出力データ(piOutputData)に保存 for(i = 0; i < iWidth*iHeight; i++){ e = 255 - piInputData[i]; //拡散処理前の対象画素処理 if(piInputData[i] <= 127){ piInputData[i] = 0; } else{ piInputData[i] = 255; } piOutputData[i] = piInputData[i]; //誤差拡散処理 //1.最後の画素の時 if(i == (iWidth*iHeight-1)){ } //2.最下行の時 else if(i >= (iWidth*iHeight - iWidth)){ piInputData[i+1] += e*3/16; } //3.右端の時 else if(((i+1) % iWidth) == 0){ piInputData[i+iWidth] += e*3/16; } //4.通常状態 else{ piInputData[i+1] += e*3/16; piInputData[i+iWidth] += e*3/16; piInputData[i+iWidth+1] += e*5/16; } } // 入力データを保存しているメモリ領域を解放 FreePgm(piInputData); // PPM形式のファイルに出力データを出力 WritePgm(piOutputData, iWidth, iHeight, iMaxValue); // 出力データを保存しているメモリ領域を解放 FreePgm(piOutputData); } となっています。

全文を見る
すると、全ての回答が全文表示されます。
  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

詳しくはみてませんが、 > 5/16*e これが必ず0になるのが原因ではないですか? (整数演算なので5/16は0。0に何をかけても0。)

kiki28
質問者

補足

あ、そうですね。実際のソースコードも e*5/16 でした。 しかし上記のようにしても結果は同じ・・・申し訳ありません。 回答ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • シンプソン法の誤差評価

    (例)台形公式の誤差評価 区間[x(i-1) , x(i)]を考える 真の面積は、ΔS(i-1)=∫(x(i-1) →x(i) )f(x)dx=F(x(i))-F(x(i-1)), 近似面積は、h/2(f(x(i-1)+f(x(i))である。 ところでF(x(i))=F(x(i-1)+h)=F(x(i-1))+f(x(i-1))h+(1/2!)f ' (x(i-1))h^2+,,,,,,であるから 誤差E(i-1)=真の面積-近似面積=ΔS(i-1)-f(x(i-1))h=(-1/12)f '' (x(i-1)h^3+,,,,, 全区間の誤差 E=Σ(i=1,n)E(i-1)=-n((h^3/12)Σ(i=1,n)f ' (x(i-1))+,,,,)=( (x(n)-x(0))/12 )h^2Σ(i=1,n)f ''(x(i-1)+,,,,,, と同様にしてシンプソンの公式の誤差評価も示したいのですが、解答、解法お願いします

  • お願いします!!!プログラミングについて。

    お願いします!!!プログラミングについて。 次の文が実行されると何がどのようにプリントされるか。何もプリントされない時は「なし」と記せ。 また、途中に「ブランク」が入る場合は、”b”と記せ。 (1) printf("i=%d j=%lf\n", 1/2,1/3); (2) x = 0.5; y= 1e0/3e0; printf("x = %7.3f, y = %12.5e\n", x, y); */ (3) i = 2; j = 3; printf("%d", i==2); (4) int sum1(i){ int s = 0; return s += i; } int sum2(i){ static int s = 0; return s += i; } main(){ int s1, s2, i; for(i=1;i<=10;i++){ s1 =sum1(i); s2 = sum2(i);} printf("%d %d\n",s1,s2); } (5) int mtx[4][3] = {{1,2,3},{4,5,6},{7,8,9},{-1,-2,-3}}; int i,j,rtot,ctot[3]={0,0,0},stot=0; for(i=0,i<4,i++){ rtot = 0; for(j=0;j<3;j++){ rtot += mtx[i][j] ctot[j] += mtx[i][j]; stot += mtx[i][j]; printf("%3d ",mtx[i][j]); } printf(" %3d\n",rtot); } printf("\n"); for(j=0;j<3;j++) printf("%3d ",ctot[j]); printf(" %3d\n",rtot); この5問をプログラミングに詳しい方教えてください!切実です。。 一つだけでも構いません!よろしくお願いします。

  • お願いします!!!プログラミングについて。

    お願いします!!!プログラミングについて。 次の文が実行されると何がどのようにプリントされるか。何もプリントされない時は「なし」と記せ。 また、途中に「ブランク」が入る場合は、”b”と記せ。 (1) printf("i=%d j=%lf\n", 1/2,1/3); (2) x = 0.5; y= 1e0/3e0; printf("x = %7.3f, y = %12.5e\n", x, y); */ (3) i = 2; j = 3; printf("%d", i==2); (4) int sum1(i){ int s = 0; return s += i; } int sum2(i){ static int s = 0; return s += i; } main(){ int s1, s2, i; for(i=1;i<=10;i++){ s1 =sum1(i); s2 = sum2(i);} printf("%d %d\n",s1,s2); } (5) int mtx[4][3] = {{1,2,3},{4,5,6},{7,8,9},{-1,-2,-3}}; int i,j,rtot,ctot[3]={0,0,0},stot=0; for(i=0,i<4,i++){ rtot = 0; for(j=0;j<3;j++){ rtot += mtx[i][j] ctot[j] += mtx[i][j]; stot += mtx[i][j]; printf("%3d ",mtx[i][j]); } printf(" %3d\n",rtot); } printf("\n"); for(j=0;j<3;j++) printf("%3d ",ctot[j]); printf(" %3d\n",rtot); この5問をプログラミングに詳しい方教えてください!切実です。。1問だけでも構いませんのでよろしくお願いします。

  • 拡散方程式のプログラミング

    拡散方程式を種々の初期条件、境界条件の下にプログラミング化(できればfortranがいいですが、その他でも大歓迎です) まず、前回の質問たくさんの方に返事していただきました。 本当にありがとうございます!!!前回の質問を整理しました。 厚さがq(μm)、底面が気体が透過しないように設定されたペイントの表面の酸素濃度C(t)を時間幅0<=t<=t0(最大時間t0まで)周期的に変えます。 ここで、拡散方程式 σC/σt=Dm*(σC^2)/(σZ^2) C:気体濃度、Z:厚さ方向、t:時間、Dm(μm2/s):拡散係数 というのがあり、これを中心差分近似したものが、 (C(i,t+1)-C(i,t))/Δt=(C(i+1,t)-2C(i,t)+C(i-1,t))/(ΔZ^2) となります。この拡散方程式に加えて、初期条件、境界条件を以下のように加えます。 ・初期条件 (初期状態は厚さ方向に一様の真空状態) →t=0;C=0(この式は正しいかわかりません↓↓) ・境界条件 ペイントの底面では厚さ方向にて濃度が同じ。 →Z=h;σC/σZ=0 この条件を離散化したものが、 →(C(1,t)-C(0,t))/ΔZとなります。 また、境界条件といたしまして、ペイント表面の濃度変化を正弦関数C(t)=Ksin2πft (K:定数、f:周波数、t:時間) として与えます。 ここで、補足をいたしますと、 ペイント表面の気体濃度を変化させると、その表面の気体はペイントの拡散係数に応じてペイント内部に拡散します(ペイント底面は気体は透過しない)。 ここで求めたい問題は、ペイント内のある時間での気体の厚さ方向での濃度分布、かつ、その厚さ方向の濃度を合計したペイント全体の気体濃度、さらに、一番求めたいのはペイント全体の気体濃度の時間変化(0<=t<=t0まで)プログラミング化するのですが。。。 様々な方のアドバイスを聞きたくてたくさん質問しています。。。申し訳ありません。

  • プログラミングのことで困っています。助けて下さい。

    プログラミングの問題がどうしても分からず、本当に困っています。 ・2x+y+3z=13 ・x+3y+2z=13 ・3x+2y+z=10 (解:x=1,y=2,z=3) を掃き出し法で解くプログラミングの問題で、次の(1)~(5)が何が当てはまるかどうしても分からないんです。 #include <stdio.h> #define N 3 /*未知数の個数*/ int main(void) { int i,j,k; double pivot,del; double a[N][n+1]={{2,1,3,13},{1,3,2,13},{3,2,1,10}}; /*係数行列*/ for(i=0;i<N;i++) { (1)____ /*ピボット係数*/ for(j=0;j<N+1;j++) /*ピボット行をピボットで割る*/ (2)____ for(k=0;k<N;k++) /*ピボット列の掃き出し*/ { if((3)____) { del=a[k][i]; for(j=i;j<N+1;j++) (4)____ } } } for(i=0;i<N;i++) (5)____ /*計算結果の表示*/ return 0; } 実行結果は x0=1.00 x1=2.00 x2=3.00 と表示させたいのですが、(1)~(5)の所がどうしても分からず、困っています。どなたか助けて下さい。お願いします。

  • 誤差を含む数値同士を掛け算した時の誤差

    誤差を含む数値を足し算した時の誤差については、ここで「集積誤差」とか「累積誤差」とかをを調べて理解したのですが、掛け算の場合はどう考えたら宜しいのでしょうか? 例えば、ある液体を「a±h 倍」に希釈したサンプルの濃度を測定したら「b±i g/L」であった。原液の全量が「c±j L」あるとき、全体に含まれている物質の量を「d±k g」と表わすと、当然 d=a×b×c ですが、誤差の部分 ±k を計算するには、どうしたら良いでしょうか? なお、このカテゴリーへは初めての書き込みです。不備がありましたら御指摘下さい。

  • 誤差を含む数字同士を掛け算した時の誤差

    誤差を含む数値を足し算した時の誤差については、ここで「集積誤差」とか「累積誤差」とかをを調べて理解したのですが、掛け算の場合はどう考えたら宜しいのでしょうか? 例えば、ある液体を「a±h 倍」に希釈したサンプルの濃度を測定したら「b±i g/L」であった。原液の全量が「c±j L」あるとき、全体に含まれている物質の量を「d±k g」と表わすと、当然 d=a×b×c ですが、誤差の部分 ±k を計算するには、どうしたら良いでしょうか? なお、このカテゴリーへは初めての書き込みです。不備がありましたら御指摘下さい。

  • プログラミングについて

    初めまして、初めて質問させていただきます。 いきなりですが最近プログラミングにはまり、独学でCプロをやり始めた物なのですが、以下のようなプログラムをCプロで打ち込んでコンパイルしたところ int main(void) { int i,j,height,length; scanf("%d",&height); if(height % 2 ==0) { putchar("invalid"); { return 0; } } scanf("%d",&length); if(height>=1 && height<=100) for(i=1;i<=height;i++){ for(j=1;j<=length;j++) if(i ==1 || i==height) { putchar('e'); } else if( i !=height/2+1){ putchar('e'); for(j=1;j<length;j++) putchar('.'); } else{ for(j=1;j<=length/2+1;j++) putchar('e'); for(j=length/2+1;j<length;j++) putchar('.'); } putchar('\n'); } return(0); } ――――――――――― Main.c:5:1: warning: implicitly declaring library function 'scanf' with type 'int (const char *restrict, ...)' [-Wimplicit-function-declaration] scanf("%d",&height); ^ Main.c:5:1: note: include the header <stdio.h> or explicitly provide a declaration for 'scanf' Main.c:8:5: warning: implicit declaration of function 'putchar' is invalid in C99 [-Wimplicit-function-declaration] putchar("invalid"); ^ 2 warnings generated. ――――――――― と上のようなエラー内容が出てしまい、丸一日自分で模索しても何故こんなエラーが出て来てしまうのか分からない為、教えて頂けるとありがたいです。

  • プログラミングの課題で困ってます。

    正弦関数x=sintのグラフを■で描きなさい(31行程度で)。数値xに対する■の数はウインド各行に表示される しきれる範囲内で任意に定めてよい。 という課題が出ました。よくわからなくて困っています。 下記に書いてるプログラミングを参考に答えを教えていただきたいと思い、質問させていただきました。よろしくお願いします。 また、下記を参考にしなくてもよいです。 プログラミングはvisual C++ 2008を使ってます。 #include "stdafx.h" #include<stdio.h> #include<math.h> int _tmain(int argc, _TCHAR* argv[]) { double x[100]; int i , j; for(i=0; i<31; i++){ x[i]=sin(0.1*i); } // for(j=0; j<31; j++){ // printf("%lf\n",y[j]); // } for(i=0; i<31; i++){ for(j=0; j<x[i]*20; j++){ printf("■"); } printf("\n"); } return 0; }

  • C++の打切り誤差についてお聞きしたいのですが・・

    ↓のプログラムが、なぜ実行結果のsumが1ではなく1.000054や9.99999999999906e-001、9.9999999999990619e-001といった答えにになってしまうのでしょうか? 10000のところを512でやった場合は普通に1と出力されたのに・・・ #include <stdio.h> int main(void){ int i; float f; double d; f = 0.0; for(i = 0; i<10000; i++) { f += 1.0/10000; } printf("float: n=%d sum=%f\n", 10000, f); d = 0.0; for(i = 0; i<10000; i++) { d += 1.0/10000; }// end for printf("double:16.14e: n=%d sum=%16.14e\n", 10000, d); printf("double:18.16e: n=%d sum=%18.16e\n", 10000, d); return 0; } 実行結果 float: n=10000 sum=1.000054 double:16.14e: n=10000 sum=9.99999999999906e-001 double:18.16e: n=10000 sum=9.9999999999990619e-001 続行するには何かキーを押してください . . .