白黒画像のバーコードの画像処理について質問です。
#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ビット画像をファイルに出力 */
}
白黒のバーコードに対して数値の埋め込みを行っているのですが、
数値を埋め込んだ画像から数値を検出するようにするにはどのように書き換えればいいでしょうか?
よろしくお願いします