• 締切済み

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

noname#126775
noname#126775

みんなの回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.2

>分かりにくくて申し訳ないですが、よろしくお願いします。 「画像・・」は度外視していますので、以下の投稿は、はずしてるかも知れません。 あしからず。 >連続した画像(01.bmp 02.bmp ・・・・100.bmp)を読み込み メインで、「ファイル名」を作り、  char cIN_name[ 64 ], cOUTname[ 64 ];  for( i = 1; i < 100; i++ ){    sprintf( cIN_name, "D:/work/%02d.bmp", i ); // 数字2桁    sprintf( cOUTname, "D:/work/image%02d.bmp", i );    JyoukinoSyori( cIN_name, cOUTname );  }  JyoukinoSyori( "D:/work/100.bmp", "D:/work/image100.bmp" ); // 数字3桁 } 「上記の処理をする」部分を関数として、該当するファイル名部分を直す。    readBMP( &bmp_oj, cIN_name );    ・    writeBMP( bmp, cOUTname ); ところで、readBMP, writeBMP 関数に、fclose(); があるんですよね・・。 蛇足 ファイル名の数字部分が、全て3桁(001.bmp 002.bmp ・・・・100.bmp)であれば(にできれば)、ちょっとだけシンプルにできたかと。 というか、100 まででよかった。

  • chie65535
  • ベストアンサー率43% (8525/19379)
回答No.1

読み出しから書き込みまでを関数にして、引数にintを渡すようにしましょう。 引数に渡されたintの変数から、読み込みファイル名の文字列「"01.bmp"」などを作るのは出来ますね? 同様に、書き込みファイル名の文字列「"image01.bmp"」などを作るのは出来ますね? それが出来れば、リテラルな文字列の変わりに、作った文字列を使ってファイルの入出力は可能ですよね?

関連するQ&A

  • 画像の抽出

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

  • BMPファイルへの書き込みができない

    このプログラムは、左半分を黒、右半分を白の画像をBMPファイルに出力しようとしています。(出来ていません) プログラムの下に質問書いてます!お願いします! #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct{ char *filename; int x; int y; int width; int height; unsigned char data[80][100]; } BMP_DATA; static void WriteBmp(char *filename, BMP_DATA Image) { unsigned long Bmp_size;/*BMPファイルのサイズ*/ unsigned int Bmp_info_header_size;/*情報ヘッダのサイズ*/ unsigned int Bmp_header_size;/*ヘッダのサイズ*/ long Bmp_width;/*幅*/ long Bmp_height;/*高さ*/ unsigned short Bmp_planes;/*プレーン数*/ unsigned short Bmp_color;/*色 = 1[bit] (黒か白かだけ)*/ long Bmp_image_size;/*画像部分のサイズ*/ long Bmp_xppm;/*水平解像度*/ long Bmp_yppm;/*垂直解像度*/ int i,j; unsigned char Bmp_headbuf[54]; /*ヘッダ*/ unsigned char Bmp_Data[13]; FILE *Out = fopen(filename, "wb"); if(Out==NULL){ fclose(Out); exit(1); } /* ヘッダ情報の準備 */ Bmp_info_header_size = 40; Bmp_header_size = 54; Bmp_planes = 1; Bmp_color = 1; Bmp_image_size = Image.height * Image.width; Bmp_xppm = 0; Bmp_yppm = 0; Bmp_size = Bmp_image_size + Bmp_header_size; Bmp_headbuf[0] = 'B'; Bmp_headbuf[1] = 'M'; memcpy(Bmp_headbuf+2, &Bmp_size, sizeof(Bmp_size)); Bmp_headbuf[6] = 0; Bmp_headbuf[7] = 0; Bmp_headbuf[8] = 0; Bmp_headbuf[9] = 0; memcpy(Bmp_headbuf+10, &Bmp_header_size, sizeof(Bmp_header_size)); Bmp_headbuf[11] = 0; Bmp_headbuf[12] = 0; Bmp_headbuf[13] = 0; memcpy(Bmp_headbuf+14, &Bmp_info_header_size, sizeof(Bmp_info_header_size)); Bmp_headbuf[15] = 0; Bmp_headbuf[16] = 0; Bmp_headbuf[17] = 0; memcpy(Bmp_headbuf+18, &Image.width, sizeof(Bmp_width)); memcpy(Bmp_headbuf+22, &Image.height, sizeof(Bmp_height)); memcpy(Bmp_headbuf+26, &Bmp_planes, sizeof(Bmp_planes)); memcpy(Bmp_headbuf+28, &Bmp_color, sizeof(Bmp_color)); memcpy(Bmp_headbuf+34, &Bmp_image_size, sizeof(Bmp_image_size)); memcpy(Bmp_headbuf+38, &Bmp_xppm, sizeof(Bmp_xppm)); memcpy(Bmp_headbuf+42, &Bmp_yppm, sizeof(Bmp_yppm)); Bmp_headbuf[46] = 0; Bmp_headbuf[47] = 0; Bmp_headbuf[48] = 0; Bmp_headbuf[49] = 0; Bmp_headbuf[50] = 0; Bmp_headbuf[51] = 0; Bmp_headbuf[52] = 0; Bmp_headbuf[53] = 0; /* ヘッダ情報書き出し */ fwrite(Bmp_headbuf, sizeof(unsigned char), Bmp_header_size, Out); /* 画像データ書き出し */ for(i=0;i<13;i++) Bmp_Data[i] = 0; for(i=0; i<Image.height; i++){ for(j=0; j<Image.width; j++){ int index = j/8; if(j%8 == 0){ Bmp_Data[index] = Image.data[i][j ] * 128 + Image.data[i][j+1] * 64 + Image.data[i][j+2] * 32 + Image.data[i][j+3] * 16 + Image.data[i][j+4] * 8 + Image.data[i][j+5] * 4 + Image.data[i][j+6] * 2 + Image.data[i][j+7]; } } Bmp_Data[12] = (Bmp_Data[12] & 0xf0); fwrite(Bmp_Data, sizeof(unsigned char), 20, Out); /* ○ */ } fclose(Out); } int main() { BMP_DATA Image; int line = 0; int i,j; Image.x = 0; Image.y = 0; Image.width = 100; Image.height = 80; if(line == 0){ for(i=0; i<Image.height; i++){ for(j=0; j<Image.width; j++){ Image.data[i][j] = 1; } } } while(1){ /* BMPファイルデータを編集 */ for(j=0; j<Image.width; j++){ if(j < 50){ Image.data[line][j] = 0;//black }else{ Image.data[line][j] = 1;//white } } /* すべての列を編集したら、再描画する */ if(line == 63){ /* BMPファイルに書込む */ WriteBmp("display.bmp", Image); break; } line++; } return 0; } 以下の条件で、BMPファイルへ書き込もうとしています ・色の深さ1(黒か白) ・画像のピクセルサイズ(横100×縦80) fwrite関数で1列ずつ書き込もうとしているのですが、 この関数は1バイトずつしか書き込めないみたいで、100ビット書き込もうと思うと、 最低でも104ビット書き込まなくてはならない状況になります。 まず、この4ビットはどう処理すればいいのでしょうか?? あと、display.bmpのファイルがある状態で、プログラムを実行するとちゃんと動くのですが、 プログラム中の○のところのfwrite関数の第三引数を13にすると、BMPファイルが壊れて閲覧できなくなります。(ある程度大きい数字だと、BMPファイルは壊れないのですが、ぐちゃぐちゃの絵になります) その理由もわかりません。 汚い文章&プログラムですが よろしくお願いします><

  • BMPファイルの輝度を配列で表す

    はじめての投稿です。よろしくお願いします。 ただいまC++でBMPファイル処理の勉強をしています。わからないところがBMPファイル(480×640)を読み込みその画像の輝度を配列(480×640)でテキストファイルに書き込みたいのですが、途中から配列がずれてしまいます。 各ピクセルからRGB値を読み込み輝度yを求めてるのですが、最初にBMPファイルのヘッダーを読み込んでしまってるんでしょうか?どなたかご教授お願いします。プラットフォームはWin32です。 以下にソースコードを載せます。 #include <stdio.h> #include <stdlib.h> #include <windows.h> #pragma warning( disable : 4996 ) #pragma warning( disable : 4244 ) #pragma warning( disable : 4700 ) int main(void){ BITMAPFILEHEADER BmpHead = { 0 }; int R, G, B, y; FILE *fpi, *fpy; /* y値出力のオープン */ if((fpy=fopen("test.txt", "a")) == NULL){ fprintf(stderr, "output file open error\n"); exit(1); } /*画像の読込*/ if((fpi = fopen("filename.bmp","rb")) != NULL ){ fread( &BmpHead, sizeof(BmpHead), 1, fpi ); fseek( fpi, BmpHead.bfOffBits, SEEK_SET ); int h,l; static int matrixy[480][640]; //画像のサイズ480×640 for(h=0;h<480;h++){ for(l=0;l<640;l++){ B = fgetc(fpi); G = fgetc(fpi); R = fgetc(fpi); y=0.298912*R+0.586611*G+0.114478*B; /*輝度の算出*/ fprintf(fpy,"%f,",y); } fprintf(fpy,"\n"); } } fclose(fpy); fclose(fpi); } よろしくお願いします。

  • 画像のRGBの値

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

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

    ビットマップ画像の色取得のご相談 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値の取得について(java)

    お世話になります。 Javaプログラム上で、指定した画像のRBG値を取得するプログラムを作りましたが、得られた値が思わしくありません。最終的にグレースケール化するためにRGB値を取得したいと考えています。 例えば、原画像の左上の画素のRGB値をgimpで確認すると、それぞれ200前後の値が、プログラムで返された値は50前後になってしまいます。 以下にソースを貼ります。とりあえず、100個の画素のRGB値を取得するように設定しています。まだjavaを勉強し始めて日が浅く、低レベルの質問かもしれませんが、解決策を教えていただける方、よろしくお願いいたします。 import java.io.*; import java.lang.*; import java.awt.*; import java.awt.color.ColorSpace; import java.awt.event.*; import javax.swing.*; import javax.imageio.ImageIO; import javax.media.*; import javax.media.control.*; import javax.media.format.*; import javax.media.util.*; import java.awt.image.*; import java.applet.*; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import java.io.File; import java.io.IOException; import java.util.*; import java.text.*; public class Sample{ static BufferedImage image; public static void main(String[] args){ try { //画像ファイルのデータを読み込む image = ImageIO.read(new File("C:\\QR\\imagefile\\sa.bmp")); } catch (Exception e) { e.printStackTrace(); image = null; } int i,j; int width = image.getWidth(); int height = image.getHeight(); int gray[][] = new int[width][height]; for(i = 0;i < 1 ;i++){ for(j = 0;j < 100 ;j++){ int rgb = image.getRGB(j,i); rgb = 0-rgb; int b = rgb%256; System.out.print(" "+b); int g = (rgb/256)%256; System.out.print(" "+g); int r = rgb/256/256; System.out.print(" "+r); gray[j][i] = (int)((0.299*r + 0.587*g + 0.114*b)); } System.out.println(""); } } }

    • ベストアンサー
    • Java
  • VBAで画像処理

    以下のプログラムは、C言語で記載されたプラグラムで、画像に鏡映変換を施すプログラムです。 これを、ExcelVBAでやりたいとおもうのですが、 特に、一度Excelのセルに読みだして、そこで数字を処理してトしたいと考えています。 (単に画像Excelの機能だけをつかってを反転するだけならば、たいしたことではないので 自分で判るのですが、一度配列なりセルに画素情報を読み込む方法は、見当もつかないので 知りたいと思っています。) ということで、特に以下の(1)、(2)に注意して、ExcelVBAで下記のプログラムを変換する方法を教えてください。よろしくお願いします。 (1)特に、以下の部分の記述がどう変化するか、教えてください。 void main(void) { char input[100], output[100]; printf("入力画像ファイル名(input.bmp):"); scanf("%s", input); printf("出力画像ファイル名(output.bmp):"); scanf("%s", output); /* 画像の入力 */ readBmp(input, image_in); /* RGB24ビットカラーBMP画像を配列に格納 */ /* 画像処理 */ mirror(image_in, image_out); /* 鏡像を作る */ /* 画像の出力 */ writeBmp(image_out, output); /* RGB24ビット画像をファイルに出力 */ } (2)特に、一度BMPの画素情報を、Excelのセルに読み込めるようにしていただけると助かります。 ========= #include <stdio.h> #include <stdlib.h> /* 最大画像サイズ */ #define Y_SIZE 1280 #define X_SIZE 1280 /* BMPファイル用 */ typedef short INT2; typedef long INT4; INT2 bfType; INT4 bfSize; INT2 bfReserved1, bfReserved2; INT4 bfOffBits; INT4 biSize, biWidth, biHeight; INT2 biPlanes, biBitCount; INT4 biCompression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant; #define HIGH 255 /* 2値画像の白 */ #define LOW 0 /* 2値画像の黒 */ #define LEVEL 256 /* 濃度レベル数 */ unsigned char image_in[Y_SIZE][X_SIZE][3]; /* 入力カラー画像配列 */ unsigned char image_out[Y_SIZE][X_SIZE][3]; /* 出力カラー画像配列 */ /* 鏡像を作る(左右逆) */ void mirror( unsigned char in[Y_SIZE][X_SIZE][3], unsigned char out[Y_SIZE][X_SIZE][3]) { int i,j,k; for (i=0; i<biHeight; i++) for (j=0; j<biWidth; j++) for (k=0; k<3; k++) out[i][j][k] = in[i][biWidth-1-j][k]; } void main(void) { char input[100], output[100]; printf("入力画像ファイル名(input.bmp):"); scanf("%s", input); printf("出力画像ファイル名(output.bmp):"); scanf("%s", output); /* 画像の入力 */ readBmp(input, image_in); /* RGB24ビットカラーBMP画像を配列に格納 */ /* 画像処理 */ mirror(image_in, image_out); /* 鏡像を作る */ /* 画像の出力 */ writeBmp(image_out, output); /* RGB24ビット画像をファイルに出力 */ }

  • 細線化のプログラム

    細線化のプログラム 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
  • imgctl.dllを使って読み込んだ画像ファイルをTransparentBltで画く方法

    今、LoadImage()で読み込んだBMP画像を BitBlt(hdc,x,y,dx,dy, hMin,0,0,SRCCOPY));や TransparentBlt(hdc,x,y,dx,dy, hMin,0,0,dx,dy,RGB(r,g,b)); で画面に書くCプログラムがあります。このプログラムをBMP画像だけでなくPNG画像も扱えるように拡張しています。いろいろと調べた結果PNG画像を読み込むためにライブラリimgctl.dllを使うプログラムに変更している途中です。しかし、imgctl.dllではLoadImage()の代わりにToDIB()関数で読み込むため、JPEG画像もPNG画像も読めるのですが、独自のDIBデータハンドル(HDIB)で管理するためHDC(デバイスコンテクストハンドル)が取得できません。そのため、 問題1、画面書き出しはBitBlt()が使えない。 問題2、TransparentBlt()関数が使えない。 という問題があります。 問題1は、DIBtoDC()で代用することで、解決しましたが、問題2が未解決です。 お知恵をお貸しください。 たとえば、HDIBからHDCを得る方法、あるいは、特定の色RGB(r,g,b)を透明として扱うTransparentBlt()関数に代わるHDIBを使った関数をお教えいただければうれしいです。

  • dxlib 画像ファイルの読み込み

    DxLibを使って画像を表示しようと思っています。 ・test1.bmp ・test2.bmp ・test3.bmpというファイルを用意して順に表示させたいんですが、 現在では for(int i = 1; i <= 3; i++){   if(i == 1)     LoadGraphScreen( 0 , 0 , "test1.bmp" , TRUE ) ;   if(i == 2)     LoadGraphScreen( 0 , 0 , "test2.bmp" , TRUE ) ;   if(i == 3)     LoadGraphScreen( 0 , 0 , "test3.bmp" , TRUE ) ; } このようになっています。 これを変数の値を用いて表示しようとしているんですがどうにもうまくいきません。 for(int i = 1; i <= 3; i++){   LoadGraphScreen( 0 , 0 , "test" & i & ".bmp" , TRUE ) ; } & を + に変えてもうまく行きませんでした。 何か方法があるのでしょうか? どなたか助言お願いします。