2010年11月5日 星期五

HW1

這個作業就是將彩色圖片轉換成灰階影像.
灰階就是以黑與白兩基色為兩極,中間以不同黑白比例所呈現的灰黑顏色.
將影像轉成灰階後,再以不同的黑白程度來做處理.

首先將一個彩色圖片轉成256色灰階:


再將灰階圖片做處理,

以下要展示的圖為128色,64色,32色,16色,8色,4色,2色.
128就是將256色切成128個顏色,64就是將256色切成64顏色,以此類推...

128色


64色


32色


16色

這張開始已經有明顯的變化了

8色

(這是什麼碗糕)

4色

(...........)

2色

(只剩下兩顆眼睛= =")

雖然有老師提供程式碼的幫忙,但是在了解演算法的時候花了不少時間,寫程式的時候也遇到不少error,都快"起肖"了,錯的地方大多都是對演算法的不熟悉所造成的,之後也是去問同學才把bug解決完.
影像處理軟體裡的灰階功能我也會了啦!!!

HW01

首先我先把原圖以及處理過的八張圖片分別秀出來


256------------------------------------
128------------------------------------
64------------------------------------
32------------------------------------
16------------------------------------
8------------------------------------
4------------------------------------
2------------------------------------

前面幾張圖,感覺並沒有差別。不過當使用越少的灰階來表現就會很清楚的看出差異

一開始著手開始時我是先從2個灰階的部分開始寫起,但是在一開始其實是寫錯的,但是我是之後一些原因才發現。
跟上課所提到的一樣,先將範圍分成兩個部分,將0~127,128~255分類,如果是正確的處理,那麼0~127應該是變成0,而128~255是255。不過我卻將128~255設成128。我用這個錯誤的方法處理了所有的圖,所以在一開始我的圖都沒有白色的部分。
錯誤的2------------------------------------

一直到做完256、128、64感覺比較不出這幾圖的差別時,我很好奇我有沒有哪裡錯誤,去翻開課本,發現這幾張圖的差異不大是正常的,不過我卻注意到2的那張圖是白色跟黑色時我才發現我做錯了。於是我又將程式碼做了修改,將值判斷正確,這八張圖就正確的出現在我的電腦。

HW1

我的方法是把老師的彩色轉灰階256色的方法做稍微修改,索引值不變,把顏色種類變少。

這張是原本彩色的圖片













透過老師給的範例程式可以很容易的把彩色圖片轉成256色的灰階圖片。
這張是256色的灰階圖片













老師的範例程式中,調灰階色盤上索引值0~255上總共有256種顏色
我把它改成每兩個索引值一個顏色,也就是0~1一個顏色,2~3一個顏色...以此類推。
這張是128色的灰階圖片













接下來也是一樣修改灰階調色盤的索引值每4個索引值顏色一樣,這樣就可以分成64種顏色。
這張是64色的灰階圖片













剩下的也是用相同的方法去加以計算修改調色盤的顏色種類。

這張是32色的灰階圖片













這張是16色的灰階圖片













這張是8色的灰階圖片













這張是4色的灰階圖片













這張是2色的灰階圖片













因為有老師詳細的範例程式碼可以參考,所以感覺第一次作業不會太難,不過這樣修改只是單純
修改調色盤而已,圖片大小並不會因為圖片顏色的減少而變小,有點投機取巧。

HW1

因為我不確定128、64、32、16、8、4、2色的值,
是要彩色圖片轉成灰階後取轉換後的128、64、32、16、8、4、2色的值,
還是彩色圖片取128、64、32、16、8、4、2色的值之後再轉成灰階。
因此我寫了這兩部分的程式。

第一部分:
彩色圖片取128、64、32、16、8、4、2色值之後再轉成灰階。

















































































第二部分:
彩色圖片轉成灰階後取轉換後的128、64、32、16、8、4、2色的值。

















































































這次的作業我覺得非常容易,不管是第一部分或第二部分,
每個色值的判斷都只要幾行短短的程式結果就出來了。
比較需要思考的地方我認為只有如何取得128、64、32、16、8、4、2色的值,
而我研究出來的數學公式為: ( 256 * n ) / L

n: 所需的顏色數-1

L: 256 / ( n + 1 )

之後只要將計算取得色值的公式,加入程式中並加上判斷設值的轉換範圍,
這樣程式就寫完了。
程式碼如下:
for(i=0; i< iImageWidth; i++)
{
for(j=0; j< iImageHeight; j++)
{
R=GetRValue(Image1->Canvas->Pixels[i][j]); //先將圖片中的RGB個別取出
G=GetGValue(Image1->Canvas->Pixels[i][j]);
B=GetBValue(Image1->Canvas->Pixels[i][j]);

for(k=4,n=0;k<=256,n<=63;k=k+4,n++) //n為顏色數,k為強度
{
if(k-4<= R && R< k)
R=(256*n)/63; //算出該取的顏色數值
if(k-4<=G && G< k)
G=(256*n)/63;
if(k-4<=B && B< k)
B=(256*n)/63;
if(R==256)
R=255;
if(G==256)
G=255;
if(B==256)
B=255;
gray=(0.299*R+0.587*G+0.114*B);
Image64Color->Canvas->Pixels[i][j]=RGB(gray,gray,gray);
}
上面的執行結果是比較簡單的轉換法,
後來我嘗試使用直接去呼叫記憶體中的值去轉換,
但是發生了轉換後的圖改變了原本的彩色圖,
造成色彩混亂,目前這部分還在研究中。

P.S:關於呼叫記憶體發生錯誤的問題,在老師的協助下解決了。
原來只是我那部分寫得太複雜了,導致後來讀圖的時候取影響到了原本的彩色圖片。
之後聽老師上可講解老師的程式,發現我的寫法還是比較複雜,
寫得行數還是太多了,還是可以再更簡短的,這部分的能力還得再加強。

下方為聽完老師講解後修改出來的程式
for (i=0; i<256; i++)
{
pal.peRed = GrayLevel[i/4]; //在調色盤進行顏色的選取
pal.peGreen = GrayLevel[i/4];
pal.peBlue = GrayLevel[i/4];
SetPaletteEntries(GrayHandle,i,1,&pal);
}
imNew->Picture->Bitmap->Palette = GrayHandle;


for (j=0;j {
bPtrImage = (Byte *)Image1->Picture->Bitmap->ScanLine[j];
bPtrNewImage = (Byte *)imNew->Picture->Bitmap->ScanLine[j];

for (i=0;i< iImageWidth;i++)
bPtrNewImage [i]=(Byte)(0.299*bPtrImage[i*3+2]+0.587*bPtrImage[i*3+1]+0.114*bPtrImage[i*3]);
}
在執行後,比我之前寫的執行速度還要更快,而且也少了冗長的判斷,
就算判斷其它位元強度也只需要更改GrayLevel[i/4]; 紅色字的數值,
而且閱讀上也更加方便,真的事讓我受益良多,該學的還多的很。

作業一


題目: 將一張彩色影像轉成灰階影像後, 再對灰階影像進行色彩量化處理, 分別用 128 色, 64 色, 32 色, 16 色, 8 色, 4 色, 2 色(黑白影像) 顯示。

但是我只做出了2色的,很簡單的想法是把256色的灰階拆成兩半,0~127為白色而另外128~256為黑色,這就是所謂的二值化。我找了很多的資料,但是都很複雜,
有的用陣列的方法是例如:

24bit-> 16bit比较的容易,因为graylevel = 0.29 * R + 0.59 * G + 0.11 * B, 因为人的眼睛对灰度比较敏感,16bit 不能被3整除,而Green通道对灰度的贡献是比较大的,所以对Green通道的量化细一些,R:G:B = 5:6:5,Green通道多分了一个bit,就是这个道理,24bit转16bit按照如下公式即可,(C描述)
R_16Bit = R_24Bit > > 3;
B_16Bit = B_24Bit > > 3;
G_16Bit = G_24Bit > > 2; Color_16Bit = ((short)R_16Bit < <>

真的有點看不懂,所以到最後還是去看同學的心得才寫出來。找資料的時候,我總是希望有人可以提供程式碼出來,但這一切都是幻象,因為真正的程式也是別人想出來的,必須要從理論著手,不過真的思考上打結了,所以雖然大概知道概念,但總是打不出來,所以必須要多練熟BCB並且把影像處理的概念多弄熟,這樣對寫程式才有幫助,這是最近找資料遇到的瓶緊,下次我會好好的先了解一些概念,在開始打程式,而不是一開始就有人幫你打好了,而且就算有程式,沒概念的人一樣不會打。

上課之後,藉由老師的講解有把剩下的程式打出來,也做出了2bit,4bit,8bit,16bit,32bit,64bit,128bit

2bit
4bit
8bit
16bit
32bit
64bit

128bit

經過老師的講解,其實這個作業並沒有想像中的這麼難,主要就是將灰階的256色給轉換罷了,
如果要2色就將256色切成2種顏色,前面0~127為一種後面,128~255是一種,如果是4色的話就是將全部分成四個顏色也就是:0~64,65~127,128~192,192~255,所以主要是先確定要分幾個顏色,然後用for迴圈把顏色分段,例如0~64為同一種顏色65~127為一種顏色...等等,所以其實這次的作業並不難,再說這次我自己被自己給誤導,其實只要了解概念就可以寫得出來,而我一直認為要去上網找看有沒有人分享類似的程式碼,結果找的都是不一樣的,不過這也是一個經驗,至少知道以後必須要有一些概念與知識。


HW1

這是我的影像處理課的第一個作業。

題目是:將一張彩色影像轉成灰階影像後,再對灰階影像分別用 128色、64色、32色、16色、8色、4色、2色(黑白影像) 顯示。

作業展示:首先,先開啟一張bmp影像,接著再轉換成256色灰階。
(轉換完後會貼在左邊,當作對照用;右邊是稍後轉換成128、64、32...灰階影像用)























轉換完256色灰階影像後接著再點選"2色顯示",如下圖右邊就是轉換後的結果。























接著是4色顯示


8色顯示


16色顯示


32色顯示


64色顯示


128色顯示



在上面幾個圖中 2、4、8、16色可明顯觀察到與原圖256色的差距,尤其是有漸層的部分;
而 32、64、128色顯示則是幾乎分辨不出與原圖的差距,
因為從彩色轉換成灰階它的色彩範圍已大大減少。


轉換128、64、32...色部分程式碼:

一開始我們先從"2色轉換"的部分看起,是相對簡單一些的。

(因為部落格上程式碼貼上來有問題,所以用圖片)



先從最裡面開始看,兩個if分別是判斷Gray值是否介於0~127還是128~255之間,
(Gray就是影像中其中一個像素點的色彩值,因為已轉換成灰階,固Gray介於0~255之間。)

若介於0~127之間,把0~127之間的值都設成0。(0就是黑色)
若介於128~255之間,把128~255之間的值設成255。(255就是白色)

設定完後最後再把像素點印出,如此該像素點不是色彩值 0 就是 255,達成256色轉成2色的結果。
外面兩個迴圈,從頭到尾,一張影像中的每個像素點都做。

接著不管是 4色、8色、16色、32色、64色、128色也都是用此概念。

例如4色就是把兩個if變成四個if,分別針對色彩值介於0~63、64~127、128~191、192~255
來給定255*0、255*0.33、255*0.66、255*1的值。



但我們不太可能做到128色還在用128個if來寫,

因此我把這N個if用for(i = 1 ;i <= N; i++)來完成:


最裡面的迴圈就是用來做那N個if,那個if會因為N的不同而把256色切成N塊,
再宣告一個變數j0用來控制這個if做到那N塊中的哪一塊。
然後再把該像素色彩值設定成255*(Ratio*j0)。
(Ratio是把1切割成N-1塊,j0會從0跑到N)

舉個例子比較好理解,若N=4,並把最裡面的迴圈拆開,看拆開後長甚麼樣:



所以,有了這三個迴圈我只要改"存成N種顏色"的N值就可以達到存成 2色、4色、8色、16色、32色、64色、128色的需求。
但也因為是三個迴圈,時間複雜度高為缺點之一,幸好圖片不算大張,所以影響不大。

程式撰寫心得:我在寫程式前一定會有個大概的想法,並從簡單的地方開始做。
如同我先從2色先做起,想法很簡單,2色不是0(黑色)就255(白色),
我就把"比較"黑的(0~127)變成0;"比較"白的(128~255)變成255,就這樣而已。

有了2色的概念後繼續延伸出4色、8色、16色...的程式,但這裡會碰到一個問題:2色2個if,4色4個if...128色128個if,這未免太多了!
解決辦法就是用迴圈處理,而且這迴圈是有彈性的會隨N不同而改變,當然迴圈內的某些變數也會跟著改變。

這個程式還真的有點小複雜,概念不難但寫起來有挑戰性,尤其是在寫第三個迴圈時還真的有點想破頭,三個迴圈挺複雜的...

好不容易寫出來了又碰到一個恐怖的問題...就是除錯,第一次開始執行時沒有反應,也不知道為甚麼會這樣,
接著我仔細看了一遍程式看看是不是有打錯字等等,但完全看不出來,此時會產生想放棄這個方法的念頭..
到後來我只好把所有變數的值印出來,像i、j、h、w、Gray、Cut等全部印出直到找到錯誤,果然還真的把錯都找出來!

像我當初印出color值時竟然都是0,我才覺得可能這是保留字之類的所以改成ColoR,然後就沒問題了;
還有我的Ratio印出時怎麼也都是0?我就聯想到資料型態不對,應該宣告為double才對因為int只會顯示整數。

所以說我認為程式除錯時,印出變數的值是很重要的,印出來才知道值對不對,才能找到程式錯在哪,
但前提是你要清楚程式中的每個變數所代表的意義,否則你會不知道你在印甚麼!