VB2008を用いた画像の抽出

このQ&Aのポイント
  • VB2008を用いて、原画像と原画像に落書きをした画像の2枚を用いて、落書きのみを抽出するプログラムを作成していますが、RGBの演算がうまくできません。
  • コードを確認し、カラーチャネルの計算が正しく行われているかを確認してください。
  • また、値が負の場合に正しく処理されるように条件文を追加しましょう。
回答を見る
  • ベストアンサー

画像の抽出

今、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 などと記載してみたのですが上手くいきませんでした。 どこを修正、加筆すればうまく抽出が出来る様になるのでしょうか。

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

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

こちらに訂正しておきます。 別々に比較せずとも If col1 <> col2 Then bmp3.SetPixel(i, j,col1) End If で落書き部分が抽出できませんか。

zyogee
質問者

お礼

まさに If col1 <> col2 Then bmp3.SetPixel(i, j,col1) End If で落書きの抽出が出来ました。こんな簡単に出来てしまい感動しました!! ご指摘本当にありがとうございました!

その他の回答 (1)

回答No.1

> r3 = r1 - r2   > g3 = g1 - g2 > b3 = b1 - b2 この部分は、何をしておられるのでしょうか? 落書きした点かどうかを調べるのなら、元の画像の色と違う点が 落書きしたところになるのではないですか? R,G,B の値のどれか一つでも違っていたら落書きしたドットとなる。 但し、元の画像と同じ色で落書きした分は、書いた事にはならない。 If (r1 <> r2) or (g1 <> g2) or (b1 <> b2) Then 落書きした箇所 End If

zyogee
質問者

お礼

> r3 = r1 - r2   > g3 = g1 - g2 > b3 = b1 - b2 この部分で落書き箇所以外のRGB値を0にして、落書きのみのRGB値を書き込もうと考えて記述しました。 よくよく考えたらRGBの値で引いても落書きのRGB値は出ませんよね… 勘違いしてました。ありがとうございますm(_ _)m

関連するQ&A

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

    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)); } } }

  • 細線化のプログラム

    細線化のプログラム 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
  • BMP画像ファイルの読み書き

    Visual StudioのC言語により、ビットマップ形式の画像に対するプログラミングで 簡単な背景差分のプログラムを作成しています。 背景画像と対象画像2枚を読み込み色の差を取り、 差の値が背景の値と近ければ背景とみなし白で塗りつぶし、 物体だけを表示した画像を生成するようなプログラムです。 1枚のみの画像は以下のプログラムで作動しますが、連続した画像(01.bmp 02.bmp ・・・・100.bmp) を読み込み上記の処理をする場合にはどうすればよいのでしょうか? 分かりにくくて申し訳ないですが、よろしくお願いします。 #include "BMPData.h" #include <math.h> int main(){ int a=150; int i,j; int r,g,b; int ir,ig,ib; int diff; BMPStruct bmp_bg; BMPStruct bmp_oj; BMPStruct bmp; RGB rgb_bg; RGB rgb_oj; RGB rgb; RGB rgb_w; rgb.r = 255; rgb.g = 255; rgb.b = 255; rgb_w.r = 0; rgb_w.g = 0; rgb_w.b = 0; readBMP(&bmp_bg, "back.bmp"); //背景画像の読み込み readBMP(&bmp_oj, "01.bmp"); //対象画像の読み込み makeBMP(&bmp,640, 480, rgb); //出力用画像を生成する for(i=0; i<640; i++){ for(j=0; j<480; j++){ getColor(bmp_bg, &rgb_bg,i,j);  //背景画像の色を取得 getColor(bmp_oj, &rgb_oj,i,j);  //対象画像の色を取得 //rgbそれぞれの値の差 r = rgb_bg.r - rgb_oj.r; g = rgb_bg.g - rgb_oj.g; b = rgb_bg.b - rgb_oj.b; //絶対値 ir = abs(r); ig = abs(g); ib = abs(b); //色の差 diff = ir + ig + ib; //背景かどうかの判定 if(diff>a){ putColor(bmp, rgb_w, i, j); //色の差が大きければ出力画像に対象画像の色をそのまま出力 } else{ putColor(bmp, rgb, i, j); //色の差が小さければ白を出力 } } } writeBMP(bmp, "image01.bmp"); }

  • c言語による画像処理について

    いつもお世話になってます。 c言語を使った画像処理を学び始めました。 入力画像の白(RGB値255,255,255)以外の画像を黒(RGB値0,0,0) に変換するプログラムを作成したいと思っているのですが、 入力画像の大きさによっては正常に命令を実行してくれないことがあるので、 改善点をご教示いただきたいと考え投稿させていただきました。ソースプログラムは #include<stdio.h> #define nx 100 //画像の幅 #define ny 100 //画像の高さ int main(void) { FILE *fp,*fp2; int i,j; unsigned char header[54]; unsigned char screen[nx][ny][3]; /* ファイルから読む */ fp=fopen("input.bmp","rb"); //ビットマップ形式 ,24ビットカラー fread(header,1,54,fp); // ヘッダ(54バイト)を飛ばす */ fread(screen,1,nx*ny*3,fp); // 残りはデータ(最下行から順に入る) //(255,255,255)以外なら黒(0,0,0)に for(j=0;j<ny;j++) for(i=0;i<nx;i++) if(screen[j][i][0]!=255||screen[j][i][1]!=255||screen[j][i][2]!=255){ screen[j][i][0]=0; screen[j][i][1]=0; screen[j][i][2]=0; } fclose(fp); /* ファイルに書く */ fp=fopen("output.bmp","wb"); fwrite(header,1,54,fp); /* ヘッダ */ fwrite(screen,1,nx*ny*3,fp); /* データ */ fclose(fp); return 0; } となっています。ここで、画像の高さ、幅を100以下にすると正常に変換できなくなります。 どなたか原因がお分かりでしたらお知らせ願えないでしょうか?

  • visual C++  画像処理における質問

    最近visual C++ で画像処理の勉強をしています。 画像濃度の取得で以下の2つの違いがわかりません。 とりあえず(1)を用いたプログラムでは、濃度取得が うまくいきませんでした。初心者ですが御回答の程 を宜しくお願い致します。 (1) col[i][j]=GetPixel(hDC1,i,j); (2) col[i][j]=(short)(GetPixel(hDC1,i,j) & 0xFF);

  • ビットマップ画像の色取得のご相談

    ビットマップ画像の色取得のご相談 WinXPでVC++2008ExpressEditionを使用してWinアプリケーションで画像処理をしようとしています.そこで,現在ビットマップのカラー画像を二値化(閾値判別分析法)するために,各色の抽出してグレースケール化を試みているのですが,色々試したのですがエラーがとれないので,もし間違い等ありましたら,ご助言いただけたらなと思います.何卒よろしくお願いいたします. 【エラー内容】 'System.ArgumentOutOfRangeException' のハンドルされていない例外が System.Drawing.dll で発生しました。追加情報: パラメータは正の値で、高さより小さい値指定しなければなりません。 【流れ】(ボタンを押したら以下三つを実行) 1.ファイルの読み込みピクチャーボックスに表示 2. ビットマップ画像の色の抽出 3. グレースケール化 /*ここから*/ OpenFileDialog^ OpenDlg = gcnew OpenFileDialog; //ファイルを開くダイアログ OpenDlg->Filter ="画像ファイル(*.bmp,*.jpg,*.jpeg,*.png,*.tif,*.tiff,*.ico)|*.bmp;*.jpg;*.jpeg;*.png;*.tif;*.tiff;*.ico"; OpenDlg->ShowDialog(); //ダイアログの表示 if (OpenDlg->FileName == "") { //ファイル名が指定されなかった場合 return; } Bitmap^ bmp; bmp = gcnew Bitmap(OpenDlg->FileName); //Bitmapをファイルより作成 pictureBox1->Image = bmp; //ピクチャボックスへ画像の表示 Bitmap^ bmp1 = gcnew Bitmap(pictureBox1->Image); unsigned char Image_in[480][640][3]; //Image_in[Y][X][3] unsigned char (*Gray)[640] = new unsigned char[480][640]; //(*Gray)[X] = new unsigned char[Y][X] double Y; int i, j; //iがY方向,jがX方向 Color color1; unsigned char R,G,B; // 赤,緑,青成分の抽出 for( i = 1; i < 480; i++) //Y方向 { for( j = 1; j < 640; j++) //X方向 { ////////////////////////////////////////////// /*この辺がエラーの原因だと思うのですが・・・*/ color1 = bmp->GetPixel(i,j); R = color1.R; G = color1.G; B = color1.B; Image_in[i][j][0] = R; Image_in[i][j][1] = G; Image_in[i][j][2] = B; } } //RGB to Gray カラー画像をグレースケール化 for( i = 0; i < 480; i++) //Y方向 { for( j = 0; j < 640; j++) //X方向 { Y = 0.299*Image_in[i][j][0] + 0.587*Image_in[i][j][1] + 0.114*Image_in[i][j][2]; Gray[i][j] = Y; } }

  • 画像のRGBの値

    画像フィルタが必要になり、そのために画像の性質を知るために、画像のRGBの値を直接求めようと思いました。 具体的には、画像ファイル(BMP)があり、その画像の全画素のRGBの値をテキストファイル(CSV形式)に変換したいのです。そのようなツールありますか? 特殊な用途なので、 while(getpixel(r,g,b)) { printf("%d,%d,%d\n",*r,*g,*b); } のようなプログラムを書かないといけないと思うのですが、「BMPファイルの先頭から順番に画素のRGBの値を持ってくる関数getpixel」が書けません。

  • 線形補間法プログラム(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; }

  • VC++ (byte)(col & 0xFF) の意味

    VC++で画像処理のプログラムを作成中です。 ビットマップを読み込み、1ピクセルごとに処理を施すのが目的です。 「デジタル画像処理入門」という本に col = GetPixel(hDC1,i,j); r = (byte)(col & 0xFF); g = (byte)(col/0x100 & 0xFF); b = (byte)(col/0x1000 & 0xFF); というプログラムが載っていました。 ここで、(byte)とはどういう意味なのでしょうか? また、(col & 0xFF)の意味はわかるのですが(col/0x100 & 0xFF)はどういう意味なのでしょうか? 例えば、colの値が0x300(10進数で258)だとすると、 col/0x100=258/256=1 となってしまうと思うのですが。 VC++のヘルプやgoogleで検索してみたのですが、わからなかったので、ここで質問させてもらいました。 お分かりの方、よろしくお願いします。

  • 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)に変更したいのですが変更されません。 間違っているところなどがあれば教えてください。

専門家に質問してみよう