2013年11月15日 星期五

HW2

這次的作業有三個小部分 : Levels、Curve 和 Histogram

Levels 色階


  此功能可以處理影像的對比亮度。輸入四個整數值 ( InputMin . InputMax . OutputMin . OutputMax ) ,X 軸為 Input 的值,Y 軸為Output 的值,當值有變動時,就要重新畫圖以及計算。上圖中的 Original Image 為 Load 進來的圖,當 Original Image Load 進來時  New Image 也要跟著 Load 進來,不然當要執行 Level 計算時會出現 Error,因為通常 bitmap 元件在還沒放進影像時,是沒有配置記憶體的,所以會出現如下圖所示告知使用者 scan line 超出範圍。


主要程式碼
for (i=0;i<256;i++)
 {
        if ( i <= iInputMin)
               iLevelsTable[i] = iOutputMin;
else if ( i >= iInputMax )
       iLevelsTable[i] = iOutputMax;
else
        {
iInputInterval = iInputMax - iInputMin;
iOutputInterval = iOutputMax - iOutputMin;
                iLevelsTable[i] =  iOutputMin + (int)((float) iOutputInterval * (i - iInputMin) / iInputInterval + 0.5) ;
         }
 }

================================================================
Curve 曲線


  此功能和 Level很像,一樣是在處理影像的對比亮度 ,不同的地方是 Level 是給予一定的範圍,利用 InputMin . InputMax . OutputMin 和 OutputMax 計算並畫出 Level 的圖;而 Curve 則是在圖上點一點,並利用曲線公式 (y=ax^2+bx+c) 將圖上的一點帶入並連接計算出 Curve 所執行出來的結果。上圖中的 Original Image 一樣為 Load 進來的,Load 進來同時 New Image 跟著 Load 進來,避免再次出現 Error,曲線中的紅點為使用者所點的,按下 Curve Button 就會更新 New Image 的影像了。

主要程式碼

for (i=1;i<255;i++)
{
        iCurveTable[i] = (int)(( fCoeA * i * i + fCoeB * i) + 0.5);
        if (iCurveTable[i] > 255)
            iCurveTable[i] = 255;
        if (iCurveTable[i] < 0)
            iCurveTable[i] = 0;
        imCurve->Canvas->LineTo(i,255-iCurveTable[i]);
 }
 imCurve->Canvas->LineTo(255,0);

================================================================
Histogram 色彩統計直方圖


  此功能在做 Red、Green 和 Blue 三個色彩的統計,利用統計的方式可以了解到三個色彩分佈的值有多少。如上圖所示,點選要顯示出來的統計圖,並點選左上角的主選單第二個Image 裡的 Histogram (如下圖所示)就會出現色彩統計方圖。


主要程式碼
for (j=0;j<iImageHeight;j++)
{
bPtrImage = (Byte *)Image1->Picture->Bitmap->ScanLine[j];
for (i=0;i<iImageWidth;i++)
for (k=0;k<iChannelNumber ;k++)
 iHistogram[k][bPtrImage[i*3+k]]++;
}
================================================================

  這次的作業感覺起來好像很難,但大部分的程式碼都給了,所以難度降低很多,不過還是有很多小問題,像是程式打完可以執行,但為什麼執行到一半出現 Error,自己也不懂問題出現在哪,英文也只看得懂超出範圍,但不知道是什麼東西,於是將訊息截圖問老師此錯誤訊息是什麼,一問之下才知道輸出的影像要和輸入的影像一起 Load,不然影像在做 scan line時會找不到位置去記,於是我將影像輸出的地方先做和影像輸入的動作一樣 Load,就解決了超出的範圍。

  做 Level 時,要知道當值小於InputMin時,輸出值為OutputMin;值大於InputMax時,輸出值為OutputMax,這些搞混的畫圖就畫不出來,執行結果也會是錯的。

  做 Curve 前的公式推導很重要,不懂拋物線方程式的話就無法完成話曲線的動作,點一點要知道座標,並將座標帶入拋物線的公式裡,才能畫出曲線。

  做 Histogram 時,要裡用陣列存取紅、綠、藍三色的值,並利用 for 迴圈將相對應的值去做加一動作,最後輸出利用對應的畫筆顏色將對應的值畫在畫布上。

2013年11月14日 星期四

00363073石維仁 HW2

寫好了程式忘了要交報告....
這是本次的祭品
第一次的作業,呈現直條圖

由於是紅藍色系的圖所以看不太到綠色
CODE
其實一共寫了2次...第一次教的時候就寫了出來...上傳到雲端後被其他科的程式覆蓋掉了...(淚目
LEVEL後的效果
輸入的最小值由40加到50
輸入的最大值由230變為200
加入CURVE的值
在這張圖沒辦法得出很明顯的變化....

心得
其實修BUG和排版花的時間比較多,看到這些功能會覺得自己進步很多,也發現市面上的修圖軟體所需的程式能力並不高,主要需要的反而是如何想到這個點子,因為寫了這個作業還多聽到了2個半小時的自由軟體演講...算是意外中的收穫吧??




HW02


Levels是仿照photoshop裡的色階所寫出來的程式
所以最小值輸入越大顏色更黑,最大值輸入越小顏色更亮
而最小值輸出是越大顏色更亮,最大值輸出越小顏色更黑
不同的是輸入是會讓整個顏色變深(最小值越大)或曝光多寡(最大值越小),輸出則是整個顏色越來越白(最小值越大)或越來越黑(最大值越小)

原圖(沒有更動)















這是把最小值輸入調大一些,很明顯的看到整體顏色變的很深















這是把最大值輸入調小,會很明顯的感受到曝光過多















這是把最小值輸出調大一些,會看到整個顏色都比較白















這是把最大值輸出調小一些,會看到整個顏色都變暗了
>















以上就是把輸入或輸出的值調大或調小所得出來的不同結果


而這是按照老師的範例很順利寫出來的程式,也加了註解上去。雖然有四塊程式,但因為只有第一行比較有所不同,所以只貼了這張















而這是我的執行鈕的程式,一開始把iImageHeight.iImageWidth.i.j.k設在裡面,所以程式跑不動,之後放在全域才能成功執行



















接下來也是仿照photoshop裡的曲線所寫出來的Cruve
它也可以做到跟色階一樣的功能,不同的是它是用曲線來表達



原圖(沒有更動)















下圖所呈現的曲線會讓圖曝光,也等同於levels輸入值的最大值調小















而這圖所呈現的曲線代表會讓圖變白,也等同於levels輸出值得最小值調大















這圖所呈現的曲線是讓圖的色澤更深,也等同於levels輸入值的最小值調大















而這張圖所呈現的曲線是讓圖整個變暗,也等同於levels輸出值的最大值調小















因此Cruve也可以辦到levels所呈現的圖,只是一個用數字選擇,一個用曲線選擇,但之後所呈現的曲線相似的話,所影響的黑白亮暗其實是一樣的


因為老師有給範例,所以大致上程式沒問題,除了像上面所說的要放在全域而我放錯地方才會出問題。反而弄最久的是一開始沒背景顏色,曲線就像飄在上面一樣,看不到X.Y軸,然後Pagecontrol又沒辦法選背景顏色,於是查了一下發現可以用Panel放在後面然後改顏色


接下來是histogram部分,主要是用陣列去儲存三個顏色的值,然後再個別掃描就好,只不過一開始的圖長的很怪,都一樣胖,之後才發現是fHistogramScalar得值不能設太大

這是跑出來的圖



































2013年11月13日 星期三

HW02

HW02

  這次的作業是關於photoshop裡各種分析、改圖的顏色的功能~

1)
  首先一開始當然要先將圖片載入
if(OpenPictureDialog1->Execute())
Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName);


2)
a.再來我們要做的是Histogram,分析圖片裡RGB的值(0~255)各有多少

for (j=0;j<iImageHeight;j++)
{
bPtrImageRow = (Byte *)Image3->Picture->Bitmap->ScanLine[j];
for (i=0; i<iImageWidth;i++)
for(k=0;k<3;k++)
iHistogram[k][bPtrImageRow[3*i+k]]++;  down的時候為--
}

b.
  因為在這用了"原始"及"累積"的差別,所以以下為"原始"

if(RadioGroup1->ItemIndex==0)
{
for (i=0;i<256;i++)
{
iHB = int(( float(iHistogram[0][i]) * fHistogramScalar ) + 0.5);
iHG = int(( float(iHistogram[1][i]) * fHistogramScalar ) + 0.5);
iHR = int(( float(iHistogram[2][i]) * fHistogramScalar ) + 0.5);
if(CheckBox3->Checked==true){
Image4->Canvas->Pen->Color = clBlue;
Image4->Canvas->MoveTo(i*3,256);
Image4->Canvas->LineTo(i*3,256-iHB);}
if(CheckBox2->Checked==true){
Image4->Canvas->Pen->Color = clGreen;
Image4->Canvas->MoveTo(i*3+0.5,256);
Image4->Canvas->LineTo(i*3+0.5,256-iHG);}
if(CheckBox1->Checked==true){
Image4->Canvas->Pen->Color = clRed;
Image4->Canvas->MoveTo(i*3+1,256);
Image4->Canvas->LineTo(i*3+1,256-iHR);}
}
}

c.
  再來則是"累積"
if(RadioGroup1->ItemIndex==1)
{  iHB=0;iHG=0;iHR=0;    down的時候要加此程式碼不然會出錯
for (i=0;i<256;i++)
{
iHB = iHB + iHistogram[0][i];
iHG = iHG + iHistogram[1][i];
iHR = iHR + iHistogram[2][i];

if(CheckBox3->Checked==true){
Image4->Canvas->Pen->Color = clBlue;
Image4->Canvas->MoveTo(i*3,256);
Image4->Canvas->LineTo(i*3,256-iHB/5000);}

if(CheckBox2->Checked==true){
Image4->Canvas->Pen->Color = clGreen;
Image4->Canvas->MoveTo(i*3+0.5,256);
Image4->Canvas->LineTo(i*3+0.5,256-iHG/5000);}

if(CheckBox1->Checked==true){
Image4->Canvas->Pen->Color = clRed;
Image4->Canvas->MoveTo(i*3+1,256);
Image4->Canvas->LineTo(i*3+1,256-iHR/5000);}
}
}

3)












這裡做的是Level,運用數學的比例公式運算出來,再點擊Apply讓圖片作變更。
程式碼有點多就不貼出來了~













最後則是Curve,直接將滑鼠點在Image上,用到了Events裡的MouseDown,也是點擊Apply讓圖片作變更。


心得:
      這次的作業相當的精彩,自己做出來相當有成就,雖然一程式部分是老師提供的,但我想自己寫也不會寫不出來,只是會花很多時間做修正,畢竟邏輯通了,程式就容易多了。
        遇到的問題其實都不太是程式方面的問題,其中花最長時間的即是圖片檔弄錯,導致溢出記憶體,一直找不到問題,最後才發現圖片雖然也是BMP檔,但位元深度卻是8而非24。之後則遇到Histogram裡up、down的問題,關鍵的問題是在有分2種分析,原先的"原始"圖我直接分別在up、down裡做iHistogram[k][bPtrImageRow[3*i+k]]的++及--,這樣的效果即是每點一次色彩值的數目就會加減1倍,但當點選"累積"圖做down的時候卻出現異常,最後則在選到"累積"時先做iHB=0;iHG=0;iHR=0;,再進入for迴圈做畫圖,如此即解決此問題了。最後的Level及Curve因為直接複製老師的程式碼做修改,所以沒什麼問題。
        我還是認為寫程式不難,而是熟不熟悉這個開發環境,要找想用的物件每次都找好久,有滿多都是問人才知道的~












HW02

這是第二次的作業要做Histogram 的統計和Levels的畫圖。

第一張原圖
 第二張原圖的Histogram統計長條圖

第三張Levels和曲線圖
用Levels產生出來的新圖

做完了這次的作業,感覺超新奇,這些功能都跟用Photoshop修圖的結果一樣,雖然原理很簡單,但因為我對於XE2這個工具不熟加上程式能力沒有很好,讓我苦惱許久,於是請教了一些同學,最後終於做出來了,讓我覺得原來Photoshop的那些小功能並不難。

HW02

第二次的功課是Histogram
老實說   這次功課真的讓人大開眼界
學到了新的功能讓人相當開心

(這是原圖)↑

接著   利用Histogram功能
便會產生下圖這樣的色素統計
而Level功能可以改變圖片色素量
 下圖為改變後
雖然對於程式的地方還不是說非常厲害
但是對於學習者來說
問問題是個讓自己也是別人一起進步的好方法
透過問問題來學習自己不懂的
更何況能夠利用BCB就做到和PS類似的功能實為一大感動





HW02

心得感想:經過這次的作業我覺得數學其實沒有這麼無聊,因為這次的作業講到了許多以前所學的,再當時我只知道考試,根本無法體會這些數學式子到底是要表達些什麼,之後便覺得數學很枯燥乏味,而在一次又一次的程式練習中對於一些小技巧越來越熟練,也對於這套軟體更佳的熟悉他的控制項要如何使用,這次最大的進步應該是對於陣列的認知與應用,因為以前練習不多,所以一看到陣列就是要想一下,就好比數學裡有數字的時候就感覺比較簡單,當它換成 x, y 時便覺得難了些,這次的作業中複雜的部份應該是Curve ,Level,因為那牽涉到公式的推倒,不過還算是順利做出來了

HW02

  這是我這次程式的外觀,裡面有的功能包括讀檔、負片調整功能、影像長條圖資訊以及圖片色階調整功能(包括線性及曲線的)。
  首先這是我這次選的圖。

  一開始選這圖的時候原本想說長條圖資訊不會稀疏的很誇張,但用了之後我發現我錯了(真的不能相信自己的眼睛,請相信實際計算後顯示的結果)。那麼廢話就不多說了,來講解一下影像資訊的長條圖該如何求出,方法就是掃描過圖片全部的點,將RGB三個顏色在各個色階的量給累加出來,需要注意的一點是每個像素點等同於在陣列中的連續三個位置存入RGB三個顏色的數值,但儲存的順序不是RGB而是BGR。簡單說明就是假設i是像素點個數,那麼在每個3*i中存的會是該像素點藍色的數值、3*i+1中存的會是該像素點綠色的數值、3*i+2中存的會是該像素點紅色的數值。另外要掃描過全部的像素點的方法除了用傳統的Canvas->Pixels[x][y]外,還可以用scanline一行一行去讀取的方法(差異在於執行速度,scanline較快)。畫線部分是透過Image->Canvas->Pen->Color改變筆的顏色再利用MoveTo(畫布指標移至畫布某位置)和LineTo(從畫布指標目前位置移至指定位置)兩個指令來完成畫線。


  接著說明一下我寫的程式,左邊的RadioGroup1(忘了更名...)是在選擇要一般長條圖還是累加型;Channel是選擇顏色,製作方法就是透過幾個CheckBox並在程式碼中多加幾行判斷,來選擇顏色。中間的upper和downer是在調整比例,讓數值能透過人工的方式調整至最佳範圍,實作方法就是多設定一個變數,將全部數值統一乘或除這個變數,在改變這個變數就可以達成改變比例。右邊原本是想做滑鼠指到長條圖上某位置就將該點資訊顯示在Memo上,但還沒完成,如過有機會,可能會在後面幾版完成這功能。


  這就是這張圖的累積值方圖,由於點很稀疏,所以蠻平的。


  然後是Level的部分,也就是圖片色階調整功能。首先是線性的,線性的需要4個數值,分別是Input的Max及min與Output的Max及min,主要的動作是將小於InputMin的值改成OutputMin,將大於InputMax的值改成OutputMax,中間則透過這4個數值連出一條直線。其實這個只要能推導出其公式(用兩點求方程式)就很簡單。須注意的是,不要直接對每個像素點做運算,這樣做會很花時間,可以先將這256個數值經轉換後所對應的數值存起來,透過查表就可大幅加快執行效能。

PS.老師在期中考卷有錯誤,第6題第1個for迴圈應該改成
  for(i = 0;i < 256;i++)
       {
       if(i < _______)
            iLevel[i]=iOutputMin;  //題目寫iLevel[i]=0
       if(i > _______)
            iLevel[i]=iOutputMax;  //題目寫iLevel[i]=255
     .......以下略


  最後是曲線部分,曲線需要3個點,分別是(0,0)、(255,255)以及使用者自訂的點(x,y),透過這三個點可決定出一條曲線,比較麻煩也同時是我有遇到的問題是轉換,如果直接用整數形式運算可能會出問題,所以要適時地轉換成浮點數。


  以上就是這次的心得感想及程式demo。

------------------------------------------------------------------------------------------------------------

由於之前選用的圖片不太好
因此更新其他照片的結果

  首先這是範例圖片裡的企鵝圖

  這是他的原長條圖

  這是累積長條圖

2013年11月12日 星期二

作業2




這是我程式讀圖的狀況
存到Image裡面而已
memo是找bug時用的

然後是統計的結果
大致是先找出現最多RGB 然後再依比例顯示
原本覺得想要看全體的結果才這樣寫
但沒料到會有圖片大部分都是某種顏色
比例差太多,比較少的部分看不出來
應該要像老師加上調整顯示的功能比較好
這地方能再加強
再來是level的功能
這部分還沒有弄出曲線
只有弄出level的功能
當初有問題是忘記把x減掉inputMin
導致有些範圍內的值會莫名地超出限制
後來不知道我哪根筋不對
很執著地想把原圖跟改過的圖分開
但是在腦袋空想的時候實在是想不太到
只想到存的地方跟讀的地方分開
可是一直想不到怎麼弄
後來看一下程式碼
row[3*j+k]=255-row[3*j+k];
看到這段的時候突然就通了
大概是太久沒寫程式了吧
感覺把很簡單的東西忘了
但是當時有些趕
就照之前的做法開一個image然後也在讀檔的時候讀圖
主要是我怕image的大小出問題,讀檔單純為了圖的長寬
(我猜有設定image大小的指令,大概是set什麼的,但沒去查)
然後再弄一個指標只到修改區
修改區指標 = 原圖指標+某些修改動作
從原圖區讀資料,修改結果存在修改區
這樣的寫法連我自己都覺得很多餘
可是今晚沒有仔細想的時間就直接拿以前的方法來改了
levels曲線的部分後面再補上