提示された5枚の画像のうち,4番目(明るい)と5枚目(暗い)に関して,
てきとーに画素の明るさの差分を見れる程度に補正処理をできるかどうか? をやってみました.
テストに際しては,
- 画像サイズがでかかったので,縦横共に1/4に縮小して使った
- とりあえず明るさだけを見たいので,グレースケールで読み込んだ
下図の
- 上段は,{画像4そのもの,画像5そのもの,両者のabsdiff結果を(見やすいように)5倍したもの}
- 下段は,{画像4補正結果,画像5補正結果,両者のabsdiff結果を(見やすいように)5倍したもの}
です.
この程度の急峻でない明暗変化具合であれば,まぁ,てきとーに前処理で明るさを補正してやる方向でも良いのではないか?と思います.
テストに用いた明るさ補正コードです.(C++ですが)
C++
1cv::Mat Correction( const cv::Mat &Src, int KernelSizeFactor=6 )
2{
3 cv::Mat Blurred;
4 {
5 int s = ( std::min( Src.rows, Src.cols ) / KernelSizeFactor ) | 0x01;
6 cv::GaussianBlur( Src, Blurred, cv::Size(s,s), 0 );
7 }
8
9 cv::Mat Result = cv::Mat( Src.rows, Src.cols, CV_8UC1 );
10 for( int y=0; y<Src.rows; ++y )
11 {
12 const unsigned char *pS = Src.ptr<unsigned char>(y);
13 const unsigned char *pB = Blurred.ptr<unsigned char>(y);
14 unsigned char *pR = Result.ptr<unsigned char>(y);
15 for( int x=0; x<Src.cols; ++x, ++pS,++pB,++pR )
16 {
17 double b = std::max<unsigned char>( 1, *pB ) / 255.0;
18 double g = log(0.5) / log(b);
19 *pR = cvRound( 255.0 * pow(*pS / 255.0, g) );
20 }
21 }
22 return Result;
23}
[補足]
この処理のPython化の話をしている質問にて,上記テストコードの処理内容に関する指摘があったのでその点を補足しておく.
問題点:
double b = std::max<unsigned char>( 1, *pB ) / 255.0;
の行が,*pBが0の場合についてはガードを入れているが,255の場合へのガードが抜けている.
そのため,*pBが255であるとき,double g = log(0.5) / log(b);
の分母が0になってしまう.
対策について:
0側と同様に,255側へのガードも入れれば良いであろうと思う.
すなわち,*pB の値を適当な有効範囲内に抑え込んでやればよかろう.
//2つの閾値 T_min, T_max の値はてきとーに決めるとして.
const unsigned char T_min = 1; //1以上の値
const unsigned char T_max = 250; //254以下の値
...
double b = std::max( T_min, std::min(T_max,*pB) ) / 255.0;