ホワイトバランス補正(program2)

  • 2020.06.28 Sunday
  • 17:32

 カメラのオートホワイトバランスを取っても、全画面のヒストグラムや画面中のグレーを探すなどいろいろなアルゴリズムが存在します。ここでは、RAWExifデータに書かれているホワイトバランスの値からRAWデータにホワイトバランス補正をかけるプログラミングして見ます。

 

ホワイトバランス補正(program2)のプログラミング

 まず、program1とは別のprogram2というフォルダを作り、program1program1.cpp,program1.h,ppm.cpp,ppm.h,Makefileをコピーし、program1.cpp,program1.h, Makefileのファイル名と中身に記述してあるprogram1program2に全て変更します。

 次にprogram2.cpp program2.hを赤字のように変更します。

  ホワイトバランス補正(program2.cpp)​

 ***************************************************/

 

#include "program2.h"

 

/*****************

 * Main function

 *****************/

int main(int argc, char *argv[])

{

 

                   int                                i = 1;

 

                   const char *program_name ="program2";

                   int                                wbbc[6] = {1024, 1024, 1024, 0, 0, 0};                                  // whitebalance[r, g, b, br, bg, bb]

                   char           *file_i = NULL;           // input file

                   char           *file_o = NULL;          // output file

 

                   fprintf(stderr,"<< %s >>¥n", program_name);

                   fprintf(stderr,"2020.01.02 designed by A.Okumura¥n¥n");

 

                   wbbc[0] = ( argc > i )? atoi(argv[i]) : 1024;

                   i++;

                   wbbc[1] = ( argc > i )? atoi(argv[i]) : 1024;

 

                   i++;

 

                   wbbc[2] = ( argc > i )? atoi(argv[i]) : 1024;

                   i++;

                   wbbc[3] = ( argc > i )? atoi(argv[i]) : 0;

                   i++;

                   wbbc[4] = ( argc > i )? atoi(argv[i]) : 0;

                   i++;

                   wbbc[5] = ( argc > i )? atoi(argv[i]) : 0;

                   i++;

 

                   file_i = argv[i++];                           // input file

 

                   file_o = argv[i++];                          // output file

 

                   /***** Main process *****/

                   if (0 != main_process(file_i, file_o, program_name, wbbc)) {

                                     return fprintf(stderr, "¥n! Calculation Failed !¥n¥n");

                   }

                   fprintf(stderr, "¥n!!!!! Calculation Succeeded !!!!!¥n¥n");

 

                   return 0;

}

 

/*****************************************************************

 *  main function of calculation

 *****************************************************************/

int main_process(char *infile, char *outfile, const char *program_name, int wbbc[6])

{

                   int              ppm_pn;

                   int              width, height;

                   int              bits;

                   // ppm header read

                   read_ppm_header(infile, &width, &height, &ppm_pn, &bits);

                   fprintf(stderr, "read ppm header¥n");

 

                   // size set

                   int              datasize = width * height;

 

                   // Memory allocate

                   unsigned short *rdatain = new unsigned short [datasize];

                   unsigned short *gdatain = new unsigned short [datasize];

                   unsigned short *bdatain = new unsigned short [datasize];

                   unsigned short *rdataout = new unsigned short [datasize];

                   unsigned short *gdataout = new unsigned short [datasize];

                   unsigned short *bdataout = new unsigned short [datasize];

 

                   // ppm data read

                   fprintf(stderr, "read ppm¥n");

                   read_ppm(infile, rdatain, gdatain, bdatain, width, height);

 

 

                   // wbalance

 

                   fprintf(stderr, "process¥n");

                   wbalance(rdatain, gdatain, bdatain, rdataout, gdataout, bdataout, width, height, bits, wbbc);

 

                   // ppm write

                   fprintf(stderr, "write ppm¥n");

                   write_ppm(outfile, rdataout, gdataout, bdataout, width, height, ppm_pn, bits, program_name);

 

                   delete [] rdatain;

                   delete [] gdatain;

                   delete [] bdatain;

                   delete [] rdataout;

                   delete [] gdataout;

                   delete [] bdataout;

 

                   return 0;

}

 

/*****************************************************************

 * wbalance

 *****************************************************************/

void wbalance(const unsigned short *rdatain, const unsigned short *gdatain, const unsigned short *bdatain,

                   unsigned short *rdataout, unsigned short *gdataout, unsigned short *bdataout,

                   int width, int height, int bits, int wbbc[6])

{

                   int              hp, vp;

                   int              pos;

                   int              maxlevel = (0x01 << bits) - 1;

 

 

                   for (vp = 0; vp < height; vp++){

 

                                     for (hp = 0; hp < width; hp++){

 

                                                        pos = vp*width + hp;

 

                                                        rdataout[pos] = (unsigned short)clip((rdatain[pos] - wbbc[3]) * wbbc[0]/wbbc[1] + wbbc[3], 0, maxlevel);

                                                        gdataout[pos] = (unsigned short)clip((gdatain[pos] - wbbc[4]) * wbbc[1]/wbbc[1] + wbbc[4], 0, maxlevel);

                                                        bdataout[pos] = (unsigned short)clip((bdatain[pos] - wbbc[5]) * wbbc[2]/wbbc[1] + wbbc[5], 0, maxlevel);

                                     }        // hp loop end

                   }        // vp loop end

 

                   return;

}

 

int clip(int a, int minlevel, int maxlevel)

{

                   int              ans;

                   ans = a;

                   if(ans >= maxlevel) ans = maxlevel;

                   if(ans <= minlevel) ans = minlevel;

                   return       ans;

}

 

/***** End of File (program2.cpp) *****/

 

program2のヘッダーファイル(program2.h

/***************************************************

 * Calculate program2 (header file)

 * @file     program2.h

 * @author Akuhiro Okumura

 * @date    2020.01.02

***************************************************/

 

#pragma once

 

#ifdef LINUX

#else

#pragma warning(disable:4996)   //                 fopen

#endif

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <math.h>

 

/***** prototype *****/

// main process

int main_process(char *infile, char *outfile, const char *program_name, int wbbc[6]);

 

void read_ppm_header(char *file, int *width, int *height, int *ppm_pn, int *bits);

void read_ppm(char *file, unsigned short *r_data, unsigned short *g_data, unsigned short *b_data, int width, int height);

void write_ppm(char *file, unsigned short *r_data, unsigned short *g_data, unsigned short *b_data,

                   int width, int height, int ppm_pn, int bits, const char *program_name);

 

void wbalance(const unsigned short *rdatain, const unsigned short *gdatain, const unsigned short *bdatain,

                   unsigned short *rdataout, unsigned short *gdataout, unsigned short *bdataout,

                   int width, int height, int bits, int wbbc[6]);

 

int clip(int a, int minlevel, int maxlevel);

 

/***** End of File (program2.h) *****/

 

●program2のコンパイル

 必要なファイルが揃ったら次にコンパイルです。

1Ubuntuを起動します。

2Ubuntuのターミナルからディレクトリーを選択し、makeとタイプしてコンパイルします。

$ cd work/../program2

$ ls

Makefile  ppm.cpp  ppm.h  program2.cpp  program2.h

$ make

g++  -O3 -Wall -I/usr/local/include -DLINUX  -c -o program2.o program2.cpp

g++  -O3 -Wall -I/usr/local/include -DLINUX  -c -o ppm.o ppm.cpp

g++  -O3 -Wall -I/usr/local/include -DLINUX -o program2 program2.o ppm.o

$ ls

Makefile  ppm.cpp  ppm.h  ppm.o  program2  program2.cpp  program2.h  program2.o

$

という表示が出て、program2 ppm.o program2.oというファイルが出来ていれば成功です。

 

●program2の実行

 program2のコンパイルが終わったら、実行させます。

1.コンパイルして出来たprogram2workにコピーします。

2exiftoolを使ってホワイトバランスの値を調べます

 RAWファイルをexiftoolにかけて、下のようにRAWExifデータを見ることが出来ます。α7siiの場合は、WB RGGB Levels Autoの項目が、カメラが求めたオートホワイトバランス値、Black Levelがブラックレベルの値となります。

  Exifデータ(ホワイトバランス)

$ cd ../work

$ exiftool DSC00100.ARW

注)ソニーのα7siiで撮影したRAWExifデータです。

3.program2.exe  <WR> <WG> <WB> <BR> <BG> <BB> <変換前の画像名>  <変換後の画像名>⏎とタイプしてプログラムを実行させます。WG,WG,WBはR,G,Bそれぞれのホワイトバランスの値、BR,BG,BBはR,G,Bそれぞれのブラックレベルの補正値を入力します。

$ ./program2.exe 2616 1024 1580 512 512 512 DSC00100.ppm DSC00100_wb.ppm

出力ファイルが出来ていれば、処理終了です。

DSC00100_wb.ppmをビューアーで見てみます。

  ホワイトバランス補正(program2)の処理結果​

赤っぽくなりましたが、これで正解のようです。

 

 この内容は、「Interface誌2020年7月号特集 AI時代の画像処理教科書 第4の記事を、読者の便宜をはかるために加筆修正したものです。(同一内容ではない)、また、ここでのプログラムは、CQ出版社さんのダウンロードページの[7月号 AI時代の画像処理教科書][特集 第4章,第5章 画像処理プログラミング] [関連ファイル一式]からダウンロードできます。

コメント
コメントする








    

calendar

S M T W T F S
   1234
567891011
12131415161718
19202122232425
262728293031 
<< July 2020 >>

selected entries

categories

archives

links

profile

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM