2014年12月10日 星期三

01361030藍政歆HW3




程式碼=>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]來存放並顯示出來,圖才正常的轉換

  這次的作業比上次難了些,但還是想一想就有辦法寫出來的,比較麻煩的是公式的推導,但老師上課有講如何推導,所以實際推導一遍其實不算太難,就是要肯想肯實際去操作   

沒有留言:

張貼留言