程式碼=>https://www.dropbox.com/s/gyw71mm54tknvig/Unit1.cpp?dl=0
這次作業做色階的調整
上圖為程式介面,工具列的檔案可將圖載入進來,下方為色階的調整部分,左方是上下限輸入出調整,給定上下限的輸入輸出然後依照比例來調整,右方是二次曲線調整,輸入(X,Y)座標後畫出拋物線後根據對應的output值調整
↑圖引(http://seiga.nicovideo.jp/seiga/im3991410)
上圖(左)是以輸入下限100上限200輸出下限0上限255做色階調整後圖的樣子,顏色看起來比原圖深,上圖(右)是色階調整的曲線圖
上圖(左)是以(X,Y)=(100,150)做色彩曲線後的樣子,較原圖淺些,但不怎麼的明顯,上圖(右)是色彩曲線,是一條拋物線
程式部分,這次用了查表法來增加運算的速度,設兩個大小為256的陣列,一個給色彩調整,另一個給色彩曲線,將計算後的色彩值放到對應的位置,到時候需要轉換時只要這個陣列尋找就好,不用每個色彩值都重新計算,會省下許多時間
for(int k=0;k<256;k++)
{if(k>iInputMax)
iOneBox[k]=iOutputMax;
else if(k<iInputMin)
iOneBox[k]=iOutputMin;
else
iOneBox[k]=iOutputMin+(k-iInputMin)*((iOutputMax-iOutputMin)/(iInputMax-iInputMin));
}
上面是色彩調整的表格製作,iOneBox是儲存運算後的色彩值的陣列,iOneBox[k]的k是欲運算的色彩值,等號後面的運算後的值是轉換後的新色彩值,到時候只要把原本的色彩值帶入k,然後就可以取得轉換後的新色彩值
沒有使用查表法的話,每個色彩值都必須代入運算,這樣要運算圖片的大小*3(RGB)的次數,而查表法的話只要運算256次+查表圖片的大小*3(RGB)的次數的時間
再來為何要有k>iInputMax跟k<iInputMin的限制,因為要把色彩值限制在iOutputMax跟iOutputMin之間,而轉換公式iOutputMin+(k-iInputMin)*((iOutputMax-iOutputMin)/(iInputMax-iInputMin))是用相似三角形的比例概念推導出來的
fA=(fPointY-fPointX)/(fPointX*fPointX-255*fPointX);
fB=1-255*fA; //這裡將色階取線的輸出值建表
for(int k=0;k<256;k++){
fS=fA*k*k+fB*k;
if(fS>255)
iTwoBox[k]=255;
else if(fS<0)
iTwoBox[k]=0;
else
iTwoBox[k]=fS;
}
上面是色階曲線的表格製作,fPointX跟fPointY分別對應(X,Y)的X跟Y,fA是在計算拋物線y=ax^2+bx+c的a,fB是在計算y=ax^2+bx+c的b,在這裡y=ax^2+bx+c的c是=0,故捨去
a,b,c都算出來了,代回去原本的方程式並將(x,y)給代入(此處的x,y是色彩變數)會得出fS,而fS>255跟fS<0的限制是因為色彩值是在0~255之間,所以不能超過這個範圍
這次遇到最大的問題是轉換後的像素需要新的BYTE*去存放,原本是直接覆蓋在bPtrImageRow[3*j+k]裡面,結果出來的圖跟想像中不一樣,之後用bPtrNewImageRow[3*j+k]來存放並顯示出來,圖才正常的轉換
沒有留言:
張貼留言