画像のHSV色空間利用の明度自動調節

解説

 RGB色空間をHSV色空間に変換、求まったH,S,Vのうち明度(V)について自動調節をした。
 まずVは 0~1.0 の間を取るので1000を乗算して小数点以下を切り捨てることで1001階調化する。 次に1001階調分の明度ヒストグラムを取って暗い方(小さい方)からどんどん加算して累積度数 を計算、その値を元に自動調節している。


実行例

 彩度が落ちてしまっているがイコライズしたときのような画像になった。




ソースコード

 画像のRGB->HSV変換とHSV->RGB変換の 「明度(V)アップ」部分を以下のように変更する。


			////////////////////////////////////
			//自動明度調節
			//
			{
				int		i;
				ULONG	pHisgram[1001];

				ZeroMemory(pHisgram,sizeof(ULONG) * 1001);

				////////////////////////////////////
				//ヒストグラム計算
				//ソースコードを見やすくするため何度もforを回している
				//
				nPos = 0;
				for(y = 0; y < pImage->GetHeight(); y++)
				{
					for(x = 0; x < pImage->GetWidth(); x++, nPos++)
					{
						//ヒストグラムデータ追加
						//HSVのVに対して1000倍し、0~1000の1001諧調とする
						pHisgram[(int)(pHSV[nPos].dV * 1000)]++;
					}
				}


				////////////////////////////////////
				//累積度数計算
				//
				double	pdCumulative[1001];

				pdCumulative[0] = pHisgram[0];
				for(i = 1; i < 1001; i++)
				{
					pdCumulative[i] = pdCumulative[i - 1] + pHisgram[i];
				}

				////////////////////////////////////
				//画素当たりの累積度数計算
				//
				for(i = 0; i < 1001; i++)
				{
					pdCumulative[i] = pdCumulative[i] / (double)(pImage->GetWidth() * pImage->GetHeight());
				}

				////////////////////////////////////
				//ヒストグラム最小累積度数チェック
				//
				double		dMin;

				for(i = 0; i < 1001; i++)
				{
					if(pdCumulative[i] == 0)
						continue;

					dMin = pdCumulative[i];
					break;
				}

				////////////////////////////////////
				//明度自動調節
				//
				nPos = 0;
				for(y = 0; y < pImage->GetHeight(); y++)
				{
					for(x = 0; x < pImage->GetWidth(); x++, nPos++)
					{
						int	nTmp;

						nTmp = (int)(((double)(pdCumulative[(int)(pHSV[nPos].dV * 1000)] - dMin) * 1000) / (double)(1 - dMin));
						if(nTmp > 1000)
							nTmp = 1000;
						if(nTmp < 0)
							nTmp = 0;
						pHSV[nPos].dV = ((double)nTmp / 1000.0);
					}
				}
			}

カテゴリー「VC++ TIPS」 のエントリー