• 締切済み

細線化のプログラム

細線化のプログラム C#で細線化のプログラムを作成してみましたがうまくいきません。 http://imagingsolution.blog107.fc2.com/blog-entry-138.html を参考に作成しました。 うまくいかないところは、一部に縦線がいくつも残ってしますところです。 ソース static Bitmap Shape(Bitmap bmp) { int Flag = 0; //初期化 for (int j = 0; j < bmp.Height ; j++) { for (int i = 0; i < bmp.Width ; i++) { if (bmp.GetPixel(i, j).R != 255) { bmp.SetPixel(i, j, Color.FromArgb(0, 0, 0)); } } } while(true){ //パターン1 for (int i = 1; i < bmp.Width - 1; i++) { for (int j = 1; j < bmp.Height - 1; j++) { if (bmp.GetPixel(i, j).R == 255) { //除去しないパターン if (( 略 )) { //セーフ } else if ((略)){ //セーフ } //除去するパターン else if ((bmp.GetPixel(i + 1, j).R != 255) || (bmp.GetPixel(i, j - 1).R != 255)) { //黒にする bmp.SetPixel(i, j, Color.FromArgb(0, 0, 0)); Flag++; } } } } // MessageBox.Show(Flag.ToString()); //終了 if (Flag == 0) return bmp; Flag = 0; /*パターン2も同じようにする*/ という感じでプログラムを組んでいます。 画像は失敗例です。アドバイスをお願いします

  • CGI
  • 回答数6
  • ありがとう数15

みんなの回答

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.6

汚いフローですが書いてみました ※ ワードで書いたのでフローというよりは単純な流れ図みたいになってますが   イメージだけ伝われば良いのでご愛嬌ということで 添付のようなフローで上手く動くのではないかと思います

回答No.5

補足です。 同一座標と言っていた部分が気になったので。 処理的にはこんな感じです。 while {   for ()   {     for ()     {       //パターン1の除去     }   }   if (パターン1で除去しなかったら終了)   for ()   {     for ()     {       //パターン2の除去     }   }   if (パターン2で除去しなかったら終了) } という具合です。 なので、1画面分ごとにパターン1の除去、パターン2の除去を繰り返します。 それでも、縦の線は残るような気もしますが、除去する/しないのパターンが間違えていないか?確認してみて下さい。

回答No.4

koi1234さんがパターン1、パターン2を交互に繰り返すと言っていますが、それが正解です。 細線化では、ほぼ線の中心付近を1画素の線として残すように処理をしていきますが、パターン1では、線の右、上の方向から線を細くし、パターン2では線の左、下の方向から線を細くする処理を行っています。 そこで、今回の失敗例のプログラムを見ると、パターン1を繰り返してから、パターン2の繰り返しを行っているので、失敗例の線の位置は、もともとの線の位置の左下に偏っていませんか?

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

これ、同時に置き換えないとだめだと思うんですが。 bmp0[bmp.Width][bmp.Height] みたいなものを用意しておいて全部0にしておいて //黒にする bmp0[j][i]=1 ; Flag++; などとして、0にする箇所を記録しておいて for (int i = 1; i < bmp.Width - 1; i++) { for (int j = 1; j < bmp.Height - 1; j++) { if ( bmp[i][j] != 0 ) { bmp.SetPixel(i, j, Color.FromArgb(0, 0, 0)); } } } と、する、といったことが必要ではないんでしょうか

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.2

文書の為意味が上手く伝わっていないようです まずフローチャートに関してですが画面全体に対しての フローチャートを描いているのではなく 1座標に対してのフローチャートが描かれています (フローチャート自体もあまりよくないかも) これは良いでしょうか?  上の理解されているならパターン2の処理を書く所が  おかしいということはわかるはず 提示されているソースでは 特定の座標データがパターン1に該当するとして 除去しないデータをif文でチェックしているようです 此処まではいいのですが その条件に含まれない全てのデータが対象になるということなので >else if ((bmp.GetPixel(i + 1, j).R != 255) || (bmp.GetPixel(i, j - 1).R != 255)) ではなくて else だけになるはずです(というのが条件は要らないのでは? と書いた理由です) でもってそのelse文になった時に パターン2の除外条件をチェックするということです フロー的にその辺あたるが判りにくいような気がしますが 変換後この条件に引っかかる物は質問者さんも書かれているように 当然のごとく存在しません ですので変換前のオリジナルデータがパターン2に該当していたら という条件でチェックを継続しなければならないはずです (ここが書いてあるフローだとわかりにくいかも) 実際やってないので間違っているかもしれませんが 該当1座標のデータとその周辺のデータがパターン1/2に該当している場合 其々の除外しない条件に当てはまるデータ以外のところを 0にしなくてはいけないはずです

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.1

内容ちゃんと見てるわけではないですがフローチャートと食い違っているのでは? (以下部分以降) >//除去するパターン >else if ((bmp.GetPixel(i + 1, j).R != 255) || (bmp.GetPixel(i, j - 1).R != 255)) 上記のようにパターン1で除去するパターンでif条件が入っていますが フローでは無条件削除した上で パターン2に該当するかチェックしている様に見えます 提示ソースでは全体をパターン1だけで処理して その後パターン2を行おうとしているように思えます フローチャートでは同一座標に対してパターン1・2の処理を順番に行っています

yuikuras
質問者

補足

「パターン1に該当する場合、画素を除去する」と書いてあるので、無条件で削除するわけではないと思います。(中心が黒になると、パターン2にはひっかからないので) また、「パターン1に該当する画素が1画素も無ければその時点で終了です」という記述から同一座標に対してパターン1,2を順番に行うのは変じゃないでしょうか? もう少しアドバイスをお願いします

関連するQ&A

  • 線形補間法プログラム(C++)

    C++言語で線形補間法のプログラムを組んで実行しているのですが、どしてもうまくいきません。ただ2倍の画像を作っているだけなのですが・・・。 以下プログラムを載せます、おおよその場所はわかるのですがどうすれば通るのかわかりません。どう直したらよいのか分かる方がいましたらご教授お願いします。 ※bmp[0]:現画像 pic:bmp[0]の縦横2倍の画像 // 線形補間法 // int zx = 2; int zy = 2; int i,j,m,n; float x,y,p,q; int xs = bmp[0]->Width/2; int ys = bmp[0]->Height/2; int d; for(i = -ys; i < ys; i++){ for(j = -xs; j < xs; j++){ y = i/zy; x = j/zx; if(y > 0){ m = (int)y; }else{ m = (int)(y-1);} if(x > 0){ n = (int)x; }else{ n = (int)(x-1);} q = y - m; p = x - n; if(q == 1){q = 0; m = m + 1;} if(p == 1){p = 0; n = n + 1;} if((m >= -ys)&&(m < ys)&&(n >= -xs)&&(n < xs)){ d = (int)((1.0 - q) * (1.0 - p) * (bmp[0]->GetPixel( m + ys, n + xs)) //おそらくこの辺に問題があるかと思われます。 + p * (bmp[0]->GetPixel( m +ys, n + xs)) + q * (1.0 - p) * (bmp[0]->GetPixel(m + 1 + ys, n + xs)) + p * (bmp[0]->GetPixel(m + 1 + ys, n + 1 + xs))); }else{ d = 0; } if(d < 0){d = 0;} if(d > 255){d = 255;} pic->SetPixel(i + ys, j + xs) = d; } } pictureBox2->Image = pic; }

  • 画像の抽出

    今、VB2008を用いて、原画像と原画像に落書きをした画像の2枚を用いて、 落書きのみを抽出するプログラムを作っているのですが、 RGBの演算がどうも上手く出来ません。 コードは Dim r1#, g1#, b1#, r2#, g2#, b2#, r3#, g3#, b3#      Dim i%, j%, nx%, ny%      Dim col1, col2 As Color '略     For j = 0 To ny - 1      For i = 0 To nx - 1       col1 = bmp1.GetPixel(i, j)'落書きした画像         r1 = col1.R         g2 = col1.G         b3 = col1.B      col2 = bmp2.GetPixel(i, j)'落書き前の原画像         r2 = col2.R         g2 = col2.G         b2 = col2.B      r3 = r1 - r2       g3 = g1 - g2     b3 = b1 - b2    bmp3.SetPixel(i, j, Color.FromArgb(Int(r3), Int(g3), Int(b3)))'落書きのみ抽出された画像の書き込み     Next    Next Form1.Picturebox1.Image = bmp3 としてみたのですが、gやbの値が - になってしまい、エラーが出て しまいます。If(g3<255) then g3 =255 などと記載してみたのですが上手くいきませんでした。 どこを修正、加筆すればうまく抽出が出来る様になるのでしょうか。

  • C#について

    C#で画像の色を変更しようと頑張っているのですが・・・ クリックした座標と同じ色の場所を青にしたいです。 XとYは画像の座標の大体の最大値です。 public partial class Form1 : Form { Bitmap bmp; public Form1() { InitializeComponent(); bmp = new Bitmap(pB1.Image); } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { Color c = bmp.GetPixel(e.X, e.Y); for (int Y = 0; Y < 280; Y++) { for (int X = 0; X < 240; X++) { Color c2 = bmp.GetPixel(X, Y); if (c.R == c2.R && c.G == c2.G && c.B == c2.B) { bmp.SetPixel(X, Y, Color.FromArgb(0, 0, 255)); } } } } } } クリックしたところと同じ色を青(0, 0, 255)に変更したいのですが変更されません。 間違っているところなどがあれば教えてください。

  • インデックスが配列の境界外です。と出てしまいます。

    C#で、HLS色空間による2値化などを利用した顔領域検出のプログラムを作っています。 文献を参考にプログラミングし、エラーも出なかったのですが… デバックすると、 f[i, j] = 0;のところで「インデックスが配列の境界外です。」と言われてしまいます。 何故なのか、どなたか教えてください。 よろしくお願いします。 --------------------プログラムの一部-------------------- public double minHue, maxHue;//肌色領域(色相) public double minSat, minLight;//肌色領域(彩度、明度) public void BinaryHue(Bitmap bmp0, int[,] f, bool flagBinaryDisp ) { int i, j, nx, ny, gray; double rr, gg, bb, c1, c2; double light, hue, saturation; Color col; nx = bmp0.Width; ny = bmp0.Height; for (j = 0; j < ny; j++) { for (i = 0; i < nx; i++) { col = bmp0.GetPixel(i, j); //原画像 rr = col.R; gg = col.G; bb = col.B; light = 0.299 * rr + 0.587 * gg + 0.114 * bb; c1 = (rr - light); c2 = (bb - light); hue = calcHue(c1, c2);//C2を基準 if (hue < 0) hue += 360.0; saturation = Math.Sqrt(c1 * c1 + c2 * c2);// / 255.0;//最大値を1 if ((hue >= minHue && hue <= maxHue && saturation > minSat)) { f[i, j] = 1; gray = 255; } else { f[i, j] = 0; gray = 0; } if (flagBinaryDisp) bmp0.SetPixel(i, j, Color.FromArgb(gray, gray, gray)); } } }

  • VB2005での画像処理

    各ピクセルの色情報を取得し,そのままコピーするプログラムです. 同じ大きさのPictureBox1とPictureBox2,それとButton1があります. エラーや警告は出ませんが,Button1をクリックしてもまったく動きません. 最終的にはPictureBox1を画像処理してPictureBox2に結果を表示させたいのですが,そのままコピーも出来ないため原因を探しています. A = picture1.GetPixel(i, j).ToArgb() picture2.SetPixel(i, j, color.FromArgb(A)) ではだめなのでしょうか.ご教授ください. -----以下プログラム------ Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim i As Integer Dim j As Integer Dim A As Integer Dim picture1 As New Bitmap(PictureBox1.Image) Dim picture2 As New Bitmap(PictureBox2.Image) For j = 0 To PictureBox1.Width - 1 For i = 0 To PictureBox1.Height - 1 A = picture1.GetPixel(i, j).ToArgb() picture2.SetPixel(i, j, color.FromArgb(A)) Next Next End Sub

  • C#でピクチャーボックスに文字を描画、出力する方法

    以下のことをやりたいのですが、できなくて困っています。 Microsoft Visual Studio 2010 Expressを使っています。 1、ピクチャーボックスに色画像を表示 2、ピクチャーボックスに文字(説明)も表示 3、その画像を出力 2まではできたのですが、2までできたあとに、プログラムのウインドウ上に他のウインドウ(マイコンピュータやマイドキュメントなど)が表示されたり、プログラムのウインドウを最小化したりして、一度隠れてしまうと文字が消えてしまうようで、画像のみの出力になってしまいました。(画像のみの出力には成功しています) なんとかして出力する方法はないでしょうか。 以下がソースです。よろしくお願いします。 ボタン1 Bitmap bmp6 = new Bitmap(800, 600); int sr, sg, sb, i, j; sr = 100; sg = 100; sb = 100; for (i = 0; i < 40; i++) { for (j = 0; j < 40; j++) { bmp6.SetPixel(i, j, Color.FromArgb(sr, sg, sb)); } pictureBox1.Image = bmp6; } ボタン2 string s1 = "文字"; Font newfont = new Font("MS明朝", 10); pictureBox1.CreateGraphics().DrawString(s1, newfont, Brushes.Blue, 50, 200); ボタン3 pictureBox1.DrawToBitmap(bmp, new Rectangle(0, 0, 800, 600)); bmp.Save(c:\\a.png);

  • プログラム停止について。

    こんばんは。 今作成しているプログラムにout[i][j]という出力用の多次元配列があります。この出力が全て同じになった時、プログラムを停止するようにしたいと思っています。 そこで、以下のような方法を考えました。 for( ; ; ) { //無限ループ flag = 0; for( i = 0; i < 10; i++ ) { for( j = 0; j < 4; j++ ) { System.out.print( out[i][j] ); if( out_sub[i][j] != out[i][j] ) { flag = 1; out_sub[i][j] = out[i][j]; } } System.out.println(); } if ( flag == 0 ) { System.exit(0); } } ですが、これがうまくいかず行き詰っています。 何かいい方法があったらぜひ教えてください。また、間違い等、指摘していただけると助かります。 よろしくお願いします。

    • ベストアンサー
    • Java
  • java

    java プログラミングで3×3の○×ゲームを作りたいのですが、エラーが出てしまいます。 どこに問題があるかわかりません。 教えていただけたら嬉しいです。 長くなってしまいますが、ご了承ください(コメント一部略)。 import java.io.*; // マスにの中身が // 空白: 0 // O : 1 // X : 2 class ox { // 勝敗の判定をするメソッド // 勝敗が付いていなければ0 を // O の勝ちなら1 を // X の勝ちなら2 を // 引き分けなら-1 を // それぞれ返す。 static int judge( int board[][] ) { int i, j, flag; for( i = 0; i < 3; ++i ) { flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[j][i]; // <=> flag = flag & board[j][i] if( flag != 0 ) return flag; } // 縦の列を調べる for( i = 0; i < 3; ++i ) { flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[i][j]; if( flag != 0 ) return flag; } // 左上→右下のナナメ flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[j][j]; if( flag != 0 ) return flag; // 右上→左下のナナメ flag = 1 | 2; for( j = 0; j < 3; ++j ) flag &= board[2-j][j]; if( flag != 0 ) return flag; // まだ置けるマスがあるかの判定 flag = 1; for( i = 0; i < 3; ++i ) { for( j = 0; j < 3; ++j ) flag *= board[i][j]; } // flag != 0 ってことは、置けるマスは無い→勝負が付いた // どちらかが勝ったのなら、上でreturn しているはず // ということで、引き分け if( flag != 0 ) return -1; // 何事もなければ、勝負続行 return 0; } // 番面の様子を表示するメソッド static void show ( int board[][] ) { String display = ""; String masu[] = { " ", "O", "X" }; int i; display += " |1|2|3\n"; for( i = 0; i < 3; ++i ) { display += "-+-+-+-\n"; display += (i+1) + "|" + masu[board[0][i]] + "|" + masu[board[1][i]] + "|" + masu[board[2} System.out.println( display ); } static int isreach( int three[], int turn ) { int i, result; // 各マスの値を2 乗して足し合わせる result = 0; for( i=0; i<3; ++i ) result += three[i]*three[i]; // リーチなら、下の条件を満たすはず if( result == 2*turn*turn ) { for( i=0; i<3; ++i ) if( three[i] == 0 ) break; return i; } return -1; } static int rival( int board[][] ) { int x,y,i,j,n; int three[] = new int[3]; // x, y が未定である事を明示 for( i=0; i<3; ++i ) { for( j=0; j<3; ++j ) three[j] = board[j][i]; 続きは追記にて

  • プログラムを組んだのにエラーが出る!!!

    #include <stdio.h> #include <stdlib.h> #include <math.h> int main(void) { int i, j; int m, flag, count; FILE *fp; if (NULL == (fp = fopen("prime.txt", "w"))) { printf("Cannot open output file\n"); exit(1); } count = 0; for (i = 2; i < 1000; i++) { m =sqrt(i); flag = 1; for (j = 2; j <= m; j++) { if (i % j == 0) { flag = 0; break; } count++; } if (flag) { printf("%4d ", i); fprintf(fp," %4d", i); } } printf("\n乗除回数:%d\n", count); fprintf(fp,"\n乗除回数 %d\n", count); fclose(fp); return 0; } (通常課題2-3 1000以下の正の整数値のうち,素数をすべて計算し,結果をファイルに格納するプログラムを作れ. .また、計算の実行の中で乗除を行った回数もあわせて表示し、ファイルに格納すること 実行結果 2 3 5 7 11 13 17 … 991 997 乗除回数:78022 どこが間違ってるのか指摘してください お願いします!

  • VB.NETにおける二値化処理の高速化

    いつも参考にさせて頂いております。 現在、VB.NET(VS2003/.NET Framework1.1)を使用して画像の二値化処理のプログラムを作成しております。 処理する事は簡単で、ビットマップファイルのRED要素を取り出し、閾値内なら白に変換して二値化するプログラムです。 以下がそのプログラムです。 ----- '変換する前の画像をファイルから読み込む Dim img1 As System.Drawing.Bitmap = New System.Drawing.Bitmap(filepath) '変換後のビットマップ Dim img2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(img1.Width, img2.Height) '二値化処理 Dim b As Byte For i = 0 To img1.Width - 1 For j = 0 To img1.Height - 1 b = img1.GetPixel(i, j).R If b >= 閾値下限 And b <= 閾値上限 Then img2.SetPixel(i, j, Color.White) Else img2.SetPixel(i, j, Color.Black) End If Next Next PictureBox1.Image = img ----- これで処理は出来るのですが、ファイルが大きい場合は、非常に時間が掛かってしまいます。処理速度はCPUの速度にもよると思うのですが、できるだけ高速化したのですが、何かよい知恵があればご教授頂けると助かります。よろしくお願いいたします。 XP Pro SP2/VS2003/VB.NET/.NET Framework1.1