画像に埋め込んだ数値を検出する処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ビタミンCC

画像に埋め込んだ数値を検出する処理について

#1

投稿記事 by ビタミンCC » 12年前

こんばんは現在C言語にて画像処理を勉強中の初心者です。
白黒画像のバーコードの画像処理について質問です。

コード:

#include <stdio.h>
#include <process.h>
#include "image.h"
#include "bmp.c"

/* 外部変数 および データ形式について

   biHeight 画像の高さ
   biWidth  画像の幅
   
   画像の配列は
     unsigned char 配列名[Y][X][色] で指定する。
	 座標系 (x,y) の表現方法ではなく、行列 (i, j) のように
	 縦, 横 の順に指定することに注意。
	 
	 色は 0, 1, 2 で表され、 0 が赤, 1が青, 2 が緑

	 Y_SIZE および X_SIZE はこのプログラムで画像サイズの最大値
	 どちらも 512 に設定されている。
	 縦,横のサイズが512を超えた場合のエラー処理は行われていない
	 ので、これらのサイズを超える画像を扱わないよう注意。
*/

unsigned char image_in[Y_SIZE][X_SIZE][3];	/* 入力カラー画像配列 */
unsigned char image_out[Y_SIZE][X_SIZE][3];	/* 出力カラー画像配列 */

void image_copy(
	unsigned char in[Y_SIZE][X_SIZE][3],
	unsigned char out[Y_SIZE][X_SIZE][3])
{
	int i,j,k;
	unsigned char y;
	for (i=0; i<biHeight; i++)
		for (j=0; j<biWidth; j++){
				y=0.212*in[i][j][0] + 0.701*in[i][j][1] + 0.085*in[i][j][2];
				out[i][j][0] = y;
				out[i][j][1] = y;
				out[i][j][2] = y;
		}
}

void makeRGBfromImage(unsigned char image[Y_SIZE][X_SIZE][3] ,
					  double R[Y_SIZE][X_SIZE], 
					  double G[Y_SIZE][X_SIZE],
					  double B[Y_SIZE][X_SIZE])
{
	int i,j;
	for(i=0; i<biHeight; i++)
		for(j=0; j<biWidth;j++){
			R[i][j] = image[i][j][0];
			G[i][j] = image[i][j][1];
			B[i][j] = image[i][j][2];
		}
}

void makeYCCfromRGB(double R[Y_SIZE][X_SIZE], 
					double G[Y_SIZE][X_SIZE],
					double B[Y_SIZE][X_SIZE],
					double Y[Y_SIZE][X_SIZE], 
					double Cr[Y_SIZE][X_SIZE],
					double Cb[Y_SIZE][X_SIZE])
{
	int i,j;
	double center = 128.0;
	for(i=0; i<biHeight; i++)
		for(j=0; j<biWidth;j++){
			Y[i][j] =  0.29900*R[i][j] + 0.58700*G[i][j] + 0.11400*B[i][j];
			Cr[i][j]=  0.50000*R[i][j] - 0.41869*G[i][j] - 0.08131*B[i][j]+center;
			Cb[i][j]= -0.16874*R[i][j] - 0.33126*G[i][j] + 0.50000*B[i][j]+center;
		}
}

void makeRGBfromYCC(double Y[Y_SIZE][X_SIZE], 
					double Cr[Y_SIZE][X_SIZE],
					double Cb[Y_SIZE][X_SIZE],
					double R[Y_SIZE][X_SIZE], 
					double G[Y_SIZE][X_SIZE],
					double B[Y_SIZE][X_SIZE])
{
	int i,j;
	double center = 128.0;
	for(i=0; i<biHeight; i++)
		for(j=0; j<biWidth;j++){
			R[i][j]= Y[i][j] + 1.402 * (Cr[i][j] - center);
			G[i][j]= Y[i][j] - 0.34414 * (Cb[i][j]-center) - 0.71414 * (Cr[i][j] - center);
			B[i][j]= Y[i][j] + 1.772 * (Cb[i][j]-center);

			if (R[i][j]<0) R[i][j]=0;
			if (R[i][j]>255) R[i][j]=255;
			if (G[i][j]<0) G[i][j]=0;
			if (G[i][j]>255) G[i][j]=255;
			if (B[i][j]<0) B[i][j]=0;
			if (B[i][j]>255) B[i][j]=255;
			
		}
}

void makeImagefromRGB(double R[Y_SIZE][X_SIZE], 
					  double G[Y_SIZE][X_SIZE],
					  double B[Y_SIZE][X_SIZE],
					  unsigned char image[Y_SIZE][X_SIZE][3])
{
	int i,j;
	for(i=0; i<biHeight; i++)
		for(j=0; j<biWidth;j++){
			image[i][j][0] = (unsigned char)R[i][j];
			image[i][j][1] = (unsigned char)G[i][j];
			image[i][j][2] = (unsigned char)B[i][j];
		}
}

void GetBarcodeInfo(double Y[Y_SIZE][X_SIZE], int *start_x, int *start_y, int *end_x, int *num_of_blackpixels)
{
	int x,y,i,j;
	double Th = 128.0; /*2値化の際のしきい値 */
	int x_StartPos, y_StartPos,x_EndPos,y_EndPos; /*バーコードが描画されている領域の座標 */
	int num;
	y=0;
	while (y<biHeight){
		x=0;
		while(x<biWidth){
			if (Y[y][x]<Th) break;
			x++;
		}
		if (x < biWidth){
			x_StartPos = x;
			y_StartPos = y;
			break;
		}
		y++;
	}
	if ((x_StartPos==0) && (y_StartPos==0))
	{
		printf("画像中に黒領域が見つかりませんでした");
		exit(-1);
	}
	
	x_EndPos=0;
	while (x<biWidth){
	/*画面右までスキャンして、一番右端の黒のx座標を求める*/
		
		if (Y[y][x] < Th)/* 黒い点であったら */
			x_EndPos=x;
		x++;
	}
	if (x_EndPos==0) {
		printf("	バーコード右端が検出できませんでした\n");
		exit(-1);
	}

	/*バーコード一番上のラインにおける、黒の画素の数を数える*/
	x=y_StartPos;
	y=y_StartPos;
	num=0; //これまでに検出した黒画素の数 
	while(x<=x_EndPos){
		if (Y[y][x] < Th) // 黒い点であったら
			num++; //黒画素数を +1 する
		x++;
	}

    *start_x= x_StartPos;
	*start_y= y_StartPos;
	*end_x = x_EndPos;
	*num_of_blackpixels =num;
}

void Embed_watermark(double Y[Y_SIZE][X_SIZE],double Y_out[Y_SIZE][X_SIZE], 
int sukasi[], int Length, int x_StartPos, int y_StartPos, int x_EndPos)
{
	int x,y;
	int bitnum;
	double Th = 128.0; /*2値化の際のしきい値 */
		
	for(y=0;y<biHeight;y++) //出力データに元データをコピー
		for(x=0;x<biWidth;x++)
			Y_out[y][x]=Y[y][x];
	
	bitnum=0; //現在何番目のbitが埋め込み対象になっているのか
	x=x_StartPos;
	y=y_StartPos;
	
	//埋め込み開始		
	while(x<=x_EndPos){
		if (Y_out[y][x]<Th){ //もし注目点が黒画素なら透かし埋め込み処理を行う
			printf("found! x=%d bitnum=%d\n",x,bitnum);
			if (sukasi[bitnum]==0){ // 「0」を埋め込むなら、該当画素を白くする
				Y_out[y][x]=255;
			}
			bitnum++; //埋め込み対象を次のビットにする
		}
		if (bitnum==Length) // もし全てのビットの埋め込み処理が終了したら
			break;
		x++;
	}
	
	printf("埋め込みが完了しました.埋め込み終了x座標=%d\n",x);

}

void main(void)
{
	int Length = 20; // 埋め込む数値のビット長
	int suchi[]={1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,0,0,1,0}; //埋め込む数値ビット
	char *input="bar.bmp";
	char *output="out.bmp";

/* 画像中のバーコードが書かれている左上端の座標 */
	int x_StartPos;
	int y_StartPos;

	int x_EndPos;//バーコードx座標の終端
	int Num_of_Blacks; //バーコードの横方向の黒画素数(=埋め込めるビット数の上限)
	
/*画像データ*/	
	static	double R[Y_SIZE][X_SIZE];
	static	double G[Y_SIZE][X_SIZE];
	static	double B[Y_SIZE][X_SIZE];
	
	static	double Y[Y_SIZE][X_SIZE];
	static	double Cr[Y_SIZE][X_SIZE];
	static	double Cb[Y_SIZE][X_SIZE];

	static double Y_out[Y_SIZE][X_SIZE];
	int i,j,k;
	
	printf("start");
	/* 画像の入力 */
	readBmp(input, image_in);  /* RGB24ビットカラーBMP画像を配列に格納 */
	/* image_in から RGB成分を取り出す */
	makeRGBfromImage(image_in , R, G, B);
	
	/* RGB成分から Y, Cr, Cb 成分を作成する */
	makeYCCfromRGB(R, G, B,   Y, Cr, Cb);

	/*透かし埋め込みに必要な、バーコードに関する情報(バーコードの開始座標、横方向の黒画素数など) */
    GetBarcodeInfo(Y,&x_StartPos, &y_StartPos, &x_EndPos, &Num_of_Blacks);
	
	printf("バーコード開始座標 x=%d y=%d\n",x_StartPos,y_StartPos);
	printf("バーコード終了x座標=%d\n",x_EndPos);
	printf("一辺あたりの黒画素数の数 = %d\n",Num_of_Blacks);
	if (Num_of_Blacks < Length){
		printf("埋め込みビット数が横方向の黒画素数を超えています。埋め込み不可能\n");
		exit(-1);
	}
	
	Embed_watermark(Y,Y_out, sukasi, Length, x_StartPos, y_StartPos, x_EndPos);
	
	/* 輝度成分から、モノクロの出力画像 image_out を作成 */
	makeImagefromRGB(Y_out, Y_out, Y_out, image_out);
	
	/* 画像の出力 */
	writeBmp(image_out, output);  /* RGB24ビット画像をファイルに出力 */

}
ソースコードでは
白黒のバーコードに対して数値の埋め込みを行っているのですが、
数値を埋め込んだ画像から数値を検出するようにするにはどのように書き換えればいいでしょうか?

よろしくお願いします

ビタミンCC

Re: 画像に埋め込んだ数値を検出する処理について

#2

投稿記事 by ビタミンCC » 12年前

環境を書き込むのを忘れていました
[[1] 質問文
 [1.1] 自分が今行いたい事は何か→埋め込んだ数値を検出したい
 [1.2] どのように取り組んだか→数値を埋め込むプログラムを作成(全て自分でやったわけではない)
 [1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)→[1.1]と同じ
 [1.4] 今何がわからないのか、知りたいのか→[1.1]と同じ

[2] 環境  
 [2.1] OS : Windows, Linux等々→Windows7 CPAD使用
 [2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々→BorlandC++使用

[3] その他
 ・どの程度C言語を理解しているか→構造体程度
 ・ライブラリを使っている場合は何を使っているか→わかりません

授業の先生に教えていただきながら作成したのですが、「埋め込みを行うプログラムができたら数値を検出するのもできるだろう」といわれ困っている状態です。
提出期限の関係で土曜日までには提出したいと思っています。教えていただきたいです

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 画像に埋め込んだ数値を検出する処理について

#3

投稿記事 by みけCAT » 12年前

「数値を検出する」とはどういう処理ですか?
未知の画像が与えられて、そこに数値が埋め込まれているかどうかを調べるプログラムですか?
それとも、今提示されているプログラムで出力された画像が与えられて、そこに埋め込まれている数値を取り出すプログラムですか?
それともその他ですか?
ビタミンCC さんが書きました:提出期限の関係で土曜日までには提出したいと思っています。
グレゴリオ暦の2013年12月21日までという解釈で合っていますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 画像に埋め込んだ数値を検出する処理について

#4

投稿記事 by みけCAT » 12年前

とりあえず、テストしやすいように、適当に作ったimage.hとbmp.cを置いておきます。
添付ファイル
suuti_kensyutu.zip
image.h / bmp.c / bar.bmp など
(17.03 KiB) ダウンロード数: 134 回
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ビタミンCC

Re: 画像に埋め込んだ数値を検出する処理について

#5

投稿記事 by ビタミンCC » 12年前

回答ありがとうございます。
みけCATさんが作成してくださったプログラムのような処理を行いたいと思っています。
画像で説明したほうがわかり易いと思うので説明致します。
まず下の元画像に対してソースコードで示した処理を行います。(A画像)
画像

すると以下のようになります(B画像)
画像


解像度を大きくして変更されている部分を赤く囲んだものがこちらです
[画像

元の画像と加工した画像を見比べて、変わっている場所の画素をみけCATさんに作成していただいたプログラムのように数値で表したいのです。

>グレゴリオ暦の2013年12月21日までという解釈で合っていますか?
はい、そうです

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 画像に埋め込んだ数値を検出する処理について

#6

投稿記事 by みけCAT » 12年前

方針としては、
1. 元画像と数値が埋め込まれた画像のデータを読み込む
2. 元画像のデータを(上のプログラムと同じ方法で)走査する
3. 数値(ビット)を埋め込む位置に来たら、数値が埋め込まれた画像の同じ位置の画素を見て、
違っていれば(特にYの値がThを超えていれば)0が埋め込まれている、そうでなければ1が埋め込まれていると判断する
4. 取得したデータを書き出す

という流れだと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ビタミンCC

Re: 画像に埋め込んだ数値を検出する処理について

#7

投稿記事 by ビタミンCC » 12年前

方針としては、
1. 元画像と数値が埋め込まれた画像のデータを読み込む
2. 元画像のデータを(上のプログラムと同じ方法で)走査する
3. 数値(ビット)を埋め込む位置に来たら、数値が埋め込まれた画像の同じ位置の画素を見て、
違っていれば(特にYの値がThを超えていれば)0が埋め込まれている、そうでなければ1が埋め込まれていると判断する
4. 取得したデータを書き出す

という流れだと思います。
必要領域 画像保持領域A 画像B保持領域 比較結果保持領域
データサイズAB

データサイズ=準備{
準備:データサイズ=ファイルデータサイズの読み込み{}
返り値 準備データサイズ


画像読み込み{
ファイルの読み込み(画像A){ファイル開いて ~ 読み込みで クローズ}
ファイルの読み込み(画像B)
ファイルデータを返す


画像比較{
画像A比較画像B
もし違えばどうするか
結果を返す


結果の書き出し{
ファイルを作成してデータを保存


ひとまず、文字で方針の方を簡単に表してみました。
このような感じでいいんですかね?

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 画像に埋め込んだ数値を検出する処理について

#8

投稿記事 by みけCAT » 12年前

大雑把すぎていいかどうかよくわかりません。
とりあえずあなたの解釈でできるところまで実装してみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 画像に埋め込んだ数値を検出する処理について

#9

投稿記事 by みけCAT » 12年前

最大限に見積もって、提示された期限まであと12時間ほどですね。
http://www.timeanddate.com/worldclock/c ... 399&p2=248
進捗どうですか?頑張ってください。(見ているかわかりませんが)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る