画像の自動コントラスト調節

解説

 グレースケールを利用したコントラスト調節。
 画像をグレースケール化してそのヒストグラムを作成する。次にそのヒストグラム を累積して中間点の色値を算出する。併せてグレースケールの最小色値と最大色値も 取得しておく。そしてそれらの値を元に色値方向に2分割して新しい色値を決定する。
 新しい色値は累積中間点までの色数に対して求まる1色ごとの"重み"を元の色値に乗 算することで決定する。


実行例




ソースコード

 GDI+を利用した画像処理テストのスケルトンの 画像処理部分を以下のように変更する。



		////////////////////////////
		//画像処理
		//
		UINT		x;
		UINT		y;
		UINT		nPos;
		RGBTRIPLE*	pTmp;
		Gdiplus::BitmapData		bitmapData;

		pImage->LockBits(&Gdiplus::Rect(0,0,pImage->GetWidth(),pImage->GetHeight())
			,Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite,PixelFormat24bppRGB,&bitmapData);

		pTmp = (RGBTRIPLE*)bitmapData.Scan0;


		//コントラスト自動調節
		{
			/////////
			//グレースケールヒストグラム作成
			//
			BYTE	nGray;
			ULONG	pnHistgram[256];

			ZeroMemory(pnHistgram,sizeof(ULONG) * 256);

			nPos = 0;
			for(y = 0; y < pImage->GetHeight(); y++)
			{
				for(x = 0; x < pImage->GetWidth(); x++, nPos++)
				{
					nGray = (BYTE)((77 * pTmp[nPos].rgbtRed + 150 * pTmp[nPos].rgbtGreen + 29 * pTmp[nPos].rgbtBlue) >> 8);
					pnHistgram[nGray]++;
				}
			}

			/////////
			//ヒストグラムの累積中間点算出
			//
			ULONG	nCount;
			ULONG	nHalfCount;

			nHalfCount = (pImage->GetWidth() * pImage->GetHeight()) / 2;

			nCount = 0;
			for(y = 0; y < 256; y++)
			{
				nCount += pnHistgram[y];
				if(nCount >= nHalfCount)
					break;
			}
			nHalfCount = y;

			/////////
			//ヒストグラムの累積最小・最大点算出
			//
			int		nMin;
			int		nMax;

			for(y = 0; y < 256; y++)
			{
				if(pnHistgram[y] != 0)
					break;
			}
			nMin = y;

			for(y = 255; y >= 0; y--)
			{
				if(pnHistgram[y] != 0)
					break;
			}
			nMax = y;


			/////////
			//自動調節
			//

			double	dH;
			double	dL;

			dH = 127.0 / (nMax - nHalfCount);	//分母がゼロになる可能性あり
			dL = 127.0 / (nHalfCount - nMin);

			nPos = 0;
			for(y = 0; y < pImage->GetHeight(); y++)
			{
				for(x = 0; x < pImage->GetWidth(); x++, nPos++)
				{
					pTmp[nPos].rgbtBlue	= (pTmp[nPos].rgbtBlue	< nHalfCount) ? (pTmp[nPos].rgbtBlue	- nMin)	* dL : (pTmp[nPos].rgbtBlue	- nHalfCount - nMin+1) * dH + 128;
					pTmp[nPos].rgbtGreen= (pTmp[nPos].rgbtGreen	< nHalfCount) ? (pTmp[nPos].rgbtGreen	- nMin) * dL : (pTmp[nPos].rgbtGreen- nHalfCount - nMin+1) * dH + 128;
					pTmp[nPos].rgbtRed	= (pTmp[nPos].rgbtRed	< nHalfCount) ? (pTmp[nPos].rgbtRed		- nMin)	* dL : (pTmp[nPos].rgbtRed	- nHalfCount - nMin+1) * dH + 128;
				}
			}
		}

		pImage->UnlockBits(&bitmapData);


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