2014年6月8日 星期日

Visible Watermark

這次作業是要自製浮水印,依然使用 python 來實作。

前言

這個好像也沒什麼演算法或什麼圖可以貼......但還是得說說是怎麼實作的。

方法

  1. 輸入圖片
  2. 轉換成 RGBA 格式
  3. 圖片剪貼
  4. 輸出圖片
其實方法很簡單,就是把原圖片和浮水印圖片都轉換成 RGBA 格式,然後藉由 Alpha 的不同來區隔。

layer = Image.new('RGBA', im.size, (0,0,0,0))
ratio = min(float(im.size[0]) / mark.size[0], float(im.size[1]) / mark.size[1])
width = int(mark.size[0] * ratio)
height = int(mark.size[1] * ratio)
layer.paste(mark, ((im.size[0] - width) / 2, (im.size[1] - height) / 2))

上面這段程式碼就是在製作 mask,完成以後將其與原圖片合起來就可以了。

結果

現在以 lena 為基準,肌肉小童當浮水印。

lena

肌肉小童


製作後如下圖:
0.5 opacity 的浮水印

感想

好實用喔,覺得開心!

2014年6月4日 星期三

顏色空間轉換

這次作業主要有兩點:

  1. RGB to HSI
  2. 膚色偵測

RGB to HSI

色相(H):

    是色彩的基本屬性,就是平常所說的顏色名稱,如紅色、黃色等。

飽和度(S):

    是指色彩的純度,越高色彩越純,低則逐漸變灰,取0-100%的數值。

亮度(I):

    亮度,取0%~100%



根據上面的公式,可以將RGB轉換成HSI,而下圖就是圖像處理後的結果。


H 通道

S 通道

I 通道



膚色檢測

在這方面,我選擇先將RGB轉換成YCbCr,然後在對其三個元素做素質上的判斷。如此一來,即可將膚色部分顯現出來。

而RGB轉換成YCbCr的公式如下圖:


在轉換完成後,根據 JORGE ALBERTO MARCIAL BASILIO et al. 所提出的 threshold 來進行檢測:


檢測結果如下:

original image

skin-only image


結論

經由這次作業,我們可以了解,圖像轉換至 YCbCr 後,確實能有效的分離出膚色部分,非常實用!


2014年5月9日 星期五

Discrete fourier transform and Filtering in spatial domain and frequency domain

這次作業主要是:
  1. Discrete fourier transform
  2. Gaussian filtering in spatial domain and frequency domain


Discrete fourier transform

DFT是傅立葉變換在時域和頻域上都呈離散的形式,將信號的時域採樣變換為其DTFT的頻域採樣。

根據 DFT 的公式,

我們可以將 2-D 的 DFT 實作出來。而第一項又分為兩種呈現方式:
  1. Spectrum
  2. Phase angle

Spectrum


第一個部分,是經由上面公式去產生出來的結果。這次的 model 是 lena,下圖就是 lena 傅利葉轉換後的頻譜樣子,為了看的更清楚,額外做了 log ,調整對比。

Spectrum

Phase angle


第二個部分則是透夠相位角來呈現,一樣是用 lena 當 model,下圖是結果,也調整過對比。

Phase angle


Gaussian filtering in spatial domain and frequency domain

高斯過濾,又稱高斯平滑,通常用它來減少影像雜訊以及降低細節層次。先看看原圖:

Original lena


Spatial domain

根據課本的步驟,首先會先產生 Gaussian mask(N*M),然後與圖做 convolution。

Spatial domain

上圖是經過處理的 lena ,明顯的可以看到其平滑的處理。

Frequency domain

頻率域相對比較複雜,首先要先將原圖做 DFT 得到 F(u, v),接著產生一個對稱的mask H(u, v) ,將其相乘後將全部 pixel 乘上  (-1) ^ (x+y),最後取其四分之一當作結果,下圖即是:

Frequency domain



從上面的結果看來,高斯確實可以達到平滑的效果。


2014年3月18日 星期二

Image Enhancement and Edge Detection

第二次作業主要是實作兩個演算法,分別是:
  1. Histogram Equalization
  2. Sobel Operator

Histogram Equalization

(圖片取自 Wikipedia

直方圖均化(Histogram Equalization),這種方法主要是將原本集中在某個區塊的機率函數(Probability Density Function),平均的分布在所有顏色上,藉此來增加圖像的全局對比度。


上圖為範例圖片,左部分是一般灰階處理,而右半部則是經過直方圖均化的產物,可以很明顯的看見其對比度的提高。接著可以看到,下圖是兩張圖片的直方圖比較表。

(直方圖)

Equalize 的主要演算法如下:
def equalize(histogram):
    lut = []
    for x in xrange(0, len(histogram), 256):
        step = reduce(operator.add, histogram[x:x + 256]) / 255
        n = 0
        for y in xrange(256):
            lut.append(n / step)
            n = n + histogram[y + x]

    return lut



Sobel Operator

在網路上 Survey 之後,發現索貝爾運算子(Sobel Operator)只是圖像處理中的運算子之一。其主要方法就是,算出影像的垂直梯度(gradient)與水平梯度兩者取絕對值相加即可。而該運算子的兩個加權函數(weighting function)是:


在知道加權函數後,我們得讓圖片的 pixel 與函數相乘

最後將其取絕對值相加

如此一來便能能夠得到結果,如下圖:


下面的程式碼是索貝爾運算子的部分核心代碼:
    # sobel weighting function
    sobelX = [-1, 0, 1, -2, 0, 2, -1, 0, 1]
    sobelY = [-1, -2, -1, 0, 0, 0, 1, 2, 1]

    # 相乘、取絕對值
    for x in xrange(1, height - 1):
        for y in xrange(1, width - 1):
            for k in xrange(3):
                for m in xrange(3):
                    tempX[k * 3 + m] = imagePixel[y - 1 + m, x - 1 + k] * sobelX[k * 3 + m]
                    tempY[k * 3 + m] = imagePixel[y - 1 + m, x - 1 + k] * sobelY[k * 3 + m]

            sharpPixel[y, x] = abs(sum(tempX)) + abs(sum(tempY))


Conclusion

這次作業完成後,原本想拿這支程式去對驗證碼進行前處理,看能不能有效的把雜訊去除,結果好像有點碰壁,希望之後了解更多後,能夠實作出來!

2014年3月8日 星期六

Image Scaling and Rotation

第一次作業,題目是影像的縮放與旋轉,重點就是操作影像的位置。而我們要實作的演算法,總共有三個:NN、Bilinear、Bicubic。

Nearest Neighbor Interpolation

(圖片取自 Tech-Algorithm

如上圖所示,這個演算法縮放圖片的方法,就是找其最近的一個鄰居,根據鄰居的顏色,來填補空缺的格子。NN追求的是簡單與快速,所以在圖片處理上相較含糊,如果放大的倍率很大的話,很容易看到鋸齒狀的結果。以下是 lena 放大三倍後的結果。

(3x lena.bmp with NN)

Bilinear Interpolation

(圖片取自 Tech-Algorithm

Bilinear與NN不同的地方是,找其最近的四個鄰居,並且根據內插法(Interpolation)去決定顏色。因此,這個縮放出來會比 NN 還要平滑,鋸齒狀的結果會比較少見,但當然只是相對少見。

(3x lena.bmp with Bilinear)

Bicubic Interpolation

Bicubic 使用鄰近十六個鄰居的像素來決定本身的值,所以相對前面兩個會比較清晰,但花費時間也久了一點。而當你將他放大看時,你能發現圖片的銳利度是比較高的。

(3x lena.bmp with Bicubic)

Image Rotation using Nearest Neighbor

這個部分,其實也可以使用 Bilinear 實作,不過比較複雜,所以就選擇了 NN。

(Rotated lena.bmp with NN)

Conclusion

在這次學習之後,讓我對於影像處理有初步的了解。個人覺得三個演算法中,就屬 Bilinear 最平衡,所需時間小於 Bicubic ,且品質大於 Nearest Neighbor。