C/C++のコンパイル方法と基本プログラム(ゲイン補正)の作成

  • 2020.06.27 Saturday
  • 14:36

 ここでは、プログラム演習の基本となる画像ファイルを読み出して、画像処理(ここではゲイン補正)を行い、また画像ファイルに書き出すプログラムを作成します。また、コンパイルに必要なmakeファイルの作成やコンパイラーのインストールなども演習し、コンパイルしたバイナリーの実行まで行います。まずは、windows(またはUbuntumkdir)でprogram1というディレクトリーを以前作ったworkと同列に作り、その中に「PPMフォーマット」で作ったppm.cppppm.hをコピーして入れます。

 

●基本プログラム(ゲイン補正)の記述(program1.cpp)

 続いてmain関数の記述です。ppmフォーマットで入力してゲインx30して、ppmフォーマットに出力するプログラムとヘッダーファイルを書いてみます。メイン関数の中でppmフォーマットの関数を呼び出して使います。

  基本プログラム(ゲイン補正)の記述(program1.cpp

/***************************************************
 * Calculate program1(main file)
 * @file    program1.cpp
 * @brief    in ppm -> program1 -> out ppm
 * @author    Akihiro Okumura
 * @date    2020.01.02
 ***************************************************/

#include "program1.h"

/*****************
 * Main function
 *****************/
int main(int argc, char *argv[])
{
    int        i = 1;
    const char    *program_name ="program1";
    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");

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

    /***** Main process *****/
    if (0 != main_process(file_i, file_o, program_name)) {
        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    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);

    // gain
    fprintf(stderr, "process¥n");
    gain(rdatain, gdatain, bdatain, rdataout, gdataout, bdataout, width, height, bits);

    // 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;
}

/*****************************************************************
 * gain
 *****************************************************************/
void gain(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    hp, vp;
    int    pos;
    int    maxlevel = (0x01 << bits) - 1;
    int    gain = 30;
 
    for (vp = 0; vp < height; vp++){
        for (hp = 0; hp < width; hp++){
            pos = vp*width + hp;
            rdataout[pos] = (unsigned short)clip(rdatain[pos] * gain, 0, maxlevel);
            gdataout[pos] = (unsigned short)clip(gdatain[pos] * gain, 0, maxlevel);
            bdataout[pos] = (unsigned short)clip(bdatain[pos] * gain, 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 (program1.cpp) *****/

 

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

/***************************************************
 * Calculate program1(header file)
  * @file    program1.h
 * @brief    in ppm -> program1 -> out ppm
 * @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);

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 gain(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 clip(int a, int minlevel, int maxlevel);

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

 

●program1のmakeファイルの記述​

 続いてMakefileの記述です。

  program1のMakefile

#
# Makefile
#
# @author    Akihiro Okumura
# @date        2020.01.02
#MACH := $(shell uname -s)

CC = g++
CFLAGS  = -O3 -Wall -I/usr/local/include -DLINUX
HDRS     =
CLIBS   =
CPPFLAGS = $(CFLAGS)

TARGET   = program1
INSTALLDIR = $(HOME)/bin.$(MACH)

all: $(TARGET)

SRCS =     program1.cpp ppm.cpp

OBJS = $(SRCS:%.cpp=%.o)

program1 :  $(OBJS)
     $(CC)  $(CFLAGS) -o $@ $(OBJS) $(LIBS)
     
program1.o :  program1.cpp
ppm.o :  ppm.cpp

clean:
     rm -f $(OBJS)

# end of Makefile

左端から空白のある行は、空白文字ではなく、タブ文字(Tab)なので注意してください。

 

●program1のコンパイル

これで、必要なファイルは全て揃いました。次にコンパイルです。

1Ubuntuを起動します。

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

$ cd work/../program1

$ ls

Makefile  ppm.cpp  ppm.h  program1.cpp  program1.h

$ make

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

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

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

$ ls

Makefile  ppm.cpp  ppm.h  ppm.o  program1  program1.cpp  program1.h  program1.o

$

という表示が出て、program1 ppm.o program1.oというファイルが出来ていれば成功です。エラーが出ている場合は、修正してエラーメッセージが消えてコンパイル出来るまで繰り返します。

 

●program1の実行

 dcrawから出力されたRAWデータにゲイン×30を掛けて見ます。dcrawから出力されるRAWデータはpgmフォーマットで出力されますが、pgmフォーマットで入力して、ppmフォーマットに出力するプログラムはちょっと面倒なので、convertpgmフォーマットからppmフォーマットに変換して使います。ちなみに、convertpgmフォーマットからppmフォーマットへの変換を行うと、グレーの値は、R,G,Bにそれぞれ同じ値がコピーされます。

1.コンパイルして出来たprogram1dcrawで作ったディレクトリー(work)にコピーします。

2Ubuntuのターミナルからディレクトリーを選択し、convertを使ってpgmppmに変換します。

$ cd ../work

$ convert DSC00100.pgm DSC00100.ppm

$ls

DSC00100.pgm

DSC00100.ppm

$

 

3./program1  <変換前の画像名>  <変換後の画像名>とタイプしてプログラムを実行させます。

メッセージが出力されて出力ファイルが出来ていれば、処理終了です。

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

  program1の処理結果

$ ./program1 DSC00100.ppm DSC00100_x30.ppm

<< program1 >>

2020.01.02 designed by A.Okumura

 

input file ("DSC00100.ppm")

Get PPM file infomation(width=4256, heigt=2848, bits=16)

read ppm header

read ppm

process

write ppm

 

!!!!! Calculation Succeeded !!!!!

$ls

DSC00100.ppm

DSC00100_x30.ppm

$

 

 

  元のRAW画像

元ののRAW画像より明るくなっていることが分かります。

 これで基本プログラムのprogram1は完成です。次の演習からは主にこのprogram1をコピーし修正して作成します。

 

 この内容は、「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