顯示具有 02360635 鄭瑞銘 標籤的文章。 顯示所有文章
顯示具有 02360635 鄭瑞銘 標籤的文章。 顯示所有文章

2017年1月15日 星期日

02360635 鄭瑞銘 Homework3

色階與曲線調整

色階與曲線調整的操作介面
色階調整使用四個文字輸入框
曲線調整則是點擊白色畫布的任一處


色階調整

圖片的原色彩值(Input)和修改後的色彩值(Output)之間有著這樣的等式:

(Output - Output Min) / (Output Max - Output Min) = (Input - Input Min) / (Input Max - Input Min)


將等式左邊留下Output之後得到此公式:

色階調整的參考公式

接下來的實驗會用:
(Input Min, Input Max, Output Min, Output Max)來表示測試時輸入的數值


從式子來看,Input Max - Input Min會使Output產生無限大的數值,
實際測試 (0, 0, 0, 255) 之後程式也跑出警告視窗告訴我除數不得為零



(50, 200, 0, 255)的組合:
(50, 200, 0, 255)對照(0, 255, 0, 255)

因為(200 - 50) < (255 - 0),
除數變小的關係,使得圖片整體變亮


(0, 255, 50, 200)的組合:
(0, 255, 50, 200)對照(0, 255, 0, 255)

因為(200 - 50) < (255 - 0),
乘數變小,使得圖片較為黯淡


(0, 255, 255, 0)的組合:
(0, 255, 255, 0)對照(0, 255, 0, 255)

試著讓(Output Max - Output Min) < 0、(Input Max - Input Min) > 0,結果一整個負片的感覺



曲線調整

由一條經過(0, 0)、(255, 255)和自定義的(x, y)的二次曲線,X軸=Input、Y軸=Output,來調整色彩值。
這部分在撰寫程式時卡了很久,點擊畫布時畫布和圖片都沒反應,最後發現我定義的(x, y)是整數型態,而計算過程多使用浮點數,所以將(x, y)強制轉型成浮點數之後終於能對圖片做色彩調整。

試驗:


(y遠大於x)、(y大於x)、(x=y)
(x大於y)、(x遠大於y)


視覺效果來說我覺得曲線調整比色階調整來得舒適。

2017年1月14日 星期六

02360635 鄭瑞銘 Homework1

影像處理的相關應用程式介紹

使用軟體:Easy Paint Tool SAI

產品LOGO

這款軟體是我從友人那邊得知而來,一款適合電繪新手使用的繪圖軟體,硬要說的話它就像功能強化版的小畫家。
對我這個電繪菜鳥來說它有許多直覺性且簡易操作的介面,像是畫面放大和縮小可以用滑鼠滾輪來操作,方向鍵可以將畫面上下左右移動……
嚴格上它是繪圖軟體,相較於專門處理相片的應用程式來說,SAI撇開了畫筆工具之後能對相片的處理並不多

所以我主要實驗它的濾鏡功能。

操作介面&濾鏡功能




濾鏡→色相/飽和度


色相(可調整範圍:-100~+100)
(實驗數值:-50、0、+50)


飽和度(可調整範圍:-100~+100)
(實驗數值:-100、0、+100)


明度(可調整範圍:-100~+100)
(實驗數值:-50、0、+50)



濾鏡→亮度/對比度


亮度(可調整範圍:-100~+100)
(實驗數值:-50、0、+50)


對比度(可調整範圍:-100~+100)
(實驗數值:-50、0、+50)


顏色濃度(可調整範圍:-100~+100)
(實驗數值:-100、0、+100)

現在用起來,明度和亮度、飽和度和顏色濃度,這兩組的效果滿相近的

然後色相的功能自己用SAI內的其他功能觀察了色彩變化,似乎是在0~256的範圍內,照著R、G、B的順序對單一色彩值調整。

個人比較好奇的是對比度的定義,數值調到-100的時候整張圖變灰色、+100則是接近全黑,不太明白對比度想要表達什麼。

2016年12月28日 星期三

02360635 鄭瑞銘 Homework 5

空間濾波—平滑化、銳利化

使用的方法相同,都是以目標像素和周邊九宮格內的像素,經由相關式子做計算。

參考公式:



原先只使用了兩個TImage元件分別命名為imgShowimgOrigin,用來貯存修改後的圖片以及原始圖片,這邊為了能重複對圖片做平滑或銳利,平滑銳利交互處理,另外加入了TImage元件命名為imgStore,原因是imgOrigin設定上是我不想要去更動的圖片資料,若要重複對圖片修改的話需要另外設一個空間來貯存每次修改前的圖片資料。

然後這個功能主要是使用imgShowimgStore,所以平滑化和銳利化處理中都有添入隱藏imgOrigin、顯示imgStore的程式碼。


為此功能增加的變數宣告:

BYTE *bPictureImageStoreRow;  // 貯存修改前的色彩值

BYTE *bPictureImageRow0; // i -1
BYTE *bPictureImageRow1; //目標像素所在的第 i
BYTE *bPictureImageRow2; // i +1
int iSum;



平滑化處理函式:

void __fastcall TForm1::miSmoothingClick(TObject *Sender)
{
if ( imgOrigin->Visible )
{
        imgOrigin->Visible = false;
        imgStore->Visible = true;
}

//貯存修改前的圖片資料
for (i = 0; i < iImageHeight; i++)
{
        bPictureImageStoreRow = (Byte*)imgStore->Picture->Bitmap->ScanLine[i];
        bPictureImageShowRow = (Byte*)imgShow->Picture->Bitmap->ScanLine[i];
        for (j = 0; j < iImageWidth; j++)
        {
                bPictureImageStoreRow[3*j+0] = bPictureImageShowRow[3*j+0];
                bPictureImageStoreRow[3*j+1] = bPictureImageShowRow[3*j+1];
                bPictureImageStoreRow[3*j+2] = bPictureImageShowRow[3*j+2];
        }
}

//平滑化處理
for (i = 1; i < iImageHeight-1; i++)
{
        bPictureImageShowRow = (Byte*)imgShow->Picture->Bitmap->ScanLine[i];
        bPictureImageRow0 = (Byte*)imgStore->Picture->Bitmap->ScanLine[i-1];
        bPictureImageRow1 = (Byte*)imgStore->Picture->Bitmap->ScanLine[i];
        bPictureImageRow2 = (Byte*)imgStore->Picture->Bitmap->ScanLine[i+1];
        for (j =1; j < iImageWidth-1; j++)
        {
                for (k = 0; k < 3; k++)
                {
                iSum = bPictureImageRow0[3*(j-1)+k] + bPictureImageRow0[3*j+k] + bPictureImageRow0[3*(j+1)+k]
                         + bPictureImageRow1[3*(j-1)+k] + bPictureImageRow1[3*j+k] + bPictureImageRow1[3*(j+1)+k]
                         + bPictureImageRow2[3*(j-1)+k] + bPictureImageRow2[3*j+k] + bPictureImageRow2[3*(j+1)+k];

                bPictureImageShowRow[3*j+k] = iSum / 9;
                }
        }
}
imgShow->Refresh();
imgStore->Refresh();
}



銳利化處理函式:

void __fastcall TForm1::miSharpingClick(TObject *Sender)
{
if ( imgOrigin->Visible )
{
        imgOrigin->Visible = false;
        imgStore->Visible = true;
}

//貯存修改前的圖片資料
for (i = 0; i < iImageHeight; i++)
{
        bPictureImageStoreRow = (Byte*)imgStore->Picture->Bitmap->ScanLine[i];
        bPictureImageShowRow = (Byte*)imgShow->Picture->Bitmap->ScanLine[i];
        for (j = 0; j < iImageWidth; j++)
        {
                bPictureImageStoreRow[3*j+0] = bPictureImageShowRow[3*j+0];
                bPictureImageStoreRow[3*j+1] = bPictureImageShowRow[3*j+1];
                bPictureImageStoreRow[3*j+2] = bPictureImageShowRow[3*j+2];
        }
}

銳利化處理
for (i = 1; i < iImageHeight-1; i++)
{
        bPictureImageShowRow = (Byte*)imgShow->Picture->Bitmap->ScanLine[i];
        bPictureImageRow0 = (Byte*)imgStore->Picture->Bitmap->ScanLine[i-1];
        bPictureImageRow1 = (Byte*)imgStore->Picture->Bitmap->ScanLine[i];
        bPictureImageRow2 = (Byte*)imgStore->Picture->Bitmap->ScanLine[i+1];
        for (j =1; j < iImageWidth-1; j++)
        {
                for (k = 0; k < 3; k++)
                {
                iSum = 5 * bPictureImageRow1[3*j+k]
                         - bPictureImageRow0[3*j+k]
                         - bPictureImageRow1[3*(j-1)+k] - bPictureImageRow1[3*(j+1)+k]
                         - bPictureImageRow2[3*j+k];
                /*
                iSum = 9 * bPictureImageRow1[3*j+k]
                         - bPictureImageRow0[3*(j-1)+k] - bPictureImageRow0[3*j+k] - bPictureImageRow0[3*(j+1)+k]
                         - bPictureImageRow1[3*(j-1)+k] - bPictureImageRow1[3*(j+1)+k]
                         - bPictureImageRow2[3*(j-1)+k] - bPictureImageRow2[3*j+k] - bPictureImageRow2[3*(j+1)+k];
                */
                if (iSum > 255)
                        bPictureImageShowRow[3*j+k] = 255;
                else if (iSum < 0)
                        bPictureImageShowRow[3*j+k] = 0;
                else
                        bPictureImageShowRow[3*j+k] = iSum;
                }
        }
}
imgShow->Refresh();
imgStore->Refresh();
}


部分運行畫面:

功能建置在Image->Filtering選單下



平滑化運行畫面




銳利化運行畫面




02360635 鄭瑞銘 Homework 6

YUV色彩調整

這功能的操作主要是先產生一個可以設定YUV色彩值的畫布(實際上只選擇UV值,Y值預設128),然後根據RGBYUV的色彩值轉換公式來製作此功能,不過在執行YUV色彩調整時,還需要多一個動作去取得每一個圖片像素的Y(RGB值轉Y)

RGBYUV色彩轉換公式,這裡使用整數型態的轉換方法:





根據YUV色彩調整所新增的變數宣告:

BYTE *bPictureImageYUVRow;  //產生畫布所使用的變數,
int iR,iG,iB;
int iY,iU,iV;
int iC,iD,iE;

以及新增的TImage元件命名為imgUV,用來產生選取YUV色彩值的畫布。



產生YUV色彩值畫布的程式碼我把它放在開啟圖片的函式裏頭,X軸代表U值、Y軸代表V值,如下:

//YUV色彩值畫布,Y = 128
imgUV->Picture->Bitmap->Height = 256;
imgUV->Picture->Bitmap->Width = 256;
imgUV->Picture->Bitmap->PixelFormat = pf24bit;
for (i = 0; i < 256; i++)
{
    bPictureImageYUVRow = (Byte*)imgUV->Picture->Bitmap->ScanLine[i];
    for ( j = 0; j < 256; j++)
    {
    iY = 128;
    iU = j;
    iV = i;

    iC = iY - 16;
    iD = iU - 128;
    iE = iV - 128;

    iR = ( (298 * iC          + 409*iE + 128) >> 8 );
    //防止溢位
    if ( iR > 255 )
        iR = 255;
    else if ( iR < 0 )
        iR = 0;

    iG = ( (298*iC - 100*iD - 208*iE + 128) >> 8 );
    //防止溢位
    if ( iG > 255 )
        iG = 255;
    else if ( iG < 0 )
        iG = 0;

    iB = ( (298*iC + 516*iD          + 128) >> 8 );
    //防止溢位
    if ( iB > 255 )
        iB = 255;
    else if ( iB < 0 )
        iB = 0;

    bPictureImageYUVRow[ 3 * j + 2 ] = iR;
    bPictureImageYUVRow[ 3 * j + 1 ] = iG;
    bPictureImageYUVRow[ 3 * j + 0 ] = iB;
    }
}
imgUV->Refresh();



執行YUV色彩調整的函式根據imgUV發生Mouse Down事件時啟用,程式如下:

void __fastcall TForm1::imgUVMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
iU = X;
iV = Y;

for (i = 0; i < iImageHeight; i++)
{
    bPictureImageShowRow = (Byte*)imgShow->Picture->Bitmap->ScanLine[i];
    bPictureImageOriginRow = (Byte*)imgOrigin->Picture->Bitmap->ScanLine[i];
    for ( j =0; j < iImageWidth; j++)
    {
        bPictureImageShowRow[ 3 * j + 0] = bPictureImageOriginRow[ 3 * j + 0 ];
        bPictureImageShowRow[ 3 * j + 1] = bPictureImageOriginRow[ 3 * j + 1 ];
        bPictureImageShowRow[ 3 * j + 2] = bPictureImageOriginRow[ 3 * j + 2 ];

        iY = ( ( 66 * int( bPictureImageShowRow[3*j+2] )
           + 129 * int( bPictureImageShowRow[3*j+1] )
           +  25 * int( bPictureImageShowRow[3*j+0] ) + 128 ) >>8 ) + 16;

        iC = iY - 16;
        iD = iU - 128;
        iE = iV - 128;

        iR = ( (298*iC          + 409*iE + 128) >> 8 );
        //防止溢位
        if ( iR > 255 )
            iR = 255;
        else if ( iR < 0 )
            iR = 0;

        iG = ( (298*iC - 100*iD - 208*iE + 128) >> 8 );
        //防止溢位
        if ( iG > 255 )
            iG = 255;
        else if ( iG < 0 )
            iG = 0;

        iB = ( (298*iC + 516*iD          + 128) >> 8 );
        //防止溢位
        if ( iB > 255 )
            iB = 255;
        else if ( iB < 0 )
            iB = 0;


        bPictureImageShowRow[3*j+0] = iB;
        bPictureImageShowRow[3*j+1] = iG;
        bPictureImageShowRow[3*j+2] = iR;
    }
}
imgShow->Refresh();

}


部分運行畫面:







可以的話之後想在YUV畫布上產生一個十字記號,用來標示自己剛剛點選的UV值是哪一個。