2016. 4.12.
石立 喬

OpenMPとVisual C++による並列処理(7)

――― コントラスト強調では、OpenMPの効果があまりない -----

 画像のコントラストを補正するのに、ガンマ補正またはトーンカーブ補正がある。トーンカーブは、入力濃度と出力濃度をグラフ化したもので、この形状により、いろいろな補正ができる。ここでは、最も良く使われる中濃度の拡張(中間濃度付近で、明るいものはより明るく、暗いものはより暗く分布範囲を広げる)によるコントラスト強調を行う。
 画像の全ピクセルに対して処理を行うので、OpenMPによる並列化に向いていると思って試してみたが、トーンカーブ補正処理が時間のかかる処理でないので、OpenMPの効果があまりなかった。

コントラスト強調と、その並列化
◎トーンカーブ
 「Visual C++ 2010 Expressを用いた易しい画像処理(2)」に詳述したガンマ(Gamma)特性を使用する。ガンマ特性はトーンカーブとも呼ばれ、画像のコントラストを補正する場合の変換特性を表す。
 コントラストを補正したい画像には、
 1)全体に明るく、明部が飛んでしまっている。
 2)全体に暗く、暗部が潰れている。
 3)全体的に明暗差が少なく、メリハリがない。
があるが、1)と2)はカメラの自動露出により、補正を必要とする画像が減少しており、天候などが悪くて生じる3)が多い。
 そこで、ここでは、3)を対象として、中濃度部のコントラスを拡張するトーンカーブを使用する。入力濃度dinと出力濃度doutの変換式には、
    dout = 255 * sin2(π/2 * din / 255)
を用いる。
◎トーンカーブのルックアップテーブル化
 上述のトーンカーブは、多くの乗除算や三角関数を用いるので、その都度計算するには、時間がかかる。そこで、あらかじめ全てのdinに対して計算した結果を、expand_tableと言う配列に格納しておく、ルックアップテーブル方式を使用する。

OpenMPによる実行時間の確認方法
 expandContrast1〜4のユーザ関数を作成し、従来と同様に、これらの関数に要する時間を測定する。
 「Visual C++ 2010 Expressを用いた易しい画像処理(2)」に示したのと同様の方法で、あらかじめ用意された濃度変換テーブルを利用し、原画像のピクセルデータをRGBに分解し、それぞれについて変換テーブルを参照して、新しいRGBを作成し、これをRGBマクロでピクセルデータ化する。
 インライン化しないexpandContrast1関数から、完全にインライン化したexpandContrast4関数まで4種類を用意し、実行時間の違いを調べる。ここで、インラインとは、途中で一旦変数に代入することなく、式または関数を、そのまま別の関数の添字として直接使用し、同じ行に入れてコードを記述することを意味する。

作成したプログラム
 「・・・による並列処理(4)」を基礎にしている。図1に示すように、プロジェクトの最初の部分で、ユーザ関数のプロトタイプを宣言し、図2に示すように、濃度変換ルックアップテーブルexpand_tableを作成している。その他は従来と同じである。
 実行時間測定用の関数をUserProgramから呼び出す方法も、従来と変わらないので、説明は省略する。


図1 プロジェクトの最初の部分でユーザ関数を宣言する



図2 濃度変換ルックアップテーブルexpand_tableを作成する


expandContrast1〜expandContrast4関数
 「Visual C++ 2010 Expressを用いた易しい画像処理(2)」で紹介した方法を、Win32用に書き直したもので、図3〜図5に示す。
 P_SIZEは、画像のWIDTH * HEIGHTを意味する定数で、307,200のかなり大きい値であるので、このforループをOpenMPで並列化する。VC++デフォルトのままで実行する場合には、#pragma文をコメントアウトする。
 ピクセルデータ配列pdataを読み取って処理した結果を、別の配列pdata1に入れるのではなく、元のpdataに戻す方が実行時間が短いのでがないかと考え試みたが、有意な差は見られなかった。


図3 COLORREF型の変数colorを介在させる、最も分かり易い関数



図4 変数colorを用いないで、配列pdataを直接用いる関数



図5 さらにインライン化の度合いを強めた二つの関数


expandContrast1関数の結果
 図6は、Release構成のVC++デフォルト(#pragma文をコメントアウトした)での結果の一例を示す。図7はOpenMPを使用した場合で、VC++デフォルトの場合よりも実行時間が短く、バラツキが減っている。 平均値では、OpenMPの優位性が見られる(VC++デフォルトの200μsecに対して、OpenMPは140μsec)が、良く見ると、繰り返しの最初や途中で、VC++デフォルトには実行時間の長い回が多いのが原因である。VC++でも、OpenMPと同程度の実行速度が得られている場合が多く、これらの理由はわからない。
 図8はDebug構成の結果をまとめたもので、上から順に処理1〜処理4の順になっている。インライン化が進むにつれて、実行時間が短くなっている。VC++デフォルトとOpenMP使用との関係はほとんど変わらない。
 図9はRelease構成の場合を示す。処理1が長く、その他はほぼ同じである。しいて言えば、OpenMP使用の処理2が一番速い。


図6 Release構成のVC++デフォルトで得られた結果の一例、実行時間の長い回が多い



図7 Release構成のOpenMP使用で得られた結果の一例、実行時間が比較的に安定している





図8 Debug構成の結果の一例、処理4が一番速い



図9 Release構成の結果の一例、OpenMP使用の処理2が速い


OpenMPによる実行時間短縮の確認の結果
 結果をまとめると表1のようになり、以下のことが分かる。
 1)Debug構成では、VC++デフォルトでもOpenMP使用でも、インライン化が強まるとともに、実行速度が速くなる。
 2)Release構成では、インライン化を進めても、実行時間があまり変わらない。しいて言えば、OpenMP使用の処理2が速い。
 3)Debug構成でもRelease構成でも、平均的には、OpenMP使用による時間短縮があるが、その理由は、VC++デフォルトに実行時間の長い回が多いためである。

表1 実行時間のまとめ(100回の平均値)



結 論
 コントラスト強調処理の実行時間を、4種類の関数を使って調べた。Debug構成では、VC++デフォルトもOpenMP使用も、インライン化を強化して行くと、次第に実行時間が短くなることが分かった。Repease構成では、変数colorを介在させるする処理1の場合はやや時間がかかったが、その他では、インライン化の程度にかかわらず、ほぼ一定であった。しいて言えば、処理2によるOpenMP使用が早かった。
 今回のコントラスト強調処理では、平均値で見れば、OpenMPによる短縮は70%程度であるが、その改善のほとんどは、VC++デフォルトの場合の変動(実行時間が増える回が多い)がなくなったことによる。その理由については分からない。
 トーンカーブによるコントラストの補正のような、あまり実行時間を要しないような処理には、OpenMPの効果が現れにくいのであろう。









「Visual C++の勉強部屋」(目次)