目的
ここでは、画像の前処理と強調に有用ないくつかの興味深い特性を持つ、人間の網膜モデルを紹介する。このチュートリアルでは次のことを学ぶ:
- 網膜から出力される主要な2つのチャンネルを理解する
- 網膜モデルの基本的な使い方を知る
- いくつかのパラメータ調整を理解する
概要
提案するモデルは、Gipsa における Jeanny Herault の研究 [141] に端を発する。これは Listic 研究室(コードのメンテナンス担当者かつ利用者)における画像処理アプリケーションに関わっている。これは完全なモデルではないが、画像処理の体験を向上させるために活用できる興味深い特性をすでに備えている。このモデルにより、以下のヒト網膜の特性を利用できる:
- スペクトル白色化(spectral whitening)。これには3つの重要な効果がある:高い時空間周波数信号の除去(ノイズ)、中周波数のディテール強調、低周波数の輝度エネルギー低減。このオールインワンの特性により、画像センサや入力輝度範囲がもたらす古典的な望ましくない歪みから、視覚信号を直接クリーニングできる。
- 局所的な対数輝度圧縮により、低照度条件下でもディテールを強調できる。
- ディテール情報(小細胞性出力チャンネル)と過渡情報(イベント、動き。大細胞性出力チャンネルで得られる)の無相関化。
最初の2点を以下に示す:
下図では、OpenEXR の画像サンプルCrissyField.exrというハイダイナミックレンジ画像を示している。このWebページ上で見えるようにするため、元の入力画像は古典的な画像輝度範囲 [0-255] に線形にスケーリングし直され、8ビット/チャンネル形式に変換されている。このような強い変換は、局所コントラストが強すぎるために多くのディテールを隠してしまう。さらにノイズエネルギーも強く、視覚情報を汚染している。
image
次の画像では、[26] で提案されているアイデアを、網膜が行うのと同じように適用すると、局所輝度適応、空間ノイズ除去、スペクトル白色化が協調して働き、より低い範囲の8ビットデータチャンネルに正確な情報を伝える。この画像では、ノイズが大幅に除去され、強い輝度コントラストによって隠れていた局所ディテールが強調されている。出力画像は自然さを保ち、視覚的内容が強調されている。色処理は [70] で提案された色の多重化/分離手法に基づいている。
image
注:画像サンプルは OpenEXR の Web サイトからダウンロードできる。このデモンストレーションに関しては、網膜処理の前に、入力画像はチャンネルの float 形式を保ったまま 0-255 の範囲に線形にスケーリングし直されている。ヒストグラムの両端の5%がカットされている(主に誤った HDR ピクセルを除去するため)。同様の処理についてはサンプルopencv/samples/cpp/OpenEXRimages_HighDynamicRange_Retina_toneMapping.cppを参照のこと。以下のデモンストレーションでは古典的な8ビット/チャンネル画像のみを扱う。
網膜モデルの出力チャンネル
網膜モデルは、上述の振る舞いの恩恵を受ける2つの出力を備えている。
- 1つ目は小細胞性チャンネル(Parvocellular channel)と呼ばれる。主に中心窩網膜領域(色感受性の光受容体を持つ高解像度の中心視)で活動し、その目的は網膜上で静止している視覚的ディテールに対して正確な色覚を提供することである。一方、網膜投影上で動く物体はぼやける。
- 2つ目のよく知られたチャンネルは大細胞性チャンネル(Magnocellular channel)である。主に網膜の周辺視で活動し、変化イベント(動き、過渡的イベントなど)に関連する信号を送る。これらの出力信号は、より詳細な解析のために視覚系が「過渡的」/動いている領域に網膜の焦点を合わせ/中心を置くのを助け、これにより視覚シーンの文脈と物体分類が改善される。
注:提案するモデルに関しては、実際の網膜とは異なり、これら2つのチャンネルを同じ解像度で入力画像全体に適用する。これにより、考慮するすべての画像から強調された視覚的ディテールと動き情報を抽出できる…しかし、これら2つのチャンネルは相補的であることを忘れてはならない。例えば、大細胞性チャンネルがある領域で強いエネルギーを示す場合、そこでは過渡的イベントがあるため、小細胞性チャンネルはおそらくぼやけている。
一例として、以下では暗い視覚シーンの webcam ビデオストリームに網膜モデルを適用する。この視覚シーンは大学の階段教室で撮影されたもので、何人かの学生が教師に話しかけながら動いている。
このビデオシーケンスでは、暗い環境のために信号対雑音比が低く、低品質の画像取得ツールチェーンのために視覚的特徴のエッジに色のアーティファクトが現れている。
image
下図には、画像全体に適用した網膜の中心窩視を示す。使用した網膜設定では、全体的な輝度が保たれ、局所コントラストが強調されている。また、信号対雑音比も改善されている:高周波の時空間ノイズが低減されるため、強調されたディテールが強調されたノイズによって損なわれることはない。
image
下図は網膜モデルの大細胞性出力である。その信号は過渡的イベントが発生した場所で強くなる。ここでは、1人の学生が画像の下部で動いており、それにより高いエネルギーが生成されている。画像の残りの部分は静止しているが、強いノイズに汚染されている。ここで網膜はノイズの大部分を除去し、誤った動き領域の「警報」を低減している。このチャンネルは過渡的/動いている領域の検出器として利用できる:イベントが発生している領域を強調表示する低コストなセグメンテーション(領域分割)ツールに対して、有用な情報を提供できる。
image
網膜のユースケース
このモデルは基本的に時空間的なビデオエフェクトに利用できるが、以下の目的でも利用できる:
- 信号対雑音比を強調し、入力画像の輝度範囲に対してロバストにディテールを強調したテクスチャ解析を行う(小細胞性網膜チャンネルの出力を参照)
- 前述の特性も活用した動き解析を行う。
文献
詳細については、以下の論文を参照のこと:[26]
- Jeanny Herault の参考著作(彼の著書 [141] で読める)を参照のこと
この網膜フィルタのコードには、著者がコードを書き直した博士課程/研究の同僚による研究上の貢献が含まれている。
- Brice Chaix de Lavarene の博士論文による色のモザイク化/デモザイク化と、その参考論文 [70] を知るために、retinacolor.hppモジュールを参照のこと
- Barthelemy Durette の博士研究と Jeanny Herault に由来する網膜の空間的対数サンプリングを知るには imagelogpolprojection.hpp を参照すること。Retina / V1 皮質投影も提案されており、これは Jeanny との議論に由来する。詳細は上記で引用した Jeanny Herault の著書にある。
コードチュートリアル
ファイルopencv_folder/samples/cpp/tutorial_code/bioinspired/retina_tutorial.cppにある元のチュートリアルのソースコードを参照のこと。
- 覚え書き
- 網膜モデルが以下の名前空間に含まれていることを忘れないこと:cv::bioinspired
コンパイルするには、OpenCV が正しくインストールされていることを前提に、以下のコマンドを使用する。コンパイルには opencv_core (cv::Mat および関連オブジェクトの管理)、opencv_highgui (表示および画像/ビデオの読み込み)、opencv_bioinspired (Retina の記述) の各ライブラリが必要である。
// compile
gcc retina_tutorial.cpp -o Retina_tuto -lopencv_core -lopencv_highgui -lopencv_bioinspired -lopencv_videoio -lopencv_imgcodecs
// Run commands : add 'log' as a last parameter to apply a spatial log sampling (simulates retina sampling)
// run on webcam
./Retina_tuto -video
// run on video file
./Retina_tuto -video myVideo.avi
// run on an image
./Retina_tuto -image myPicture.jpg
// run on an image with log sampling
./Retina_tuto -image myPicture.jpg log
以下はコードの説明である:
Retina の定義は bioinspired パッケージに含まれており、単純なインクルードで利用できる。お好みであれば専用のヘッダopencv2/bioinspired.hppを使ってもよいが、その場合は他の必要な opencv モジュールopencv2/core.hppとopencv2/highgui.hppをインクルードすること
#include "opencv2/opencv.hpp"
ヘルプ関数を用意し、プログラムを実行するためのヒントをユーザに提供する
static void help(std::string errorMessage)
{
std::cout<<"Program init error : "<<errorMessage<<std::endl;
std::cout<<"\nProgram call procedure : retinaDemo [processing mode] [Optional : media target] [Optional LAST parameter: \"log\" to activate retina log sampling]"<<std::endl;
std::cout<<"\t[processing mode] :"<<std::endl;
std::cout<<"\t -image : for still image processing"<<std::endl;
std::cout<<"\t -video : for video stream processing"<<std::endl;
std::cout<<"\t[Optional : media target] :"<<std::endl;
std::cout<<"\t if processing an image or video file, then, specify the path and filename of the target to process"<<std::endl;
std::cout<<"\t leave empty if processing video stream coming from a connected video device"<<std::endl;
std::cout<<"\t[Optional : activate retina log sampling] : an optional last parameter can be specified for retina spatial log sampling"<<std::endl;
std::cout<<"\t set \"log\" without quotes to activate this sampling, output frame size will be divided by 4"<<std::endl;
std::cout<<"\nExamples:"<<std::endl;
std::cout<<"\t-Image processing : ./retinaDemo -image lena.jpg"<<std::endl;
std::cout<<"\t-Image processing with log sampling : ./retinaDemo -image lena.jpg log"<<std::endl;
std::cout<<"\t-Video processing : ./retinaDemo -video myMovie.mp4"<<std::endl;
std::cout<<"\t-Live video processing : ./retinaDemo -video"<<std::endl;
std::cout<<"\nPlease start again with new parameters"<<std::endl;
std::cout<<"****************************************************"<<std::endl;
std::cout<<" NOTE : this program generates the default retina parameters file 'RetinaDefaultParameters.xml'"<<std::endl;
std::cout<<" => you can use this to fine tune parameters and load them if you save to file 'RetinaSpecificParameters.xml'"<<std::endl;
}
次に、メインプログラムを開始し、まず入力画像を読み込むcv::Mat行列を宣言する。また、(必要に応じて)ビデオストリームを読み込めるようにcv::VideoCaptureオブジェクトも確保する
int main(
int argc,
char* argv[]) {
n-dimensional dense array class
Definition mat.hpp:840
Class for video capturing from video files, image sequences or cameras.
Definition videoio.hpp:786
int main(int argc, char *argv[])
Definition highgui_qt.cpp:3
メインプログラムでは、処理の前にまず入力コマンドパラメータをチェックする。ここでは、単一の読み込んだ画像(ユーザがコマンド-imageを選択した場合)またはビデオストリーム(ユーザがコマンド-videoを選択した場合)から、最初の入力画像を読み込む。また、ユーザがプログラム呼び出しの末尾にlogコマンドを追加した場合は、網膜が行う空間的な対数画像サンプリングがブール型フラグuseLogSamplingによって考慮される。
std::cout<<"****************************************************"<<std::endl;
std::cout<<"* Retina demonstration : demonstrates the use of is a wrapper class of the Gipsa/Listic Labs retina model."<<std::endl;
std::cout<<"* This demo will try to load the file 'RetinaSpecificParameters.xml' (if exists).\nTo create it, copy the autogenerated template 'RetinaDefaultParameters.xml'.\nThen tweak it with your own retina parameters."<<std::endl;
if (argc<2)
{
help("bad number of parameter");
return -1;
}
bool useLogSampling = !strcmp(argv[argc-1], "log");
std::string inputMediaType=argv[1];
if (!strcmp(inputMediaType.c_str(), "-image") && argc >= 3)
{
std::cout<<"RetinaDemo: processing image "<<argv[2]<<std::endl;
}else
if (!strcmp(inputMediaType.c_str(), "-video"))
{
if (argc == 2 || (argc == 3 && useLogSampling))
{
}else
{
std::cout<<"RetinaDemo: processing video stream "<<argv[2]<<std::endl;
videoCapture.
open(argv[2]);
}
videoCapture>>inputFrame;
}else
{
help("bad command parameter");
return -1;
}
virtual bool open(const String &filename, int apiPreference=CAP_ANY)
Opens a video file or a capturing device or an IP video stream for video capturing.
Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
Loads an image from a file.
すべての入力パラメータが処理されると、最初の画像が読み込まれているはずである。読み込まれていない場合はエラーを表示してプログラムを停止する:
{
help("Input media could not be loaded, aborting");
return -1;
}
bool empty() const
Returns true if the array has no elements.
これで網膜モデルを実行する準備がすべて整った。ここでは、網膜のインスタンスを確保し、最終的なログサンプリングオプションを管理することを提案する。Retina のコンストラクタは、管理する必要のある入力データのサイズを示す cv::Size オブジェクトを少なくとも必要とする。色やそれに関連する色多重化戦略(ここではenum cv::bioinspired::RETINA_COLOR_BAYER を使って Bayer 多重化を選択している)といった他のオプションを有効にできる。ログサンプリングを使用する場合、画像縮小係数(より小さな出力画像)とログサンプリングの強度を調整できる。
if (useLogSampling)
{
}
else
myRetina = cv::bioinspired::createRetina(inputFrame.
size());
MatSize size
Definition mat.hpp:2226
@ RETINA_COLOR_BAYER
standard bayer sampling
Definition retina.hpp:86
std::shared_ptr< _Tp > Ptr
Definition cvstd_wrapper.hpp:23
完了すると、提案するコードは網膜のデフォルトパラメータを含むデフォルトの xml ファイルを書き出す。これは、このテンプレートを使って独自の設定を作成するのに便利である。ここで生成されるテンプレート xml ファイルはRetinaDefaultParameters.xmlと呼ばれる。
myRetina->write("RetinaDefaultParameters.xml");
次の行では、網膜はRetinaSpecificParameters.xmlという別の xml ファイルの読み込みを試みる。これを作成して独自の設定を導入していればそれが読み込まれ、そうでない場合はデフォルトの網膜パラメータが使用される。
myRetina->setup("RetinaSpecificParameters.xml");
ここでは必須ではないが、可能であることを示すために、網膜のバッファをゼロにリセットして過去のイベントを強制的に忘れさせることができる。
myRetina->clearBuffers();
さあ、網膜を実行する時だ!まず、2つの網膜チャンネル出力を受け取る準備のできた出力バッファをいくつか作成する
次に、ループ内で網膜を実行し、必要に応じてビデオシーケンスから新しいフレームを読み込み、網膜の出力を専用バッファに取り戻す。
while(true)
{
videoCapture>>inputFrame;
myRetina->run(inputFrame);
myRetina->getParvo(retinaOutput_parvo);
myRetina->getMagno(retinaOutput_magno);
}
virtual bool isOpened() const
Returns true if video capturing has been initialized already.
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
int waitKey(int delay=0)
Waits for a pressed key.
これで完了だ!しかし、システムを安全にしたい場合は、例外に注意して管理すること。網膜は無関係なデータ(入力フレームがない、設定が誤っているなど)を見たときに例外をスローすることがある。そこで、次のように網膜のコード全体を try/catch システムで囲むことを推奨する:
try{
[---]
while(true)
{
[---]
}
{
std::cerr<<
"Error using Retina : "<<e.
what()<<std::endl;
}
Class passed to an error.
Definition core.hpp:120
virtual const char * what() const noexcept override
網膜のパラメータ、何をすべきか?
まず、参考論文 [26] を読むことを推奨する
完了したら、デモが生成した設定ファイルRetinaDefaultParameters.xmlを開き、それを見てみよう。
<?xml version="1.0"?>
<opencv_storage>
<OPLandIPLparvo>
<colorMode>1</colorMode>
<normaliseOutput>1</normaliseOutput>
<photoreceptorsLocalAdaptationSensitivity>7.5e-01</photoreceptorsLocalAdaptationSensitivity>
<photoreceptorsTemporalConstant>9.0e-01</photoreceptorsTemporalConstant>
<photoreceptorsSpatialConstant>5.7e-01</photoreceptorsSpatialConstant>
<horizontalCellsGain>0.01</horizontalCellsGain>
<hcellsTemporalConstant>0.5</hcellsTemporalConstant>
<hcellsSpatialConstant>7.</hcellsSpatialConstant>
<ganglionCellsSensitivity>7.5e-01</ganglionCellsSensitivity></OPLandIPLparvo>
<IPLmagno>
<normaliseOutput>1</normaliseOutput>
<parasolCells_beta>0.</parasolCells_beta>
<parasolCells_tau>0.</parasolCells_tau>
<parasolCells_k>7.</parasolCells_k>
<amacrinCellsTemporalCutFrequency>2.0e+00</amacrinCellsTemporalCutFrequency>
<V0CompressionParameter>9.5e-01</V0CompressionParameter>
<localAdaptintegration_tau>0.</localAdaptintegration_tau>
<localAdaptintegration_k>7.</localAdaptintegration_k></IPLmagno>
</opencv_storage>
ここでいくつかのヒントを示すが、実際には最適なパラメータ設定は、網膜に与える入力画像よりも、網膜で何をしたいかにより依存する。特定の輝度圧縮を目的としてより特化した設定を必要とするハイダイナミックレンジ画像 (HDR) のより特殊なケースを除けば、網膜の振る舞いは内容が変わってもかなり安定しているはずである。OpenCV は OpenEXR 画像との互換性のおかげで、このような HDR 形式を扱えることに留意のこと。
次に、アプリケーションの目標が特定の画像処理の前にディテール強調を必要とする場合、平均輝度情報が必要かどうかを知る必要がある。必要ない場合、網膜はそのエネルギーを打ち消すか大幅に低減でき、これによりより高い空間周波数のディテールがより見えるようになる。
基本パラメータ
もっとも単純な引数は次のとおりである:
- colorMode : 網膜にカラー情報を処理させる(1の場合)か、グレースケール画像を処理させる(0の場合)かを指定する。後者の場合、入力の最初のチャンネルのみが処理される。
- normaliseOutput : 各チャンネルがこの引数を持つ。値を1に設定すると、対象チャンネルの出力が0から255の範囲に再スケールされる。この場合、Magnocellular(大細胞系)出力レベル(動き/過渡チャンネル検出)には注意すること。残留ノイズも再スケールされてしまう!
注 : カラーを使用すると、カラーチャンネルの多重化/逆多重化が必要となり、処理量も増加する。グレースケールを使えばはるかに高速な処理が期待できる。すべての網膜処理について1ピクセルあたり約30回の積演算で済み、最近ではマルチコアアーキテクチャ向けに並列化されている。
光受容体パラメータ
以下の引数は、網膜の入口である光受容体に作用し、後続のすべての処理に影響を与える。これらのセンサは、時間的・空間的なデータを平滑化し、局所輝度に対する感度も調整する低域通過時空間フィルタであり、その結果、ディテールの抽出を改善し、高周波ノイズを除去する。
- photoreceptorsLocalAdaptationSensitivity 0から1の範囲。1に近い値は、光受容体レベルでの高輝度の対数圧縮効果を高める。0に近い値はより線形な感度を与える。これを単独で大きくすると、Parvo(ディテールチャンネル)の出力画像が白飛びすることがある。ganglionCellsSensitivityと組み合わせて調整すると、局所輝度がどのような状態であっても画像を非常に高コントラストにできる... ただし自然さが低下するという代償を伴う。
- photoreceptorsTemporalConstant 網膜の入口における低域通過フィルタ効果の時間定数を設定する。高い値は強い時間平滑化効果をもたらす。動いている物体はぼやけて消えることがある一方、静止物体が優先される。ただし網膜処理を開始したとき、安定状態に達するまでに時間がかかる。
- photoreceptorsSpatialConstant 光受容体の低域通過フィルタ効果に関連する空間定数を指定する。これらの引数は、以降で許容される空間信号周期の最小値を指定する。通常、このフィルタは高周波ノイズを除去する。一方、値が0だとノイズはまったく除去されず、値を大きくすると高い空間周波数が除去され始め、徐々に低い周波数も除去されていく... 入力画像のディテールを残したい場合は高い値にしないよう注意すること! カラー画像については0.53という値が良い折衷案である。この選択はカラースペクトルにあまり影響しないからである。これより高い値は、グレーでぼやけた出力画像をもたらす。
水平細胞パラメータ
この引数群は、光受容体に接続された神経ネットワークである水平細胞を調整する。光受容体の感度を調節し、最終的なスペクトル白色化(空間帯域通過効果の一部であり、視覚的ディテールの強調に寄与する)のための処理を完成させる。
- horizontalCellsGain これは重要な引数である! 平均輝度に関心がなく、ディテールの強調だけに注目したい場合は、この引数をゼロに設定する。一方、環境の輝度データをある程度残したい場合は、低い空間周波数をシステムに通すために高めの値(<1)を設定する。
- hcellsTemporalConstant 光受容体と同様に、この引数は入力データを平滑化する低域通過時間フィルタの時間定数に作用する。ここでは、高い値は網膜の強い残効を生み、低い値は網膜の応答性を高める。網膜の強い残効を抑えるため、この値はphotoreceptorsTemporalConstantより小さくすべきである。
- hcellsSpatialConstant これらの細胞フィルタの低域通過特性の空間定数である。以降で許容される最も低い空間周波数を指定する。視覚的には、高い値は非常に低い空間周波数の処理をもたらし、目立つハロー効果を生じる。低い値はこの効果を軽減するが、photoreceptorsSpatialConstantの値より低くはできないという制約がある。これら2つの引数が実際には網膜の空間帯域通過特性を指定する。
注 前述の引数による処理が完了すると、入力データはノイズが除去され、輝度もすでに部分的に強調されている。以下の引数は、出力される2つの網膜信号の最終処理段階に作用する。
Parvo(ディテールチャンネル)専用パラメータ
- ganglionCellsSensitivity このディテール専用チャンネルの出力で生じる最終的な局所適応の強さを指定する。引数値は0から1の範囲を保つ。低い値は線形応答を与えがちで、高い値は残った低コントラスト領域を強調する。
注 : この引数は、明るい領域であっても視覚シーンの低エネルギーのディテールを優先することで、白飛びした画像を補正できる。
IPL Magno(動き/過渡チャンネル)パラメータ
画像の情報がクリーニングされると、このチャンネルは高域通過時間フィルタとして働き、過渡信号(イベント、動きなど)に関連する信号のみを選択する。低域通過空間フィルタが抽出された過渡データを平滑化し、最終的な対数圧縮が小さな過渡イベントを強調することでイベント感度を高める。
- parasolCells_beta 一般にゼロに設定され、この処理段階の入口における増幅ゲインと見なせる。通常は0に設定する。
- parasolCells_tau 追加できる時間平滑化効果。
- parasolCells_k 空間フィルタリング効果の空間定数。残留ノイズの影響を受けにくい低い空間周波数の信号を優先するには、高い値に設定する。
- amacrinCellsTemporalCutFrequency 高域通過フィルタの時間定数を指定する。高い値はゆっくりとした過渡イベントを選択できるようにする。
- V0CompressionParameter 対数圧縮の強さを指定する。前述の説明と同様の動作だが、ここでは過渡イベントの感度を強調する。
- localAdaptintegration_tau 一般に0に設定され、実際にはここでは特に用途はない。
- localAdaptintegration_k 局所適応を行う領域のサイズを指定する。低い値は短い範囲の局所適応をもたらし(ノイズへの感度が高くなる)、高い値は対数圧縮を確実にする。