2009年1月10日 星期六
2009年1月6日 星期二
Matrix
CvArr → CvMat → IplImage ( 繼承關係 )
Even though OpenCV is implemented in C, the structures used in OpenCV have an object-oriented design; in effect, IplImage is derived from CvMat, which is derived from CvArr
1.
When CvArr* appears, it is acceptable to pass CvMat* or IplImage* to the routine.
可以用 CvArr * 去接 CvMat 或是 IplImage
上層往下指,上層的每一個成員下層也一定都有,所以一定都會對滿
反之,下層有的上層不見得有,所以下層的指標有些會接不到東西,就錯誤
故可以用上層的指標去接下層的成員函式。
2.
CvArr, can be thought of as an abstract base class from which CvMat is itself derived.
抽象基礎類別
是把最底層的class成員函數都宣告成virtual,本身的class沒辦法實體化
只提供該有哪些function的功能
實體的使用內容卻是由衍生出來的class去各自設計
也就是提供類似模組或樣版
第二點的參考資料來源:奇摩知識+
Even though OpenCV is implemented in C, the structures used in OpenCV have an object-oriented design; in effect, IplImage is derived from CvMat, which is derived from CvArr
1.
When CvArr* appears, it is acceptable to pass CvMat* or IplImage* to the routine.
可以用 CvArr * 去接 CvMat 或是 IplImage
上層往下指,上層的每一個成員下層也一定都有,所以一定都會對滿
反之,下層有的上層不見得有,所以下層的指標有些會接不到東西,就錯誤
故可以用上層的指標去接下層的成員函式。
2.
CvArr, can be thought of as an abstract base class from which CvMat is itself derived.
抽象基礎類別
是把最底層的class成員函數都宣告成virtual,本身的class沒辦法實體化
只提供該有哪些function的功能
實體的使用內容卻是由衍生出來的class去各自設計
也就是提供類似模組或樣版
第二點的參考資料來源:奇摩知識+
2009年1月5日 星期一
A Not-So-Simple Transformation

← 左為cvPyrDown()兩次的結果,
右為cvCanny()一次的結果。
// Example 2-5. Using cvPyrDown() to create a new image that is half the width and height of the input image
// Example 2-6. The Canny edge detector writes its output to a single channel (grayscale) image
// Example 2-7. Combining the pyramid down operator (twice) and the Canny subroutine in a simple image pipeline
// Example 2-8. Simplifying the image pipeline of Example 2-7 by making the individual stages release their intermediate memory allocations
#include "highgui.h"
#include "cv.h"
IplImage *doPyrDown( IplImage * , int );
IplImage *doCanny( IplImage * , double , double , double );
int main( int argc , char **argv )
{
cvNamedWindow( "Input" , CV_WINDOW_AUTOSIZE );
cvNamedWindow( "Output1" , CV_WINDOW_AUTOSIZE );
//cvNamedWindow( "Output2" , CV_WINDOW_AUTOSIZE );
//cvNamedWindow( "Output3" , CV_WINDOW_AUTOSIZE );
IplImage *image = cvLoadImage( argv[1] , 0);
IplImage *out1 = doPyrDown( image , IPL_GAUSSIAN_5x5 );
//IplImage *out2 = doPyrDown( out1 , IPL_GAUSSIAN_5x5 );
//IplImage *out3 = doCanny( out2 , 10 , 100 , 3 );
out1 = doPyrDown( out1 , IPL_GAUSSIAN_5x5 );
cvShowImage( "Input" , out1 );
out1 = doCanny( out1 , 10 , 100 , 3 );
//cvShowImage( "Input" , image );
cvShowImage( "Output1" , out1 );
//cvShowImage( "Output2" , out2 );
//cvShowImage( "Output3" , out3 );
cvWaitKey( 0 );
cvReleaseImage( &image );
cvReleaseImage( &out1 );
//cvReleaseImage( &out2 );
//cvReleaseImage( &out3 );
cvDestroyWindow( "Input" );
cvDestroyWindow( "Output1" );
//cvDestroyWindow( "Output2" );
//cvDestroyWindow( "Output3" );
return 0;
}
// Example 2-5.
IplImage *doPyrDown( IplImage *in , int filter )
{
// Best to make sure input image is divisible by two.
//
assert( in->width%2 == 0 && in->height%2 == 0 );
IplImage *out = cvCreateImage( cvSize( in->width/2 , in->height/2 ) , in->depth , in->nChannels );
cvPyrDown( in , out , filter );
return out;
}
// Example 2-6.
IplImage *doCanny( IplImage *in , double lowThresh , double highThresh , double aperture )
{
if( in->nChannels != 1 )
return 0; // Canny only handles gray scale iamges
IplImage *out = cvCreateImage( cvGetSize( in ) , IPL_DEPTH_8U , 1 );
cvCanny( in , out , lowThresh , highThresh , aperture );
return out;
}
2009年1月4日 星期日
Equalization using VB

←開檔

←依序為原圖、灰階、灰階均化、轉回彩色

←存檔
' 背景需要先拉入OpenFileDialog與SaveFileDialog物件
' RGB 轉成 YIQ 並且顯示灰階
Dim i, j, r, g, b, Y, imgW, imgH As Integer
Dim bmp As New Bitmap(PictureBox1.Image)
imgW = bmp.Width
imgH = bmp.Height
Dim bmp1 As New Bitmap(imgW, imgH)
For i = 0 To imgW - 1
For j = 0 To imgH - 1
r = bmp.GetPixel(i, j).R
g = bmp.GetPixel(i, j).G
b = bmp.GetPixel(i, j).B
Y = (0.299 * r + 0.587 * g + 0.114 * b)
If Y < 0 Then
Y = 0
ElseIf Y > 255 Then
Y = 255
End If
bmp1.SetPixel(i, j, Color.FromArgb(Y, Y, Y))
Next
Next
PictureBox2.SizeMode = PictureBox1.SizeMode
PictureBox2.Image = bmp1
' 對灰階影像做亮度均化
Dim imgW, imgH, i, j, Y As Integer
Dim bmp As New Bitmap(PictureBox2.Image)
imgW = bmp.Width
imgH = bmp.Height
Dim bmp1 As New Bitmap(imgW, imgH)
Dim N(255) As Integer
For i = 0 To imgW - 1
For j = 0 To imgH - 1
Y = bmp.GetPixel(i, j).R
N(Y) = N(Y) + 1
Next
Next
For i = 1 To 255
N(i) = N(i - 1) + N(i)
Next
j = imgW * imgH
For i = 0 To 255
' 四捨五入
If (N(i) * 255 / j * 10) Mod 10 < 5 Then
N(i) = N(i) * 255 / j
Else
N(i) = N(i) * 255 / j + 1
End If
If N(i) > 255 Then
N(i) = 255
ElseIf N(i) < 0 Then
N(i) = 0
End If
Next
For i = 0 To imgW - 1
For j = 0 To imgH - 1
Y = N(bmp.GetPixel(i, j).R)
bmp1.SetPixel(i, j, Color.FromArgb(Y, Y, Y))
Next
Next
PictureBox3.SizeMode = PictureBox2.SizeMode
PictureBox3.Image = bmp1
' 將均化過的Y與沒變的IQ轉回RGB
Dim i, j, r, g, b, Y, AI, Q, imgW, imgH As Integer
Dim bmp As New Bitmap(PictureBox1.Image)
Dim bmp1 As New Bitmap(PictureBox3.Image)
imgW = bmp.Width
imgH = bmp.Height
Dim bmp2 As New Bitmap(imgW, imgH)
For i = 0 To imgW - 1
For j = 0 To imgH - 1
r = bmp.GetPixel(i, j).R
g = bmp.GetPixel(i, j).G
b = bmp.GetPixel(i, j).B
Y = bmp1.GetPixel(i, j).R
AI = (0.596 * r - 0.274 * g - 0.322 * b)
Q = (0.211 * r - 0.522 * g + 0.311 * b)
r = (1 * Y + 0.956 * AI + 0.632 * Q)
If r < 0 Then
r = 0
ElseIf r > 255 Then
r = 255
End If
g = (1 * Y - 0.272 * AI - 0.648 * Q)
If g < 0 Then
g = 0
ElseIf g > 255 Then
g = 255
End If
b = (1 * Y - 1.105 * AI + 0.705 * Q)
If b < 0 Then
b = 0
ElseIf b > 255 Then
b = 255
End If
bmp2.SetPixel(i, j, Color.FromArgb(r, g, b))
Next
Next
PictureBox4.SizeMode = PictureBox3.SizeMode
PictureBox4.Image = bmp2
' 讀檔
Dim openFileDialog1 As New OpenFileDialog()
openFileDialog1.Filter = "Bmp Files|*.bmp"
openFileDialog1.Title = "Select a Bitmap File"
If openFileDialog1.ShowDialog() = DialogResult.OK Then
PictureBox1.Image = Image.FromFile(openFileDialog1.FileName)
Button1.Enabled = True
Label1.Visible = True
End If
' 存檔
Dim saveFileDialog1 As New SaveFileDialog()
saveFileDialog1.Filter = "Bitmap Image|*.bmp"
saveFileDialog1.Title = "Save an Bitmap File"
saveFileDialog1.ShowDialog()
' If the file name is not an empty string open it for saving.
If saveFileDialog1.FileName <> "" Then
' Saves the Image via a FileStream created by the OpenFile method.
Dim fs As System.IO.FileStream = CType _ (saveFileDialog1.OpenFile(), System.IO.FileStream)
' Saves the Image in the appropriate ImageFormat based upon the
' file type selected in the dialog box.
' NOTE that the FilterIndex property is one-based.
Me.PictureBox2.Image.Save(fs, _ System.Drawing.Imaging.ImageFormat.Bmp)
fs.Close()
End If
A Simple Transformation
// If the resource is not from bitmap file but from avi file, then each frame of the output
// will up-side down, I still not find out what reason.
// Example 2-4. Loading and then smoothing an image before it is displayed on the screen
#include "cv.h"
#include "highgui.h"
void example2_4( IplImage *);
int main(int argc,char **argv)
{
IplImage *image = cvLoadImage( argv[1] );
example2_4( image );
cvReleaseImage( &image );
return 0;
}
void example2_4( IplImage *image )
{
// Create some windows to show the input
// and output image in.
//
cvNamedWindow( "Example4-in" );
cvNamedWindow( "Example4-out" );
// Create a window to show our input image
//
cvShowImage( "Example4-in" , image );
// Create an image to hold the smoothed output
//
IplImage *out = cvCreateImage( cvGetSize(image) , IPL_DEPTH_8U , 3 );
// Do the smoothing
//
cvSmooth( image , out , CV_GAUSSIAN , 31 , 31);
// Show the smoothed image in the output window
//
cvShowImage( "Example4-out" , out );
//Be tidy
//
cvReleaseImage( &out );
// Wait for the user to hit a key, then clean up the windows
//
cvWaitKey( 0 );
cvDestroyWindow( "Example4-in" );
cvDestroyWindow( "Example4-out" );
}
// will up-side down, I still not find out what reason.
// Example 2-4. Loading and then smoothing an image before it is displayed on the screen
#include "cv.h"
#include "highgui.h"
void example2_4( IplImage *);
int main(int argc,char **argv)
{
IplImage *image = cvLoadImage( argv[1] );
example2_4( image );
cvReleaseImage( &image );
return 0;
}
void example2_4( IplImage *image )
{
// Create some windows to show the input
// and output image in.
//
cvNamedWindow( "Example4-in" );
cvNamedWindow( "Example4-out" );
// Create a window to show our input image
//
cvShowImage( "Example4-in" , image );
// Create an image to hold the smoothed output
//
IplImage *out = cvCreateImage( cvGetSize(image) , IPL_DEPTH_8U , 3 );
// Do the smoothing
//
cvSmooth( image , out , CV_GAUSSIAN , 31 , 31);
// Show the smoothed image in the output window
//
cvShowImage( "Example4-out" , out );
//Be tidy
//
cvReleaseImage( &out );
// Wait for the user to hit a key, then clean up the windows
//
cvWaitKey( 0 );
cvDestroyWindow( "Example4-in" );
cvDestroyWindow( "Example4-out" );
}
Trackbar Slider
// Example 2-3. Program to add a trackbar slider to the basic viewr window: when the slider is
// moved, the function onTrackbarSlide() is called and then passed to the slider's new value
#include "cv.h"
#include "highgui.h"
void onTrackbarSlide(int);
int g_slider_position = 0;
CvCapture *g_capture = NULL;
int main(int argc, char **argv)
{
cvNamedWindow("Example3",CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture(argv[1]);
// we use it when we want to query some data from the CvCapture structure
// it will return how many frames are in the video
int frames = (int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_FRAME_COUNT);
IplImage *frame;
if(frames!=0)
for(;;g_slider_position++)
{
// the last parameter is a callback function that reset the position of trackbar slider
cvCreateTrackbar("Position","Example3",&g_slider_position,frames,onTrackbarSlide);
frame = cvQueryFrame( g_capture );
if( !frame )
break;
cvShowImage("Example3",frame);
char c = cvWaitKey(33);
if( c==27 )
break;
while((c=='p')||(c=='P'))
{
c = cvWaitKey(0);
if( c==27 )
{
cvReleaseCapture( &g_capture );
cvDestroyWindow("Example3");
return 0;
}
if( (c=='c')||(c=='C')||(c==13) )
break;
else
c='p';
}
}
cvReleaseCapture( &g_capture );
cvDestroyWindow("Example3");
return 0;
}
void onTrackbarSlide(int pos)
{
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
// moved, the function onTrackbarSlide() is called and then passed to the slider's new value
#include "cv.h"
#include "highgui.h"
void onTrackbarSlide(int);
int g_slider_position = 0;
CvCapture *g_capture = NULL;
int main(int argc, char **argv)
{
cvNamedWindow("Example3",CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture(argv[1]);
// we use it when we want to query some data from the CvCapture structure
// it will return how many frames are in the video
int frames = (int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_FRAME_COUNT);
IplImage *frame;
if(frames!=0)
for(;;g_slider_position++)
{
// the last parameter is a callback function that reset the position of trackbar slider
cvCreateTrackbar("Position","Example3",&g_slider_position,frames,onTrackbarSlide);
frame = cvQueryFrame( g_capture );
if( !frame )
break;
cvShowImage("Example3",frame);
char c = cvWaitKey(33);
if( c==27 )
break;
while((c=='p')||(c=='P'))
{
c = cvWaitKey(0);
if( c==27 )
{
cvReleaseCapture( &g_capture );
cvDestroyWindow("Example3");
return 0;
}
if( (c=='c')||(c=='C')||(c==13) )
break;
else
c='p';
}
}
cvReleaseCapture( &g_capture );
cvDestroyWindow("Example3");
return 0;
}
void onTrackbarSlide(int pos)
{
cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
AVI Video
// Example 2-2. A simple OpenCV program for playing a video file from disk
#include "highgui.h"
int main(int argc, char **argv)
{
cvNamedWindow("Example2",CV_WINDOW_AUTOSIZE);
// it will also allocate a memory for the image
CvCapture *capture = cvCreateFileCapture(argv[1]);
IplImage *frame;
while(1)
{
frame = cvQueryFrame( capture );
if( !frame )
break;
cvShowImage( "Example2", frame );
// 30 frames per second = 30 frames / 1000 ms = 1 frame / 33 ms
// if no stdin then it will return -1
char c = cvWaitKey(33);
if(c==27)
break;
// pause while pressing p or P
while((c=='p')||(c=='P'))
{
c = cvWaitKey(0);
if(c==27)
{
cvReleaseCapture( &capture );
cvDestroyWindow( "Example" );
return 0;
}
// continue the video while pressing c, C or enter
if((c=='c')||(c=='C')||(c==13))
break;
else
c='p';
}
}
// it will also called "cvReleaseImage()" for the "frame" pointer
cvReleaseCapture( &capture );
cvDestroyWindow( "Example2" );
return 0;
}
#include "highgui.h"
int main(int argc, char **argv)
{
cvNamedWindow("Example2",CV_WINDOW_AUTOSIZE);
// it will also allocate a memory for the image
CvCapture *capture = cvCreateFileCapture(argv[1]);
IplImage *frame;
while(1)
{
frame = cvQueryFrame( capture );
if( !frame )
break;
cvShowImage( "Example2", frame );
// 30 frames per second = 30 frames / 1000 ms = 1 frame / 33 ms
// if no stdin then it will return -1
char c = cvWaitKey(33);
if(c==27)
break;
// pause while pressing p or P
while((c=='p')||(c=='P'))
{
c = cvWaitKey(0);
if(c==27)
{
cvReleaseCapture( &capture );
cvDestroyWindow( "Example" );
return 0;
}
// continue the video while pressing c, C or enter
if((c=='c')||(c=='C')||(c==13))
break;
else
c='p';
}
}
// it will also called "cvReleaseImage()" for the "frame" pointer
cvReleaseCapture( &capture );
cvDestroyWindow( "Example2" );
return 0;
}
2009年1月2日 星期五
二零零八跨年
今年依舊是在詠寧家跨年
成員:我、Angie、丁丁、左左、殺手、詠寧、啾啾
好不容易熬玩歷史課回家匆匆洗了個澡便趕往中壢
抵達目的地後不久沒想到意外的來了神秘嘉賓:聰明人跟宅豪

←右手邊的看起來不只宅,還呆呆的 XD"
好不容易大家都到齊了,舟車勞苦之後都飢腸轆轆,
便東西先放在一旁沒整頓就整群先去中原夜市覓食了,
找來找去都沒找到詠寧哥哥說的"傻蛋的窩",只好作罷,
走著走著倒是意外的發現了一家"塞納河"的義大利麵店,
感覺裝潢得很溫馨,裡面的服務生也很親切,給人感覺很舒服,
出餐雖然頗久 ( XD" 吃了快兩個小時吧 ) 但是卻是平常所感受不到的悠哉,
跟米卡果然不能比 = =+ 應該說米卡真的是太不好吃了,
大推這家店的手工蛋糕,在中原夜市的三井電腦斜對面巷子進去,

←巧克力部分超美味,吃起來很綿密不會膩
有機會可以再去吃吃看,為了美食到處奔波阿 XDDDD
回去的途中還順手夾了一個長頸鹿充氣娃娃,不過卻花了五十元,
感覺是被騙錢了 =口=... 不過大家卻玩得莫名很high...XD?

←啾啾的牙突

←被小惡魔硬是戴上去的丁丁,可憐的應該是長頸鹿...
中間就是倒數跨年啦,其間還打了蠻久的桌球 XD"
沒辦法,誰叫有一半都是系桌的,哈哈哈
大家都老了 =.=.... 沒辦法通霄到天亮,
不過也可能是因為宵夜吃鐵板燒加上冰火的關係吧,天氣太冷,
/* 家樂福買的澳洲培根肉串,結果是羊肉 = = 黑店 大家以後不要去阿...不爽 */
酒足飯飽之後喝完酒暖暖地好舒服超想睡 XD
隔天中午吃了到中壢一定要吃的牛肉麵!
之前吃過了永川、老師傅牛肉麵之後,這次主打:老三牛肉麵
坦白說,我覺得比老師傅差,且又忘記弄我們點的東西,
讓我們等超久 = =... 不開心~~~~~ 不推! 還是老師傅好吃!
計畫中的重頭戲就是巧克力火鍋啦! 今年突發奇想,繼去年豆漿火鍋之後,
今年特別一點,不過因為有一半的人有事先走,QQ
所以剩下一半的人吃了幾乎全部的東西,吃的超飽,可能一段時間不會吃甜食了吧我猜~

←啾啾(左)跟我(右)的傑作,啾咪跟囧 XDDD 超可愛的啦,棉花糖+巧克力醬愛不釋手

←蘋果麵包做地,也很好吃 >///<
←離開前的KUSO~ 倒掛金鉤 XD" 感覺很蠢 哈哈哈
Ps. 番外篇 ~ 到三峽吃完晚餐之後騎車回宿舍,沒想到紅燈左轉被抓到了 XD
哭哭,騎車以來第一張紅單,沒想到在元旦來臨了
XD 噴1,800...唉 Orz 以後的日子怎麼過阿 QQ
成員:我、Angie、丁丁、左左、殺手、詠寧、啾啾
好不容易熬玩歷史課回家匆匆洗了個澡便趕往中壢
抵達目的地後不久沒想到意外的來了神秘嘉賓:聰明人跟宅豪
←右手邊的看起來不只宅,還呆呆的 XD"
好不容易大家都到齊了,舟車勞苦之後都飢腸轆轆,
便東西先放在一旁沒整頓就整群先去中原夜市覓食了,
找來找去都沒找到詠寧哥哥說的"傻蛋的窩",只好作罷,
走著走著倒是意外的發現了一家"塞納河"的義大利麵店,
感覺裝潢得很溫馨,裡面的服務生也很親切,給人感覺很舒服,
出餐雖然頗久 ( XD" 吃了快兩個小時吧 ) 但是卻是平常所感受不到的悠哉,
跟米卡果然不能比 = =+ 應該說米卡真的是太不好吃了,
大推這家店的手工蛋糕,在中原夜市的三井電腦斜對面巷子進去,
←巧克力部分超美味,吃起來很綿密不會膩
有機會可以再去吃吃看,為了美食到處奔波阿 XDDDD
回去的途中還順手夾了一個長頸鹿充氣娃娃,不過卻花了五十元,
感覺是被騙錢了 =口=... 不過大家卻玩得莫名很high...XD?
←啾啾的牙突
←被小惡魔硬是戴上去的丁丁,可憐的應該是長頸鹿...
中間就是倒數跨年啦,其間還打了蠻久的桌球 XD"
沒辦法,誰叫有一半都是系桌的,哈哈哈
大家都老了 =.=.... 沒辦法通霄到天亮,
不過也可能是因為宵夜吃鐵板燒加上冰火的關係吧,天氣太冷,
/* 家樂福買的澳洲培根肉串,結果是羊肉 = = 黑店 大家以後不要去阿...不爽 */
酒足飯飽之後喝完酒暖暖地好舒服超想睡 XD
隔天中午吃了到中壢一定要吃的牛肉麵!
之前吃過了永川、老師傅牛肉麵之後,這次主打:老三牛肉麵
坦白說,我覺得比老師傅差,且又忘記弄我們點的東西,
讓我們等超久 = =... 不開心~~~~~ 不推! 還是老師傅好吃!
計畫中的重頭戲就是巧克力火鍋啦! 今年突發奇想,繼去年豆漿火鍋之後,
今年特別一點,不過因為有一半的人有事先走,QQ
所以剩下一半的人吃了幾乎全部的東西,吃的超飽,可能一段時間不會吃甜食了吧我猜~
←啾啾(左)跟我(右)的傑作,啾咪跟囧 XDDD 超可愛的啦,棉花糖+巧克力醬愛不釋手
←蘋果麵包做地,也很好吃 >///<
←離開前的KUSO~ 倒掛金鉤 XD" 感覺很蠢 哈哈哈
Ps. 番外篇 ~ 到三峽吃完晚餐之後騎車回宿舍,沒想到紅燈左轉被抓到了 XD
哭哭,騎車以來第一張紅單,沒想到在元旦來臨了
XD 噴1,800...唉 Orz 以後的日子怎麼過阿 QQ
2009年1月1日 星期四
Equalization using VC
專案→屬性→組態屬性→連結器→輸入→其他相依性 加入 gdiplus.dll
按 Enter 會依序出現

← 一開始顯示測試原圖

← 顯示原圖的灰階影像

← 經過亮度均化後的灰階影像

← 將修改過後的YIQ轉回RGB

← 直接對RGB做亮度均化,出現色偏
===========================================================
Header File
#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#ifndef _CVE_H_
#define _CVE_H_
Graphics* graphics;
Image* image;
Pen* pen;
/* RGB layers of the image */
int** i_R;
int** i_G;
int** i_B;
/* RGB layers of the image */
int** i_Red;
int** i_Green;
int** i_Blue;
/* YIQ layers of the image */
int** iY_Gray;
int** iI_Gray;
int** iQ_Gray;
/* calculation of RGB layers */
int* num_R;
int* num_G;
int* num_B;
/* probability of RGB layers */
double* pro_R;
double* pro_G;
double* pro_B;
/* probability of gray level */
double* pro_Gray;
/* calculation of gray level */
int* num_Gray;
/* decide to take which processing action */
int flag;
/* image height and width */
int i_Height, i_Width;
/* total pixels */
double i_Pixels;
#endif
===========================================================
CPP FILE
#include "CVE.h"
using namespace Gdiplus;
/* function prototype */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Clear();
void myKeys(HWND);
void OnPaint(HDC);
void Setup1();
void Setup2(HDC);
/* WinMain , the program entry point */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int iCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
/* initilize the flag to show the original image at first */
flag = 1;
/* Initialize GDI+. */
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("Equalization");
RegisterClass(&wndClass);
Setup1();
hWnd = CreateWindow(
TEXT("Equalization"), // window class name
TEXT("CVHW Equalization"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
i_Width * 2, // initial x size
i_Height * 2, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
HDC hdc = GetDC(hWnd);
Setup2(hdc);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while(1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
myKeys(hWnd);
}
GdiplusShutdown(gdiplusToken);
Clear();
return (int)msg.wParam;
}
/* WndProc */
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch(message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
OnPaint(hdc);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
/* free memory */
void Clear()
{
delete i_Red;
delete i_Green;
delete i_Blue;
delete i_R;
delete i_G;
delete i_B;
delete iY_Gray;
delete iI_Gray;
delete iQ_Gray;
delete [] num_Gray;
delete [] pro_Gray;
delete [] num_R;
delete [] num_G;
delete [] num_B;
delete [] pro_R;
delete [] pro_G;
delete [] pro_B;
}
/* keyboard events */
void myKeys(HWND hwnd)
{
static int count=2;
/* press ESC to exit program */
if(GetKeyState(27) & 0x80)
exit(0);
/* press enter to continue the next image */
if(GetKeyState(13) & 0x80)
{
flag = (count%=7)++;
InvalidateRect(hwnd, NULL, FALSE);
}
}
/* initialize_1 */
void Setup1()
{
image = new Image(L"test.jpg");
if(image->GetHeight() == 0 && image->GetWidth() == 0)
image = new Image(L"test.bmp");
i_Height = image->GetHeight();
i_Width = image->GetWidth();
}
/* initialize_2 */
void Setup2(HDC hdc)
{
graphics = new Graphics(hdc);
pen = new Pen(Color(0,0,255), 3);
i_Pixels = (double)(i_Height * i_Width);
num_Gray = new int[256];
pro_Gray = new double[256];
num_R = new int[256];
num_G = new int[256];
num_B = new int[256];
pro_R = new double[256];
pro_G = new double[256];
pro_B = new double[256];
for(int i = 0; i < 256; i++)
{
num_Gray[i] = 0;
pro_Gray[i] = 0;
num_R[i] = 0;
num_G[i] = 0;
num_B[i] = 0;
pro_R[i] = 0;
pro_G[i] = 0;
pro_B[i] = 0;
}
i_Red = new int*[i_Height];
i_Green = new int*[i_Height];
i_Blue = new int*[i_Height];
iY_Gray = new int*[i_Height];
iI_Gray = new int*[i_Height];
iQ_Gray = new int*[i_Height];
i_R = new int*[i_Height];
i_G = new int*[i_Height];
i_B = new int*[i_Height];
for(int i = 0; i < i_Height;i++)
{
i_Red[i] = new int[i_Width];
i_Green[i] = new int[i_Width];
i_Blue[i] = new int[i_Width];
iY_Gray[i] = new int[i_Width];
iI_Gray[i] = new int[i_Width];
iQ_Gray[i] = new int[i_Width];
i_R[i] = new int[i_Width];
i_G[i] = new int[i_Width];
i_B[i] = new int[i_Width];
}
}
/* image processing */
void OnPaint(HDC hdc)
{
COLORREF color;
switch(flag)
{
/* show the original image */
case 1:
graphics->DrawImage(image, 0, 0, i_Width, i_Height);
break;
/* show the gray level of the image */
case 2:
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
color = GetPixel(hdc, j ,i);
i_Red[i][j] = i_R[i][j] = GetRValue(color);
i_Green[i][j] = i_G[i][j] = GetGValue(color);
i_Blue[i][j] = i_B[i][j] = GetBValue(color);
iY_Gray[i][j] = (int)(0.299 * i_Red[i][j] + 0.587 * i_Green[i][j] + 0.114 * i_Blue[i][j]);
iI_Gray[i][j] = (int)(0.596 * i_Red[i][j] - 0.274 * i_Green[i][j] - 0.322 * i_Blue[i][j]);
iQ_Gray[i][j] = (int)(0.211 * i_Red[i][j] - 0.522 * i_Green[i][j] + 0.311 * i_Blue[i][j]);
num_Gray[iY_Gray[i][j]]++;
num_R[i_R[i][j]]++;
num_G[i_G[i][j]]++;
num_B[i_B[i][j]]++;
color = RGB(iY_Gray[i][j], iY_Gray[i][j], iY_Gray[i][j]);
SetPixel(hdc, j + i_Width, i, color);
}
break;
/* show the gray level of the image after equalizing */
case 3:
for(int i = 1; i < 256; i++)
{
num_Gray[i] += num_Gray[i-1];
num_R[i]+=num_R[i-1];
num_G[i]+=num_G[i-1];
num_B[i]+=num_B[i-1];
}
for(int i = 0; i < 256; i++)
{
pro_Gray[i] = double(num_Gray[i]) / i_Pixels;
pro_R[i] = double(num_R[i]) / i_Pixels;
pro_G[i] = double(num_G[i]) / i_Pixels;
pro_B[i] = double(num_B[i]) / i_Pixels;
}
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
iY_Gray[i][j] = (int)(pro_Gray[iY_Gray[i][j]] * 255);
i_R[i][j] = (int)(pro_R[i_R[i][j]] * 255);
i_G[i][j] = (int)(pro_G[i_G[i][j]] * 255);
i_B[i][j] = (int)(pro_B[i_B[i][j]] * 255);
color = RGB(iY_Gray[i][j], iY_Gray[i][j], iY_Gray[i][j]);
SetPixel(hdc, j, i + i_Height, color);
}
break;
/* YIQ→RGB */
case 4:
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
i_Red[i][j] = (int)(1 * iY_Gray[i][j] + 0.956 * iI_Gray[i][j] + 0.632 * iQ_Gray[i][j]);
if(i_Red[i][j]>255)
i_Red[i][j]=255;
else if(i_Red[i][j]<0)
i_Red[i][j]=0;
i_Green[i][j]= (int)(1 * iY_Gray[i][j] - 0.272 * iI_Gray[i][j] - 0.648 * iQ_Gray[i][j]);
if(i_Green[i][j]>255)
i_Green[i][j]=255;
else if(i_Green[i][j]<0)
i_Green[i][j]=0;
i_Blue[i][j]= (int)(1 * iY_Gray[i][j] - 1.105 * iI_Gray[i][j] + 0.705 * iQ_Gray[i][j]);
if(i_Blue[i][j]>255)
i_Blue[i][j]=255;
else if(i_Blue[i][j]<0)
i_Blue[i][j]=0;
color = RGB(i_Red[i][j], i_Green[i][j], i_Blue[i][j]);
SetPixel(hdc, j + i_Width, i + i_Height, color);
}
break;
/* equalize directly to each R, G, B layer */
case 5:
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
color = RGB(i_R[i][j], i_G[i][j], i_B[i][j]);
SetPixel(hdc, j, i, color);
}
break;
default:
break;
}
}
===========================================================
按 Enter 會依序出現

← 一開始顯示測試原圖

← 顯示原圖的灰階影像

← 經過亮度均化後的灰階影像

← 將修改過後的YIQ轉回RGB

← 直接對RGB做亮度均化,出現色偏
===========================================================
Header File
#include <windows.h>
#include <gdiplus.h>
using namespace Gdiplus;
#ifndef _CVE_H_
#define _CVE_H_
Graphics* graphics;
Image* image;
Pen* pen;
/* RGB layers of the image */
int** i_R;
int** i_G;
int** i_B;
/* RGB layers of the image */
int** i_Red;
int** i_Green;
int** i_Blue;
/* YIQ layers of the image */
int** iY_Gray;
int** iI_Gray;
int** iQ_Gray;
/* calculation of RGB layers */
int* num_R;
int* num_G;
int* num_B;
/* probability of RGB layers */
double* pro_R;
double* pro_G;
double* pro_B;
/* probability of gray level */
double* pro_Gray;
/* calculation of gray level */
int* num_Gray;
/* decide to take which processing action */
int flag;
/* image height and width */
int i_Height, i_Width;
/* total pixels */
double i_Pixels;
#endif
===========================================================
CPP FILE
#include "CVE.h"
using namespace Gdiplus;
/* function prototype */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Clear();
void myKeys(HWND);
void OnPaint(HDC);
void Setup1();
void Setup2(HDC);
/* WinMain , the program entry point */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int iCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
/* initilize the flag to show the original image at first */
flag = 1;
/* Initialize GDI+. */
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("Equalization");
RegisterClass(&wndClass);
Setup1();
hWnd = CreateWindow(
TEXT("Equalization"), // window class name
TEXT("CVHW Equalization"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
i_Width * 2, // initial x size
i_Height * 2, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
HDC hdc = GetDC(hWnd);
Setup2(hdc);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while(1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
myKeys(hWnd);
}
GdiplusShutdown(gdiplusToken);
Clear();
return (int)msg.wParam;
}
/* WndProc */
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch(message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
OnPaint(hdc);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
/* free memory */
void Clear()
{
delete i_Red;
delete i_Green;
delete i_Blue;
delete i_R;
delete i_G;
delete i_B;
delete iY_Gray;
delete iI_Gray;
delete iQ_Gray;
delete [] num_Gray;
delete [] pro_Gray;
delete [] num_R;
delete [] num_G;
delete [] num_B;
delete [] pro_R;
delete [] pro_G;
delete [] pro_B;
}
/* keyboard events */
void myKeys(HWND hwnd)
{
static int count=2;
/* press ESC to exit program */
if(GetKeyState(27) & 0x80)
exit(0);
/* press enter to continue the next image */
if(GetKeyState(13) & 0x80)
{
flag = (count%=7)++;
InvalidateRect(hwnd, NULL, FALSE);
}
}
/* initialize_1 */
void Setup1()
{
image = new Image(L"test.jpg");
if(image->GetHeight() == 0 && image->GetWidth() == 0)
image = new Image(L"test.bmp");
i_Height = image->GetHeight();
i_Width = image->GetWidth();
}
/* initialize_2 */
void Setup2(HDC hdc)
{
graphics = new Graphics(hdc);
pen = new Pen(Color(0,0,255), 3);
i_Pixels = (double)(i_Height * i_Width);
num_Gray = new int[256];
pro_Gray = new double[256];
num_R = new int[256];
num_G = new int[256];
num_B = new int[256];
pro_R = new double[256];
pro_G = new double[256];
pro_B = new double[256];
for(int i = 0; i < 256; i++)
{
num_Gray[i] = 0;
pro_Gray[i] = 0;
num_R[i] = 0;
num_G[i] = 0;
num_B[i] = 0;
pro_R[i] = 0;
pro_G[i] = 0;
pro_B[i] = 0;
}
i_Red = new int*[i_Height];
i_Green = new int*[i_Height];
i_Blue = new int*[i_Height];
iY_Gray = new int*[i_Height];
iI_Gray = new int*[i_Height];
iQ_Gray = new int*[i_Height];
i_R = new int*[i_Height];
i_G = new int*[i_Height];
i_B = new int*[i_Height];
for(int i = 0; i < i_Height;i++)
{
i_Red[i] = new int[i_Width];
i_Green[i] = new int[i_Width];
i_Blue[i] = new int[i_Width];
iY_Gray[i] = new int[i_Width];
iI_Gray[i] = new int[i_Width];
iQ_Gray[i] = new int[i_Width];
i_R[i] = new int[i_Width];
i_G[i] = new int[i_Width];
i_B[i] = new int[i_Width];
}
}
/* image processing */
void OnPaint(HDC hdc)
{
COLORREF color;
switch(flag)
{
/* show the original image */
case 1:
graphics->DrawImage(image, 0, 0, i_Width, i_Height);
break;
/* show the gray level of the image */
case 2:
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
color = GetPixel(hdc, j ,i);
i_Red[i][j] = i_R[i][j] = GetRValue(color);
i_Green[i][j] = i_G[i][j] = GetGValue(color);
i_Blue[i][j] = i_B[i][j] = GetBValue(color);
iY_Gray[i][j] = (int)(0.299 * i_Red[i][j] + 0.587 * i_Green[i][j] + 0.114 * i_Blue[i][j]);
iI_Gray[i][j] = (int)(0.596 * i_Red[i][j] - 0.274 * i_Green[i][j] - 0.322 * i_Blue[i][j]);
iQ_Gray[i][j] = (int)(0.211 * i_Red[i][j] - 0.522 * i_Green[i][j] + 0.311 * i_Blue[i][j]);
num_Gray[iY_Gray[i][j]]++;
num_R[i_R[i][j]]++;
num_G[i_G[i][j]]++;
num_B[i_B[i][j]]++;
color = RGB(iY_Gray[i][j], iY_Gray[i][j], iY_Gray[i][j]);
SetPixel(hdc, j + i_Width, i, color);
}
break;
/* show the gray level of the image after equalizing */
case 3:
for(int i = 1; i < 256; i++)
{
num_Gray[i] += num_Gray[i-1];
num_R[i]+=num_R[i-1];
num_G[i]+=num_G[i-1];
num_B[i]+=num_B[i-1];
}
for(int i = 0; i < 256; i++)
{
pro_Gray[i] = double(num_Gray[i]) / i_Pixels;
pro_R[i] = double(num_R[i]) / i_Pixels;
pro_G[i] = double(num_G[i]) / i_Pixels;
pro_B[i] = double(num_B[i]) / i_Pixels;
}
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
iY_Gray[i][j] = (int)(pro_Gray[iY_Gray[i][j]] * 255);
i_R[i][j] = (int)(pro_R[i_R[i][j]] * 255);
i_G[i][j] = (int)(pro_G[i_G[i][j]] * 255);
i_B[i][j] = (int)(pro_B[i_B[i][j]] * 255);
color = RGB(iY_Gray[i][j], iY_Gray[i][j], iY_Gray[i][j]);
SetPixel(hdc, j, i + i_Height, color);
}
break;
/* YIQ→RGB */
case 4:
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
i_Red[i][j] = (int)(1 * iY_Gray[i][j] + 0.956 * iI_Gray[i][j] + 0.632 * iQ_Gray[i][j]);
if(i_Red[i][j]>255)
i_Red[i][j]=255;
else if(i_Red[i][j]<0)
i_Red[i][j]=0;
i_Green[i][j]= (int)(1 * iY_Gray[i][j] - 0.272 * iI_Gray[i][j] - 0.648 * iQ_Gray[i][j]);
if(i_Green[i][j]>255)
i_Green[i][j]=255;
else if(i_Green[i][j]<0)
i_Green[i][j]=0;
i_Blue[i][j]= (int)(1 * iY_Gray[i][j] - 1.105 * iI_Gray[i][j] + 0.705 * iQ_Gray[i][j]);
if(i_Blue[i][j]>255)
i_Blue[i][j]=255;
else if(i_Blue[i][j]<0)
i_Blue[i][j]=0;
color = RGB(i_Red[i][j], i_Green[i][j], i_Blue[i][j]);
SetPixel(hdc, j + i_Width, i + i_Height, color);
}
break;
/* equalize directly to each R, G, B layer */
case 5:
for(int i = 0; i < i_Height; i++)
for(int j = 0; j < i_Width; j++)
{
color = RGB(i_R[i][j], i_G[i][j], i_B[i][j]);
SetPixel(hdc, j, i, color);
}
break;
default:
break;
}
}
===========================================================
訂閱:
文章 (Atom)