ビットマップ画像の色取得

このQ&Aのポイント
  • WinXPでVC++2008ExpressEditionを使用してWinアプリケーションで画像処理をしようとしています.ビットマップのカラー画像を二値化(閾値判別分析法)するために,各色の抽出してグレースケール化を試みているのですが,エラーがとれないので,ご助言いただけたらなと思います.
  • ファイルを開くダイアログを表示し、選択した画像ファイルをピクチャーボックスに表示します.その後、ビットマップ画像の色を抽出し、グレースケール化します.
  • 質問者は、ビットマップ画像のカラー画像を二値化(閾値判別分析法)するために、各色の抽出してグレースケール化を試みているが、エラーが発生している。具体的なエラーメッセージやソースコードも提示されている。エラーの原因を特定し、修正する方法を教えてほしいという相談です。
回答を見る
  • ベストアンサー

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

ビットマップ画像の色取得のご相談 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; } }

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

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

>/*この辺がエラーの原因だと思うのですが・・・*/ >color1 = bmp->GetPixel(i,j); 判ってんなら、何で気付かない? ループ変数をiとjじゃなく、yとxに書き変えてみれば、自分の愚かさに気付けると思うよ。 以下、ループ変数を書き換えたソース // 赤,緑,青成分の抽出 for( y = 1; y < 480; y++)//Y方向 //何で1から始めてるのか知らんが放置 { for( x = 1; x < 640; x++)//X方向 //何で1から始めてるのか知らんが放置 { ////////////////////////////////////////////// /*この辺がエラーの原因だと思うのですが・・・*/ color1 = bmp->GetPixel(y,x); R = color1.R; G = color1.G; B = color1.B; Image_in[y][x][0] = R; Image_in[y][x][1] = G; Image_in[y][x][2] = B; } } //RGB to Gray カラー画像をグレースケール化 for( y = 0; y < 480; y++)//Y方向 { for( x = 0; x < 640; x++)//X方向 { Y = 0.299*Image_in[y][x][0] + 0.587*Image_in[y][x][1] + 0.114*Image_in[y][x][2]; Gray[y][x] = Y; } } どう?気付いた? 気付けない場合は color1 = bmp->GetPixel(y,x); の行を「声に出して100回読んで」みよう。 それで解らなければ、BitmapオブジェクトのGetpixel()メソッドの関数仕様書を「声に出して100回読んで」みよう。 あと「ループ変数にi,jを使う」などと言うアフォな慣例には従わないこと。 変数に「X座標」とか「Y座標」とかの意味があるなら、変数名は「x」とか「y」とかにするべき。 本当は「PixelPosX」とか「PixelPosY」とか、見て解る名前にすんのが良いけどね。

kanemaru_okweb
質問者

お礼

chie65535さま 懇切丁寧に教えて頂きまして誠にありがとうございました.また些細なことでお聞きして申し訳ございませんでした.無事グレースケール化することができました.

その他の回答 (1)

回答No.1

どういうサイズの画像を処理しているのでしょう? ソースコードからは横480×縦640の画像を処理しているように見えますが、読み込んだ画像のサイズがこれと違う(例えば横640×縦480)画像サイズなら、ピクセルの指定範囲が画像の範囲を飛び出すのでエラーが発生します。

kanemaru_okweb
質問者

お礼

magicalpassさま ご指摘いただきまして誠にありがとうございます.画像処理は横640×縦480でした・・・この部分でも勘違いをしておりました.本当にありがとうございました.

関連するQ&A

  • 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ビット画像をファイルに出力 */ }

  • GDIによるメモリ上からの画像データ読み込みに関して

    開発環境はVC++/CLIです。 アンマネージ型のCOMオブジェクトの扱いで困っております。 JPEGやPNGなどの画像データを保存したunsigned char型配列から、Gdiplus::Bitmap型を作ろうとしています。 unsigned int imagesize; // 画像のバイト数が格納されている array<unsigned char>^ image = gcnew array<unsigned char>(imagesize); //画像のデータが格納されている 事前にこのようなデータを用意し、以下のように記述しました。 HGLOBAL hResourceBuffer = GlobalAlloc(GMEM_MOVEABLE , imagesize); void* pResourceBuffer = GlobalLock(hResourceBuffer); CopyMemory(pResourceBuffer, &image, imagesize); IStream* pIStream = NULL; CreateStreamOnHGlobal(hResourceBuffer, TRUE, &pIStream) data->bmp = new Gdiplus::Bitmap(pIStream); pIStream->Release(); GlobalUnlock(hResourceBuffer); GlobalFree(hResourceBuffer); しかしながら、上記のコードだと、CopyMemory時に「保護されたメモリに書き込もうとした」といったエラーが発生します。 Webで色々検索しましたが、全て似たような記述で動作していました。 何が問題なのでしょうか? 尚、上記と同様の画像データ配列を使って、System::Drawing::Bitmap型に格納したとき、画像が正常に表示されることを確認しております。 画像のバイト数に於いても取得したデータに間違いはなく、やはりメモリ関連の問題だと思うのですが…。 MemoryStream^ memst = gcnew MemoryStream(image); Bitmap^ bmp = gcnew Bitmap(memst); memst->Close(); Graphics^ im = pictureBox1->CreateGraphics(); im->DrawImage(bmp, 0, 0, 100, 100); delete bmp;

  • 配列を使ったビットマップクラス

    VC++を使ったフォームアプリケーションでビットマップなどの画像を表示させ、ピクセル処理を施せるプログラムを作りました。このプログラム上ではピクチャボックスを1つ用意していますが、今後もっと多くのピクチャボックスが必要になってきます。以下のプログラムではBitmapクラスのbmpをピクチャボックス1の画像に入れています。単純にBitmapクラスのbmpを増やせば(例:bmp1)、ピクチャボックスが増えても平気ですが、処理の関係上配列を使いたいと思っています。なので下に書いてあるプログラムのbmp->という部分をbmp[0]->というふうに変えたいと考えています。自分なりに調べて(1)、(2)の部分を変えればいいと思うのですがどうもうまくいきません。わかる方がいたらご教授ください、おねがいします。 #pragma once namespace bmp { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::Text; using namespace System::Collections::Generic; /// <summary> /// Form1 の概要 /// /// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた /// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを /// 変更する必要があります。この変更を行わないと、 /// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、 /// 正しく相互に利用できなくなります。 /// </summary> public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // bmp = nullptr; ……… (1) //Bitmap^ bmp[300]; }      //省略// #pragma endregion //private: array<Bitmap^>^ bmp = gcnew array<Bitmap^>(300); ……… (2) private: Bitmap^ bmp; private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { bmp = gcnew Bitmap("C:/Documents and Settings/Owner/デスクトップ/lena.bmp",true); pictureBox1->Image = bmp; } private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) { /*bmp = gcnew Bitmap("C:/Documents and Settings/Owner/デスクトップ/lena.bmp",true);*/ int x,y; int w = bmp->Width; int h = bmp->Height; for(x = 0; x < w; x++){ for(y = 0; y < h; y++){ if(x < (w * 0.05) || y < (h * 0.05) || (y > (h - (h*0.05)))&&(y < h) || (x > (w - (w*0.05)))&&(x < w)){ Color pixelColor = bmp->GetPixel( x, y ); Color newColor = Color::FromArgb( 255, 0, 0 ); bmp->SetPixel( x, y, newColor ); } } } pictureBox1->Image = bmp; } private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { } }; }

  • 画像の一部を出力

    2次元配列image[][]に入っている画像の、ある点(X、Y)を始点として、縦10、横20の部分のみをファイルに出力したいのですが、 for(i=X;i<X+10;i++){ for(j=Y;j<Y+20;j++){ fwrite(&image[i][j], sizeof(unsigned char), 1, fpo); } } としたところ、なにやら変な画像が出力されていました。 何か考えられる原因がありますでしょうか?

  • 二つの画像を並べて表示

    ひとりで独学でVC++2005を勉強してるのですが、pictureBoxでつまずいます。初心者ですがわかりやすく教えて頂けたらと思います。 やりたい事はタイトル通り、画像を単純に並べて表示したいだけなのですが、WEB場で検索しても的を得た答えが見つかりませんでした。 二つの画像を読み込んで、新しいBitmapデータに書き込めばいいのかと思ったのですが、どうやっていいのか見当が付きません。 Bitmap^ bmpA = gcnew Bitmap("testAA.bmp"); Bitmap^ bmpB = gcnew Bitmap("testAB.bmp"); int w = bmpA->Width + bmpB->Width; int h = bmpA->Height + bmpB->Height; Bitmap^ bmp = gcnew Bitmap(w,h); //ここで何やっていいかわかりません。 pictureBox1->Image = bmp; 最終的にはタイル的にどんどん並べて行きたいと考えています。 助言の方よろしくお願いします。

  • ビットマップを直接編集して背景画像を波打たせる

    質問(1) pixelsは一次元配列で1ラインのx方向の要素を左方向や右方向にシフト量sだけ離れた所へコピーすることにより1ラインの画像のピクセルデータをシフト量sだけずらして波打たせる効果を持たせていることは想像つきますが、これではy方向を考慮した全てのラインをずらすことにはなっていない様な感じがします。y方向はどうなっているのですか? 質問(2) int line = y*bmpdata.Stride/4;で4で割っているのは何故ですか? 質問(3) if(s<0){ //左へコピー for(int x=-s; x<BITMAP_W; x++){ if(x+s>=0){ pixels[line+x+s] = pixels[line+x]; } } } でこのif文の中の条件式x+s>=0はint x=-s;→int x+s=0;…;x++により明らかに常に真ではないですか?もし、そうだとしたらこのif文は必要ないのではないですか? 質問(4) } else if(s>0){ //右へコピー for(int x=BITMAP_W; x>=s; x--){ if(x+s<BITMAP_W){ pixels[line+x] = pixels[line+x-s]; } } } } でこのif文の中の条件式x+s<BITMAP_Wの意味が良く分かりません。 質問(5)(6)(7) for(int y=0; y<BITMAP_H; y++){ … int line = y*bmpdata.Stride/4;の意味が良く分かりません。質問(5) … pixels[line+x+s] = pixels[line+x];でlineを加えているのは何故ですか?質問(6) … pixels[line+x] = pixels[line+x-s];でlineを加えているのは何故ですか?質問(7) C言語、C++言語初心者なので分かりやすく教えて下さい。 宜しくお願いします。 プログラムコード(animation.cpp) //ウェーブエフェクト UINT g_wavecount; const int BITMAP_H = 480; const int BITMAP_W = 320; float g_wavelines[BITMAP_H]; //ウェーブエフェクト初期化 void ResetWave(){ g_wavecount = 0; float r=0, rdelta=3.14f/12;//波の数 float waveh = 3;//波の高さ for(int i=0; i<BITMAP_H; i++){ g_wavelines[i] = sinf(r) * waveh; r += rdelta; } } //ウェーブエフェクト描画 void RenderWave(Gdiplus::Bitmap *bmp){ g_wavecount++; int topline = g_wavecount % BITMAP_H; //ビットマップのロック Gdiplus::BitmapData bmpdata; Gdiplus::Status status = bmp->LockBits( &Gdiplus::Rect(0,0,320,480), Gdiplus::ImageLockModeWrite, bmp->GetPixelFormat(), &bmpdata); if(status != Gdiplus::Ok) return; UINT* pixels = (UINT*)bmpdata.Scan0; //←この行から下のコードが全部分からない。 //ビットマップを加工する for(int y=0; y<BITMAP_H; y++){ //シフト量を取得 int s = (int)g_wavelines[(topline+y)%BITMAP_H]; int line = y*bmpdata.Stride/4; //ピクセルコピー if(s<0){ //左へコピー for(int x=-s; x<BITMAP_W; x++){ if(x+s>=0){ pixels[line+x+s] = pixels[line+x]; } } } else if(s>0){ //右へコピー for(int x=BITMAP_W; x>=s; x--){ if(x+s<BITMAP_W){ pixels[line+x] = pixels[line+x-s]; } } } } bmp->UnlockBits(&bmpdata); }

  • 行毎の黒のドット(ピクセル)数を教えていただけませんか?

    開発環境Microsoft Visual Studio .NET 2003 2値画像を読み込んだ時、各行毎の黒のピクセル(ドット)数を表示する プログラムを組もうとしているのですがわかりません。 画像読み込みまではできたのですがその後のプログラムがわかりません 誰か組んでいただけないでしょうか? #include <stdio.h> #include <process.h> #define Y_SIZE 3648 // 処理できる最大画像 #define X_SIZE 3648 #define HIGH 255 // 画像の最大強度値 #define LOW 0 // 画像の最小強度値 #define LEVEL 256 // 画像の強度レベル値 // BMPファイルのフォーマットに従って用意した変数 typedef unsigned short WORD; typedef unsigned long DWORD; WORD bfType; DWORD bfSize; WORD bfReserved1, bfReserved2; DWORD bfOffBits; DWORD biSize, biWidth, biHeight; WORD biPlanes, biBitCount; DWORD biCompression, biSizeImage, biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant; unsigned char image_in[Y_SIZE][X_SIZE][3]; // 入力カラー画像配列 unsigned char image_out[Y_SIZE][X_SIZE][3]; //出力カラー画像配列 unsigned char image_bw[Y_SIZE][X_SIZE]; //濃淡画像配列 unsigned char data_rgb[Y_SIZE][X_SIZE][3]; // RGB画像配列 //******************************************** // 24Bitビットマップファイル読み込み * //******************************************** void readBMP( char *filename, // BMPファイル名 unsigned char image[Y_SIZE][X_SIZE][3] // 24ビットRGB画像配列 ) { FILE *fp; int i, j, k; // ファイルオープン if ((fp = fopen(filename, "rb"))==NULL) { printf("readBmp: Open error!\n"); exit(1); } printf("input file : %s\n", filename); // ヘッダー情報読み込む fread(&bfType, sizeof(bfType), 1, fp); fread(&bfSize, sizeof(bfSize), 1, fp); fread(&bfReserved1, sizeof(bfReserved1), 1, fp); fread(&bfReserved2, sizeof(bfReserved2), 1, fp); fread(&bfOffBits, sizeof(bfOffBits), 1, fp); fread(&biSize, sizeof(biSize), 1, fp); fread(&biWidth, sizeof(biWidth), 1, fp); fread(&biHeight, sizeof(biHeight), 1, fp); fread(&biPlanes, sizeof(biPlanes), 1, fp); fread(&biBitCount, sizeof(biBitCount), 1, fp); fread(&biCompression, sizeof(biCompression), 1, fp); fread(&biSizeImage, sizeof(biSizeImage), 1, fp); fread(&biXPelsPerMeter, sizeof(biXPelsPerMeter), 1, fp); fread(&biYPelsPerMeter, sizeof(biYPelsPerMeter), 1, fp); fread(&biClrUsed, sizeof(biClrUsed), 1, fp); fread(&biClrImportant, sizeof(biClrImportant), 1, fp); // RGB画像データ読み込む for (i=0; i<(int)biHeight; i++) for (j=0; j<(int)biWidth; j++) { for (k=0; k<3; k++) { //fread(&image[i][j][2-k], 1, 1, fp); fread(&image[biHeight-i][j][2-k], 1, 1, fp); } } fclose(fp); } //********************************************** // RGBカラー画像を256諧調白黒濃淡画像へ変換 * //********************************************** void BMPto256BW( unsigned char image[Y_SIZE][X_SIZE][3], unsigned char image_bw[Y_SIZE][X_SIZE] ) { int y, x, a; for (y=0; y<(int)biHeight; y++) for (x=0; x<(int)biWidth; x++) { a = (int)(0.3*image[y][x][0] + 0.59*image[y][x][1] + 0.11*image[y][x][2]); if (a<LOW) a = LOW; if (a>HIGH) a = HIGH; image_bw[y][x] = a; } } //***************************************** //各行の黒色判定 //***************************************** //**************************************** // 白黒濃淡画像配列のコピー * //**************************************** void imageCopyBW( unsigned char image1[Y_SIZE][X_SIZE], unsigned char image2[Y_SIZE][X_SIZE] ) { int x, y; for (y=0; y<(int)biHeight; y++) for (x=0; x<(int)biWidth; x++) image2[y][x] = image1[y][x]; } void main(void) { char input[100], output[100]; int intensity; printf("入力画像ファイル名(*.bmp):"); scanf("%s", input); readBMP(input, image_in); // 画像の入力,RGB24ビットカラーBMP画像を配列に格納 //一列各行の黒色の数出力 }

  • カラー画像からグレースケール画像フォーマットの変換

    カラー画像からグレースケール画像フォーマットの変換するプログラムなんですが、いまいち理解できていません。 プログラムはRGB構造体を使ってのものなんですが添削お願いいたします。 #include<stdio.h> #include<stdlib.h> typedef struct _RGB { unsigned char r; unsigned char g; unsigned char b; } RGB; int main(int argc, char *argv[]) { int x, y; unsigned char *in, *out; int i, j, Magic, level; unsigned char tmp[255]; RGB **pixels; int width = 255; int height = 255; int size = width * height; FILE *fin, *fout; if(argc != 3){ printf("Usage : %s input outpu \n", argv[0]); exit(1); } fin = fopen(argv[1], "rb"); fgets(tmp, 255, fin); if(tmp[0] != 'P'){ return 0; } sscanf(tmp, "P%d", &Magic); if(Magic < 1 || Magic > 6){ return 0; } do{ fgets(tmp, 255, fin); } while(tmp[0] == '#'); sscanf(tmp, "%d %d", &x, &y); if(x < 1 || y < 1){ return 0; } fgets(tmp, 255, fin); sscanf(tmp, "%d", &level); printf("P%d\n", &Magic); printf("%d %d\n", x, y); printf("%d\n", level); in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in, sizeof(unsigned char), x*y, fin); pixels = (RGB**)malloc(width*sizeof(RGB*)); pixels[0] = (RGB* )malloc(size * sizeof(RGB)); for(i = 1; i < width; i++){ pixels[i] = pixels[i - 1] + height; } free(pixels[0]); for(i = 1; i < width * height * 3; i++){ out[i] = pixels[i][0].r * 0.299 + pixels[i][1].g * 0.587 + pixels[i][2].b * 0.114; } fout = fopen(argv[2], "wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); free(pixels); free(in); free(out); free(fin); free(fout); }

  • らべリnグについての質問です

    数字が書かれた画像を2値化し、ラベリングして数字だけを抜き出して出力したいのですが、どうも上手くいきません。 色々試しても見たのですが、数字だけを取り出すことはできませんでした。 以下のプログラムのどこを直せば、ラベリングされた画像を抜き出すことができるのでしょうか? 一週間やってもできませんでした… 何方か教えて下さると大変助かります #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define Y_SIZE 512 //縦の最大画素数 #define X_SIZE 512 //横の最大画素数 #define HIGH 255 //最大階調値 #define LOW 0 //最小階調値 #define Level 256 #define FileName 256 #define MaxBufferSize 640 #define L_BASE 100 #define Black 1 #define White 2 unsigned char image[Y_SIZE][X_SIZE]; //入力画像用配列 unsigned char label_image[Y_SIZE][X_SIZE]; unsigned char image_h[Y_SIZE][X_SIZE]; int x_size, y_size; int Label=200; long hist[256]; void set(unsigned char image[Y_SIZE][X_SIZE], int xs, int ys, int label); void save(unsigned char output_img[Y_SIZE][X_SIZE],int output_ysize,int output_xsize); void load(void) { 入力画像 } void hist1(unsigned char image_in[Y_SIZE][X_SIZE], int x, int y, long hist[256]) { ヒストグラム処理 } void hist2(long hist[256], unsigned char image_h[Y_SIZE][X_SIZE]) { ヒストグラムを画像化 } void thr(unsigned char image_in[Y_SIZE][X_SIZE], unsigned char image_out[Y_SIZE][X_SIZE], int thresh, int type) { 閾値処理 閾値180 タイプ白 } 画像のラベリング処理 int labeling(unsigned char image_in[Y_SIZE][X_SIZE], unsigned char image_label[Y_SIZE][X_SIZE]) { int i, j, label; for (i = 0; i < Y_SIZE; i++) for (j = 0; j < X_SIZE; j++) image_label[i][j] = image_in[i][j]; label = L_BASE; for (i = 0; i < Y_SIZE; i++) for (j = 0; j < X_SIZE; j++) { if (image_label[i][j] == HIGH) { if (label >= HIGH) return -1; set(image_label, j, i, label); label++; }} return label - L_BASE; } 連結している画素すべてにラベル付け void set(unsigned char image[Y_SIZE][X_SIZE], int xs, int ys, int label) { int i, j, cnt, im, ip, jm, jp; image[ys][xs] = label; while(1) { cnt = 0; for (i = 0; i < Y_SIZE; i++) for (j = 0; j < X_SIZE; j++) if (image[i][j] == label) { im = i-1; ip = i+1; jm = j-1; jp = j+1; if (im < 0) im = 0; if (ip >= Y_SIZE) ip = Y_SIZE-1; if (jm < 0) jm = 0; if (jp >= X_SIZE) jp = X_SIZE-1; if (image[i ][jp] == HIGH) { image[i ][jp] = label; cnt++; } if (image[im][jp] == HIGH) { image[im][jp] = label; cnt++; } if (image[im][j ] == HIGH) { image[im][j ] = label; cnt++; } if (image[im][jm] == HIGH) { image[im][jm] = label; cnt++; } if (image[i ][jm] == HIGH) { image[i ][jm] = label; cnt++; } if (image[ip][jm] == HIGH) { image[ip][jm] = label; cnt++; } if (image[ip][j ] == HIGH) { image[ip][j ] = label; cnt++; } if (image[ip][jp] == HIGH) { image[ip][jp] = label; cnt++; } } if (cnt == 0) break; } save(image,ys,xs); } //ラベリング画像の出力 void save(unsigned char output_img[Y_SIZE][X_SIZE],int output_ysize,int output_xsize) { char f_name[FileName]; FILE *fp; int i, j,n; printf("Output File (*.pgm) : "); scanf("%s",f_name); fp = fopen(f_name, "wb"); fputs( "P5\n", fp ); fputs( "# Created by Image Processing\n", fp ); fprintf( fp, "%d %d\n", output_xsize, output_ysize ); fprintf( fp, "%d\n", HIGH); 画像データの出力 for (i=0; i<output_ysize; i++) for (j=0; j<output_xsize; j++) fputc(output_img[i][j], fp); fclose(fp); } int main(void){ int thresh=180, type=White; 入力画像 load(); ヒストグラム処理 hist1(image, x_size, y_size, hist); ヒストグラム画像化 hist2(hist,image_h); 閾値処理 thr(image, image_h, thresh, type); labeling(image_h, label_image); return 0; }

  • 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ファイルは壊れないのですが、ぐちゃぐちゃの絵になります) その理由もわかりません。 汚い文章&プログラムですが よろしくお願いします><