直方圖
直方圖所要做的事情是統計一張圖片的藍、綠、紅,各色彩從0到255的使用量,所以我宣告了以下二維陣列:
int iHistogram[3][256]; // 直方圖數據
然後用兩層for迴圈統計圖片的藍、綠、紅色彩值,最外圈代表走訪到圖片的第i列像素、內圈則走訪圖片的第i列第j排像素,藍、綠、紅色的統計依序執行。
統計用的程式碼:
// 初始化色彩統計
for (i = 0; i < 3; i++)
for
(j = 0; j < 256; j++)
iHistogram[i][j] = 0;
for (i = 0; i < iImageHeight; i++)
{
bPictureImageShowRow
= (Byte*)imgShow->Picture->Bitmap->ScanLine[i];
for
(j = 0; j < iImageWidth; j++)
{
//藍色值
iHistogram[0][
int(bPictureImageShowRow[3*j+0]) ] += 1;
//綠色值
iHistogram[1][
int(bPictureImageShowRow[3*j+1]) ] += 1;
//紅色值
iHistogram[2][
int(bPictureImageShowRow[3*j+2]) ] += 1;
}
}
//將結果繪製出來
DrawHistogram(imgHistogram,chkRed,chkGreen,chkBlue);
繪製直方圖
繪製直方圖的部分我是將藍、綠、紅三種結果表示在同一個TImage(imgHistogram)元件內,使用三個TCheckBox(chkRed、chkGreen、chkBlue)元件來自訂輸出哪幾個顏色的統計結果。
在這裡遇到的問題是我剛開始把函式宣告成這樣:
void DrawHistogram( );
想說四個元件都有宣告在標頭檔(Unit1.h)裡面,但是執行時它看不懂我寫在函式裡面的那四個變數名稱:imgHistogram、chkRed、chkGreen、chkBlue。
所以才將函式改寫成接收了四個元件的變數名稱,如下:
void DrawHistogram(
TImage
*imgHistogram,
TCheckBox
*chkRed,
TCheckBox
*chkGreen,
TCheckBox
*chkBlue)
{
// 畫布清空
imgHistogram->Canvas->Brush->Color
= clWhite;
imgHistogram->Canvas->FillRect(
Rect(0,0,imgHistogram->Width,imgHistogram->Height) );
// 顯示紅色
if (chkRed->Checked == True)
for
(j = 0; j < 256; j++)
{
imgHistogram->Canvas->Pen->Color =
clRed;
imgHistogram->Canvas->Pen->Width =
1;
imgHistogram->Canvas->MoveTo( j*3, 0
);
imgHistogram->Canvas->LineTo( j*3,
int(float(iHistogram[2][j]) / fTotal * 5000) );
}
// 顯示綠色
if (chkGreen->Checked == True)
for
(j = 0; j < 256; j++)
{
imgHistogram->Canvas->Pen->Color =
clGreen;
imgHistogram->Canvas->Pen->Width =
1;
imgHistogram->Canvas->MoveTo( j*3+1,
0 );
imgHistogram->Canvas->LineTo( j*3+1,
int(float(iHistogram[1][j]) / fTotal * 5000) );
}
// 顯示藍色
if (chkBlue->Checked == True)
for
(j = 0; j < 256; j++)
{
imgHistogram->Canvas->Pen->Color =
clBlue;
imgHistogram->Canvas->Pen->Width =
1;
imgHistogram->Canvas->MoveTo( j*3+2,
0 );
imgHistogram->Canvas->LineTo( j*3+2,
int(float(iHistogram[0][j]) / fTotal * 5000) );
}
}
累積直方圖
使用前面直方圖的數據(iHistogram),利用兩層迴圈來製作累積直方圖的值,本來是使用整數型態(iCumulativeHistogram)來貯存,但之後要進行直方圖均化的處理,所以改為使用浮點數型態(fCumulativeHistogram),是將每個從iHistogram計算來的值除以圖片像素總數,像素總數在載入圖片時計算完成。
繪製的方法和直方圖相似。
宣告的變數如下:
float fCumulativeHistogram[3][256]; // 累積直方圖數據
float fTotal; // 圖片像素總數
計算累積直方圖的函式:
// 初始化色彩累積統計
for (i = 0; i < 3; i++)
{
fCumulativeHistogram[i][0]
= float( iHistogram[i][0] ) / fTotal;
for
(j = 1; j < 256; j++)
fCumulativeHistogram[i][j]
= 0;
}
for ( i = 0; i < 3; i++ )
for
( j = 1; j < 256; j++ )
fCumulativeHistogram[i][j]
= fCumulativeHistogram[ i ][ j - 1 ]
+ ( float(
iHistogram[ i ][ j - 1 ] ) / fTotal );
//繪製累積直方圖
DrawCumulativeHistogram(imgCumulativeHistogram,chkRed,chkGreen,chkBlue);
繪製累積直方圖的函式:
void DrawCumulativeHistogram(
TImage
*imgCumulativeHistogram,
TCheckBox
*chkRed,
TCheckBox
*chkGreen,
TCheckBox
*chkBlue)
{
// 畫布清空
imgCumulativeHistogram->Canvas->Brush->Color
= clWhite;
imgCumulativeHistogram->Canvas->FillRect(
Rect(0,0,imgCumulativeHistogram->Width,imgCumulativeHistogram->Height) );
// 顯示紅色
if (chkRed->Checked == True)
for
(j = 0; j < 256; j++)
{
imgCumulativeHistogram->Canvas->Pen->Color
= clRed;
imgCumulativeHistogram->Canvas->Pen->Width
= 1;
imgCumulativeHistogram->Canvas->MoveTo(
j*3, 0 );
imgCumulativeHistogram->Canvas->LineTo(
j*3, int(fCumulativeHistogram[2][j] * 100) );
}
// 顯示綠色
if (chkGreen->Checked == True)
for
(j = 0; j < 256; j++)
{
imgCumulativeHistogram->Canvas->Pen->Color
= clGreen;
imgCumulativeHistogram->Canvas->Pen->Width
= 1;
imgCumulativeHistogram->Canvas->MoveTo(
j*3+1,0 );
imgCumulativeHistogram->Canvas->LineTo(
j*3+1, int(fCumulativeHistogram[1][j] * 100) );
}
// 顯示藍色
if (chkBlue->Checked == True)
for
(j = 0; j < 256; j++)
{
imgCumulativeHistogram->Canvas->Pen->Color
= clBlue;
imgCumulativeHistogram->Canvas->Pen->Width
= 1;
imgCumulativeHistogram->Canvas->MoveTo(
j*3+2,0 );
imgCumulativeHistogram->Canvas->LineTo(
j*3+2, int(fCumulativeHistogram[0][j] * 100) );
}
}
直方圖均化的程式碼:
for (i = 0; i < iImageHeight; i++)
{
bPictureImageShowRow
= (Byte*)imgShow->Picture->Bitmap->ScanLine[i];
bPictureImageOriginRow
= (Byte*)imgOrigin->Picture->Bitmap->ScanLine[i];
for
(j =0; j < iImageWidth; j++)
{
bPictureImageShowRow[3*j+0] =
int(fCumulativeHistogram[0][ int(bPictureImageShowRow[3*j+0]) ] * 255);
// 防止單一像素色彩值溢位
if ( bPictureImageShowRow[3*j+0] > 255 )
bPictureImageShowRow[3*j+0]
= 255;
bPictureImageShowRow[3*j+1] =
int(fCumulativeHistogram[1][ int(bPictureImageShowRow[3*j+1]) ] * 255);
// 防止單一像素色彩值溢位
if ( bPictureImageShowRow[3*j+1] > 255 )
bPictureImageShowRow[3*j+1]
= 255;
bPictureImageShowRow[3*j+2] =
int(fCumulativeHistogram[2][ int(bPictureImageShowRow[3*j+2]) ] * 255);
// 防止單一像素色彩值溢位
if ( bPictureImageShowRow[3*j+2] > 255 )
bPictureImageShowRow[3*j+2]
= 255;
}
}
imgShow->Refresh();
部分程式執行畫面:
開啟圖片後的畫面,第二次作業的結果輸出,我放在「Color Statistics」的分頁
直方圖(Histogram)、累積直方圖(Cumulative Histogram)、直方圖均化(Histogram
Equalization)的功能建在Image->Calculate的選單下
直方圖的結果,預設是藍、綠、紅都輸出,可以在下方勾選想觀看的顏色,再按下Reset按鍵重新輸出結果。
累積直方圖的結果
直方圖均化後的圖片,若要觀看均化後的直方圖和累積直方圖,則要再到選單操作兩個功能。
均化後的直方圖
均化後的累積直方圖
沒有留言:
張貼留言