VBAで画像処理

このQ&Aのポイント
  • VBAを使用してExcelで画像処理を行う方法を教えてください。
  • Excelのセルに画素情報を読み込む方法を教えてください。
  • C言語で作成されたプログラムをExcel VBAで変換し、画像の鏡映変換を行いたいです。
回答を見る
  • ベストアンサー

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

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

  • ベストアンサー
  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.1

BMPを読み込むVBAコードは、何日か前に本サイトに投稿されていたと思いますが、既に時の流れの中に埋没していて、ちょっと探してみましたが、見つけられませんでした。 ちょうど、白黒画像の黒画素数を数えたいと思っていたところなので、昔作った(切り貼りした?)コードを引っ張りだしてみました。ご要望とは異なりますが、GDI+のラッパー?クラスを用いる方法です。R, G, Bを別々のワークシートに書き出しています。 詳細はこちらをご参照下さい。 http://www.f3.dion.ne.jp/~element/msaccess/AcTipsFrmGdiClass.html クラスはこちらからダウンロードして下さい。コメントはフランス語ですが(^^;)中身は自由に見られます。 'http://arkham46.developpez.com/articles/office/clgdiplus/ 'Le module clGdiPlus au format cls pour toutes versions d'Office.v2.0 (11/01/11)をダウンロードして解凍 'Excelにインポート 'インポートされたクラスの頭の方の、#Const Access = True -> False に 'Microsoft Forms 2.0 Object Libraryに参照設定 Sub test() Dim clGdip As ClGdiPlus Dim retBool As Boolean Dim lPixels() As Byte Dim lCptX As Long, lCptY As Long Dim colorRed As Long, colorGreen As Long, colorBlue As Long Dim OpenFileName As Variant Dim srcfile As String Dim bufR As Variant, bufG As Variant, bufB As Variant Dim xSize As Long, ySize As Long OpenFileName = Application.GetOpenFilename("画像ファイル,*.jpg;*.bmp;*.png") If OpenFileName <> False Then srcfile = OpenFileName Else Exit Sub End If ActiveSheet.Cells.Clear Application.ScreenUpdating = False Set clGdip = New ClGdiPlus retBool = clGdip.OpenFile(srcfile) If Not retBool Then Exit Sub lPixels = clGdip.GetPixels xSize = UBound(lPixels(), 2) ySize = UBound(lPixels(), 3) ReDim bufR(1 To ySize, 1 To xSize) ReDim bufG(1 To ySize, 1 To xSize) ReDim bufB(1 To ySize, 1 To xSize) For lCptX = 1 To xSize For lCptY = 1 To ySize colorBlue = lPixels(1, lCptX, lCptY) bufB(lCptY, lCptX) = colorBlue colorGreen = lPixels(2, lCptX, lCptY) bufG(lCptY, lCptX) = colorGreen colorRed = lPixels(3, lCptX, lCptY) bufR(lCptY, lCptX) = colorRed '色成分 不透明度 = lPixels(4, lCptX, lCptY) '無視 'ActiveSheetのセルに読み込んだ色をつけます。xl2007以降対応です。 'これを生かすととても時間がかかります。コーヒーでも飲みながら待て! 'Cells(lCptY, lCptX).Interior.Color = RGB(colorRed, colorGreen, colorBlue) Next lCptY Next lCptX With Worksheets(1) .Range(.Cells(1, 1), .Cells(ySize, xSize)).Value = bufR End With With Worksheets(2) .Range(.Cells(1, 1), .Cells(ySize, xSize)).Value = bufG End With With Worksheets(3) .Range(.Cells(1, 1), .Cells(ySize, xSize)).Value = bufB End With Set clGdip = Nothing Application.ScreenUpdating = True End Sub ファイルに書き出す方もありますが、文字数制限に引っかかりましたので、ご要望が有ればアップします。

Kokorochaniuna
質問者

お礼

回答ありがとうございました。感激しています。 '色成分 不透明度 = lPixels(4, lCptX, lCptY) を有効にすると、「関数が定義されていない」 というメッセージが出る以外は今のところ概ね 良好のようです。 これで、生画像の取得が出来るようになりましたが、 さらにエクスポートの方法 が判るととうれしいです。続きのコードをいただけると嬉しいです。 よろしくお願いします。 【補足】 以下、のちに見る人の参考のため補足します。 (1)Microsoft Forms 2.0 Object Libraryの出し方 通常は、 [ツール]-[マクロ]-[Visual Basic Editor]-[ツール]-[参照設定]-[Microsoft Forms 2.0 Object Library] で出るようですが、私の環境(Excel2010)ではなかったようです。 ただ、挿入メニューからユーザーフォームを挿入すると、見つかりました。 <http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1113418901> <http://www.moug.net/faq/viewtopic.php?t=62876> (2)クラスモジュールのインポート法 http://officetanaka.net/excel/vba/tips/tips112c.htm

Kokorochaniuna
質問者

補足

【その他の補足事項】 後に見る人のために、「お礼」でつけた補足に加え、さらに補足をつけます。 (1)test1のソースで Cells(lCptY, lCptX).Interior.Color = RGB(colorRed, colorGreen, colorBlue) のみを有効にすると、取り込んだ画像の各ピクセルごとの色を シート1上に表示できるようになりました。 i5を搭載するPCで、675 KBのBMPを用いて前記操作を行った場合、2~3秒で 所望の処理が出来ました。但し、古いPCだと、やはり5分程度かかるようです。 (2)当たり前のことではありますが、xlsで横方向256ピクセル以上の 画像を、test1で開こうとすると、 「実行時エラー’1004’ アプリケーション定義またはオブジェクト定義のエラーです。」 が出ます。 デバックすると、 .Range(.Cells(1, 1), .Cells(ySize, xSize)).Value = bufR がエラーとしてひっかかりますが、要はExcelの列数制限の問題です。 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1410808914 xlsmは、セキュリティー云々に関したMSの責任逃れ警告 があるので、デフォルトをxlsにしている人も多いかと思いますので ご注意ください。 尚、EXCEL2007で、「一度xls型式で作成したものを、 保存時にxlsmで保存した場合」でも、前記のエラーが出る 場合がありました。この場合は、一度xlsmファイルを終了して Excelを再起動すれば、問題なく動作しています。ご報告まで。 (3)白黒画像(カラー画像をイルファンビューでグレースケールに変換したもの) を、読み込んだ場合エラーになるかなと思いましたが、特に問題なく ひらけているようです。理由はよくわかりません。

その他の回答 (2)

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.3

#2です。 確かにコードをこちらから貼り付け戻して実行すると再現されます。 よくよくコードを見ると、 下から8行目が、意図せずコメントアウトされてしまっているので、こちらを生かして下さい。 ' clGdip.SetPixels lPixels 回答のテキストボックス内で小手直ししている際にゴミが残ってしまった様です。 悩ませてしまって申し訳ありませんでした。

Kokorochaniuna
質問者

お礼

以下のコードでうまくいきました(といっても言われた通りの修正をしただけですが)ありがとうございました。 Sub test2() Dim clGdip As ClGdiPlus Dim retBool As Boolean Dim lPixels() As Byte Dim lCptX As Long, lCptY As Long Dim destfile As String Dim ImageWidth As Long, ImageHeight As Long Dim vntFileName As Variant Dim pictType As String Dim bufR As Variant, bufG As Variant, bufB As Variant Dim targetRange As Range Const jpegQuality As Long = 90 Set targetRange = Worksheets(1).Range("A1").CurrentRegion ImageWidth = targetRange.Columns.Count ImageHeight = targetRange.Rows.Count bufR = targetRange.Value bufG = Worksheets(2).Range(targetRange.Address).Value bufB = Worksheets(3).Range(targetRange.Address).Value vntFileName = _ Application.GetSaveAsFilename(InitialFileName:="Picture.jpg" _ , FileFilter:="画像ファイル,*.jpg;*.bmp;*.png" _ , FilterIndex:=1 _ , Title:="保存先の指定" _ ) If vntFileName <> False Then Select Case StrConv(Right(vntFileName, 3), vbUpperCase) Case "JPG" pictType = "JPG" Case "BMP" pictType = "BMP" Case "PNG" pictType = "PNG" Case Else MsgBox "サポートされていない画像形式です" Exit Sub End Select destfile = vntFileName Else Exit Sub End If Set clGdip = New ClGdiPlus ' 新しいビットマップを作成 幅、高さ、解像度(デフォルト96) retBool = clGdip.CreateBitmap(ImageWidth, ImageHeight, 96) lPixels = clGdip.GetPixels For lCptX = 1 To UBound(lPixels(), 2) For lCptY = 1 To UBound(lPixels(), 3) lPixels(1, lCptX, lCptY) = bufB(lCptY, lCptX) lPixels(2, lCptX, lCptY) = bufG(lCptY, lCptX) lPixels(3, lCptX, lCptY) = bufR(lCptY, lCptX) lPixels(4, lCptX, lCptY) = &HFF Next lCptY Next lCptX clGdip.SetPixels lPixels If pictType = "JPG" Then retBool = clGdip.SaveFile(destfile, "JPG", jpegQuality) Else retBool = clGdip.SaveFile(destfile, pictType) End If Set clGdip = Nothing End Sub

Kokorochaniuna
質問者

補足

教えていただいた方法、大変素晴らしいです。 2次元FFTとか、あるいは二次元データの処理とかは Excelで普通に出来ましたが、画像に吐き出したり 画像を取り込んだりすることについて言及した本は 知る限りないです。 是非書籍として出していただきたいぐらいの内容です。 本当にありがとうございました。

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.2

#1です。ご要望に応じてファイルに書き出すコードを提示します。ご参考まで。 なお、不透明度はPNGでないと意味をなさないかと思いますが、試していません。 Sub test2() Dim clGdip As ClGdiPlus Dim retBool As Boolean Dim lPixels() As Byte Dim lCptX As Long, lCptY As Long Dim destfile As String Dim ImageWidth As Long, ImageHeight As Long Dim vntFileName As Variant Dim pictType As String Dim bufR As Variant, bufG As Variant, bufB As Variant Dim targetRange As Range Const jpegQuality As Long = 90 Set targetRange = Worksheets(1).Range("A1").CurrentRegion ImageWidth = targetRange.Columns.Count ImageHeight = targetRange.Rows.Count bufR = targetRange.Value bufG = Worksheets(2).Range(targetRange.Address).Value bufB = Worksheets(3).Range(targetRange.Address).Value vntFileName = _ Application.GetSaveAsFilename(InitialFileName:="Picture.jpg" _ , FileFilter:="画像ファイル,*.jpg;*.bmp;*.png" _ , FilterIndex:=1 _ , Title:="保存先の指定" _ ) If vntFileName <> False Then Select Case StrConv(Right(vntFileName, 3), vbUpperCase) Case "JPG" pictType = "JPG" Case "BMP" pictType = "BMP" Case "PNG" pictType = "PNG" Case Else MsgBox "サポートされていない画像形式です" Exit Sub End Select destfile = vntFileName Else Exit Sub End If Set clGdip = New ClGdiPlus ' 新しいビットマップを作成 幅、高さ、解像度(デフォルト96) retBool = clGdip.CreateBitmap(ImageWidth, ImageHeight, 96) lPixels = clGdip.GetPixels For lCptX = 1 To UBound(lPixels(), 2) For lCptY = 1 To UBound(lPixels(), 3) lPixels(1, lCptX, lCptY) = bufB(lCptY, lCptX) lPixels(2, lCptX, lCptY) = bufG(lCptY, lCptX) lPixels(3, lCptX, lCptY) = bufR(lCptY, lCptX) lPixels(4, lCptX, lCptY) = &HFF Next lCptY Next lCptX ' clGdip.SetPixels lPixels If pictType = "JPG" Then retBool = clGdip.SaveFile(destfile, "JPG", jpegQuality) Else retBool = clGdip.SaveFile(destfile, pictType) End If Set clGdip = Nothing End Sub

Kokorochaniuna
質問者

お礼

回答ありがとうございます。残念ながら、今のところトラぶっています。 画像の保存作業それ自体は、やっているようなのですが、 エクスポートされる画像は、空の画像です。 フォーマットがjpgの場合でもbmpの場合でもそうなります。 真っ黒な数キロバイトの画像が作成されます。

関連するQ&A

  • 画像処理について・・・・・・・・・・・

    #include<stdio.h> #include<stdlib.h> #define X_SIZE 512 #define Y_SIZE 512 unsigned char DATA[Y_SIZE][X_SIZE]; unsigned char O_DATA[Y_SIZE][X_SIZE]; char input_file_name[256]=”Lenna.raw”; char output_file_name[256]=”Lenna_out.raw”; void heikin(){ int x,u; int temp; for(y=1;y<Y_SIZE-1;y++){ for(x=1;x<X_SIZE-1;x++){ temp=・・・・・・・・・・・・・・・・・・・・・・・・; O_DATA[x][y]=(unsigned char)temp; } } } Int main (){ FILE*fp; If((fp=fopen(input_file_name,”rb”))==NULL){ Printf(“ファイルオ-プンエラ-\n”); Return 1; } Fread(DATA,sizeof(DATA),1,fp); fclose(fp); heikin(); if((fp=fopen(output_file_name,”wb”))==NULL{ printf(“ファイルオ-プンエラ-\n”); return 1; } Fwrite(O_DATA,sizeof(O_DATA),1,fp); Fclose(fp); Return 0; } ソースコードをやっているのですが、後、・・・・・・・・・の所を入力して完成なんですが、苦戦してます。 処理の内容としましては、 1、入力画像Lenna.rawを読み込んで、 2、平均値フィルタをかけ、 3、Lenna_out.rawに書き出す(保存する)したいんですが、公式みたいなのを入れればいいのでしょうか? すみませんが、お願いします。

  • らべリ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; }

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

    開発環境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画像を配列に格納 //一列各行の黒色の数出力 }

  • 3次元配列でのポインタ

    唐突ですみません。 サイズが640*480の画像を180枚読み込むプログラムをポインタを使って作成しようと考えています。 以下で示すプログラムは画像を読み込むための作成したものですが、エラーが出てしまい実行することができません。 間違えている箇所があればご指摘お願いします。 また、そのほかに効率の良いやり方などがありましたらご教授願います。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define xsize 640 #define ysize 480 #define round 180 #include "Input.h" void Input_task(unsigned char ***In); void main() {   static unsigned char ***In;   int i,j;   In=(unsigned char***)malloc(sizeof(unsigned char)*round);   for(i=0;i<round;i++)   {     In[i]=(unsigned char**)malloc(sizeof(unsigned char)*ysize);     for(j=0;j<ysize;j++)     {       In[i][j]=(unsigned char*)malloc(sizeof(unsigned char)*xsize);     }   }   Input_task(In); } Input.hの中身 void Input_task(unsigned char ***In) {   char filename[30];   int i,j,k;   FILE *fp;   for(i=0;i<round;i++)   {     sprintf(filename,"b20_%04d.raw",i);     fp=fopen(filename,"rb");    for(j=0;j<ysize;j++)     {       for(k=0;k<xsize;k++)       {         *(*(*(In+i)+j)+k)=(unsigned char)getc(fp);       }     }    fclose(fp);   } }

  • C言語でbmp モノクロ画像の画像処理を行い、x・y・1or0 をtx

    C言語でbmp モノクロ画像の画像処理を行い、x・y・1or0 をtxtファイルに出力するプログラムを作らないといけないのですが、下記のプログラムのどこをいじればいいかわかりませんだれかお分かりになりませんか? #include <stdio.h> #include <process.h> #define COEF 0.1; #define X_CHORD_Max 512 #define Y_CHORD_Max 512 unsigned long *readBmp(char *filename); main() { unsigned long *pBmp; char input[64], output[64]; int x, y, k,n; char temp; float xCodnt,yCodnt; unsigned long hight, wight; unsigned int maskBit = 0x0080; /* Record the data*/ printf("Input file.bmp :"); scanf("%s", input); printf("output file.txt :"); scanf("%s", output); FILE *fpTxt; if((fpTxt=fopen(output,"wt"))==NULL) { printf("Cannot open file strike any key exit!"); getch(); exit(1); } pBmp = readBmp(input); /* Read the Data*/ hight = *(pBmp+1); wight = *pBmp/32; pBmp += 2; for (y=0;y<hight; y++) { for (x=0; x<wight; x++) { for (k=0; k<4; k++) { temp =(char)*pBmp; for (n=0; n<8; n++) { if(temp & maskBit) { xCodnt = COEF; yCodnt =COEF; xCodnt = xCodnt*(x*32+k*8+n); yCodnt = yCodnt*y; fprintf(fpTxt,"G01 X%f Y%f\n",xCodnt,yCodnt); } maskBit >>= 1; } *pBmp >>= 8; maskBit = 0x0080; } pBmp ++; } } rewind(fpTxt); fclose(fpTxt); //END

  • とあるプログラムを教えてほしいのですが

    はじめましてこんばんは hommado と申します。 じつは先週の授業でこんな問題を出されたんですがもしできたらとあるプログラムを教えてほしいのです。 問題は 「キーボードから何階調にするのかを読み込むことで、入力画像LAX.bmpを任意の階調数に変換する」という プログラムです。 一応下に素体のプログラムをおいたんで、其のプログラムに何か付け足す感じでお願いします。「/*******↓基本的には、この範囲に画像処理プログラムを書く****/」から 「 /********↑**************************************************/」の中にプログラムを書くかんじなのでもし分かったら教えてください。お願いします。 あと何か他の所に付け足すようなところがあったら教えてください ここから元のプログラム // Bitmapファイルを読み込んで, // 別のファイルに出力するだけのプログラムです #include<stdio.h> #define XSIZE 256 /* 画像の横サイズ*/ #define YSIZE 256 /* 画像の縦サイズ*/ void main(void) { int x,y; char fni[40],fno[40]; /* 入力ファイルと出力ファイルの名前を格納するための配列*/ unsigned char head[1078],buf[YSIZE][XSIZE]; /* 入力ファイル(ビットマップファイル)のヘッダ情報と輝度値情報を格納するための配列*/ unsigned char in_image[YSIZE][XSIZE]; /* 入力画像の画素の輝度値を格納するための配列*/ unsigned char out_image[YSIZE][XSIZE]; /* 出力画像の画素の輝度値を格納するための配列*/ FILE *fp,*fp2; /* ファイルポインタ*/ printf("ファイル名を入れてください:"); scanf("%s",fni); fp=fopen(fni,"rb"); /* 読み込み& バイナリモードでオープンする*/ /* 配列head にビットマップファイルのヘッダ情報が格納されます*/ fread(head,sizeof(unsigned char),1078,fp); /* unsigned char 型のデータ×個を配列head に読み込む*/ /* 配列buf にビットマップファイルの輝度値情報が格納されます*/ fread(buf,sizeof(unsigned char),XSIZE*YSIZE,fp); for(y=0;y<YSIZE;y++){ for(x=0;x<XSIZE;x++){ in_image[y][x]=buf[y][x]; /* 画像の左下の画素が座標buf[0][0] です*/ } } printf("読み込み終了しました!\n"); printf("出力ファイル名を入れてください:"); scanf("%s",fno); /*******↓基本的には、この範囲に画像処理プログラムを書く****/       ここにプログラムを書いてください!      (もしここ以外で、他の所で付け足すプログラムがあったら何行目に       何を書くのかも教えてください) /********↑**************************************************/ fp2=fopen(fno,"wb"); /* 書き込み& バイナリモードでオープンする*/ /* 配列head の内容を出力ファイルに書き込む*/ fwrite(head,sizeof(unsigned char),1078,fp2); /* 配列out_image の内容を出力ファイルに書き込む*/ fwrite(out_image,sizeof(unsigned char),XSIZE*YSIZE,fp2); fclose(fp); /* ファイルをクローズする*/ fclose(fp2); /* ファイルをクローズする*/ printf("作業完了!\n"); }

  • SDKにてRAW画像(ヘッダ情報0)の表示

    現在RAW画像(ヘッダ情報0)の表示プログラムをSDKにて作成中です。 色々と細かな質問に対してお答えいただいた皆様に感謝します。 おかげで一応表示することができました。 しかし新たな疑問が出てきてしまいました。 詳しく説明します。 まず入力画像情報をグローバルな構造体により管理するため、 typedef struct{ unsigned char *Input_Image; int Width; int Height; HWND hwnd; char szFileName[MAX_PATH]; char szFileTitle[MAX_PATH]; LPBITMAPINFO lpBitmapInfo; HANDLE hMemBitmapInfo; HANDLE hMemInput_Image; int flag; }IMAGEINFORMATION; static IMAGEINFORMATION *Image; このように定義しました。 ちなみにこの構造体メンバの最初のメンバ*Input_Imageは入力画像が格納するポインタです。今回の問題に対しこの*Input_Imageメンバのみ注意をお願いします。 画像入力処理として Image->hMemInput_Image = GlobalAlloc(GHND, sizeof(unsigned char) * Image->Height * Image->Width); Image->Input_Image = (unsigned char *)GlobalLock(Image->hMemInput_Image); により画像情報のポインタをImage->Input_Imageに格納します。 しかし入力した情報をそのまま使用すると、表示した場合に上下さかさまに反転して表示されてしまうので、この後に画像情報の反転処理を行わなければなりません。この反転処理を行う関数をvoid ReverseBitmap(unsigned char *)として、内容を次に示します。 void ReverseBitmap(unsigned char *Input) {   int i, j, width, height;   unsigned char temp;   width = Image->Width-1;   height = Image->Height-1;   for(i=0; i<=height; i++){     for(j=0; j<=width; j++){       temp = Input[width * (height - i) + j];       Input[width * (height - i) + j] = Input[width * i + j];       Input[width * i + j] = temp;     }   } } 関数実行の記述は  ReverseBitmap(Image->Input_Image);  のように行いました。 これにより反転した配列が ReverseBitmap関数の引数に格納されていると考えたのですが、結果は反映されていませんでした。 結果として色々と試してみたのですが、どうやってもさかさまのまま表示されてしまいます。 関数への引数の渡し方、反転の仕方に問題があるようならアドバイスをお願いします。 そして、反転処理を記述した場合、2次元画像を1次元配列で操作するのは結構めんどくさいです。なのでこの上の定義をもとに、反転処理を2次元配列にて行うような方法はないでしょうか? こちらの疑問もよろしくお願いします。

  • 平均値フィルタについて・・・・・・・・

    #include<stdio.h> #include<stdlib.h> #define X_SIZE 512 #define Y_SIZE 512 unsigned char DATA[Y_SIZE][X_SIZE]; unsigned char O_DATA[Y_SIZE][X_SIZE]; char input_file_name[256]=”Lenna.raw”; char output_file_name[256]=”Lenna_out.raw”; void heikin(){ int x,u; int temp; for(y=1;y<Y_SIZE-1;y++){ for(x=1;x<X_SIZE-1;x++){ temp=・・・・・・・・・・・・・・・・・ ; O_DATA[x][y]=(unsigned char)temp; } } } Int main (){ FILE*fp; If((fp=fopen(input_file_name,”rb”))==NULL){ Printf(“ファイルオ-プンエラ-\n”); Return 1; } Fread(DATA,sizeof(DATA),1,fp); fclose(fp); heikin(); if((fp=fopen(output_file_name,”wb”))==NULL{ printf(“ファイルオ-プンエラ-\n”); return 1; } Fwrite(O_DATA,sizeof(O_DATA),1,fp); Fclose(fp); Return 0; } 自分でプログラムを作って練習しているのですが、このソースコードで入力画像を読み込んで、平均値フィルタをかけ、Lenna_out.rawに書き出そうとしているのですが、・・・・・・の箇所には公式を当てはめていけばいいんでしょうか?? すみませんがよろしくお願いします。。。。。。

  • 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以下にすると正常に変換できなくなります。 どなたか原因がお分かりでしたらお知らせ願えないでしょうか?

  • ラベリング処理プログラム

    画像のラベリング処理プログラムを作っているんですが どうもうまく実行できません。よければ教えていただけないでしょうか。 #include<stdio.h> #include<stdlib.h> int column, row; unsigned char val[4] = {0,0,0,0}; unsigned char tmp[255]; int pos_y[4] = {-1, 0, 1, 0}; int pos_x[4] = {0, 1, 0, -1}; int i, j, x, y, label, level, label1; int label_count = 1; unsigned char *in, *out; void labeling_main(); void labeling_search(); void labeling_main() { for(i = 0; i < y; i++){ for(j = 0; j < x; j++){ printf("aaa\n"); if(out[i * x + j] == 255){ printf("bbb\n"); fflush(stdout); out[i * x + j] = label_count; labeling_search(label_count, i, j); label_count++; } } } } void labeling_search(int label_count, int x, int y) { for(i = 0; i < 4; i++){ if(out[(pos_y[i] + y) * x + (pos_x[i] + x)] == 255){ out[(pos_y[i] + y) * x + (pos_x[i] + x)] = label_count; labeling_search(label_count,(pos_y[i]+y),(pos_x[i]+x)); } } printf("ccc\n"); } int main(int argc, char *argv[]) { int result; int head, Magic; unsigned char *image, *in, *out, *res, *ros; FILE *fin, *fout; if(argc!=3){ printf("Usage : %s input output\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); 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); out = (unsigned char *)malloc(sizeof(unsigned char) *x*y); //2値画像 for (i = 0; i < y; i++) { for (j = 0; j < x; j++){ if(in[i * x + j] > 120){ out[i * x + j] = 0; }else if(in[i * x + j] <= 120){ out[i * x + j] = 255; } } } labeling_main(); printf("Max label number:%d\n",label_count); free(in); free(out); fclose(fin); fclose(fout); } コンパイルは通るのですが実行するとlabeling_mainの if文でセグメンテーションが出てしまいます。

専門家に質問してみよう