2016年12月18日 星期日

OPENCV(12)--追蹤顏色物件並利用它來做打磚塊遊戲


        這篇文章利用之前所介紹的OPENCV基礎方法來做一個可以追蹤顏色物件的範例。
首先我用3D印表機列印一個綠色的小物件,然後用筆電的內建webcam 抓取即時影像透過OPENCV的處裡來追蹤這個綠色物件的位置。然後可以畫出他移動的軌跡。接著利用這個特點把它應用在經典遊戲打磚塊擋板的控制,當該綠色物件往右移時打磚塊裡的擋板也會跟著往右移,往左移也跟著往左移,提供一種不需透過鍵盤或滑鼠就可以隔空操作擋板的方式,增加遊戲的樂趣。實際操作請觀看底下影片連結。

  主要處理步驟如下

1.開啟Web camera 擷取影像
       _, frame = cap.read()
2. 高斯模糊
     frame = cv2.GaussianBlur(frame,(77,77),0)
3.從BGR轉成HSV 色域
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
4.設定擷取綠色物件範圍
lower_green = np.array([60,50,50])
upper_green = np.array([80,255,255])
mask = cv2.inRange(hsv, lower_green, upper_green)
5.利用找出的mask 跟原圖做 Bitwise-AND
res = cv2.bitwise_and(frame,frame, mask= mask)
6.找出輪廓
        cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
7.找出輪廓之後便可以找出其質心或是面積周長
       M = cv2.moments(cnt)


<圖一>追蹤物件並劃出軌跡



<圖二>應用在打磚塊遊戲,擋板位置會跟著綠色物件X軸位置而移動



2016年12月1日 星期四

OPENCV(11)--contours and convex hull(輪廓與凸包)


         這篇介紹OPENCV提供找出輪廓與繪製輪廓,凸包的函數。

<圖一輪廓,凸包>





 什麼是輪廓:

        輪廓可以簡單認為成將連續的點(連著邊界)連在一起的曲線,具有相同的顏色或者灰度。輪廓在形狀分析和物體的檢測和識別中很有用。

• 為了更加準確,必須使用二值化圖像。所以在尋找輪廓之前,要進行閾值化處理或者 Canny
   邊界檢測。
• 查找輪廓的函數會修改原始圖像。如果你在找到輪廓之後還想使用原始圖像的話,應該將
   原始圖像存儲到其他變數中。
• 在 OpenCV 中,查找輪廓就像在黑色背景中找超白色物體。注意,要找的物體應該是白色
   而背景應該是黑色。

OPENCV提供函數 cv2.ftndContours()找輪廓:
        它有三個參數,第一個是輸入圖像,第二個是輪廓檢索模式,第三個是輪廓近似方法。
返回值有三個,第一個是圖像,第二個是輪廓,第三個是輪廓的層析結構。
第二個返回值"輪廓"是一個Python 清單(list),其中存儲這圖像中的所有輪廓。每一個輪廓都是一個 Numpy 陣列,包含物件邊界點(x,y)的座標。

2016年11月28日 星期一

機器學習(2)--使用OPENCV SVM實作手寫辨識

 
      這一篇我們要來利用OPENCV 所提供的SVM(支援向量機)來實作手寫辨識。在程式實作中,我稍微改變了OPENCV官版原本的範例程式,除了修正在Python3.5+OPENCV3.x
build code 會error以外,程式最後並加入自己手畫的數字圖進行預測。可以使用小畫家直接手繪一20x20 pixel 黑底白字數字圖當作自己輸入預測的樣本。如下<圖一>

另外可以跟前一篇KNN做比較
機器學習(1)--使用OPENCV KNN實作手寫辨識


<圖一>上方為用小畫家手寫輸入的樣本圖片,下方是使用OPENCV SVM辨識出的結果



2016年11月22日 星期二

Conway's Game of Life in Python(使用Python實現Conway的生命遊戲)

    這篇文章提供一Python範例程式來實現Conway的生命遊戲,並使用Pygame套件實現出動畫效果。

在1970年,英國數學家約翰·康威(John Conway)創造了他的“生命遊戲”。
這是一組規則,在一殖民地裡模仿生物有機體的混亂和生長及死亡。
在“遊戲”裡由“活的”和“死的”細胞單元組成,並將演變呈現在網格上。
從這一代過到下一代的規則如下:
     在網格上以該細胞為中心計算其八個相鄰的細胞,

1.假設人口過剩:如果該"活細胞"被三個以上的活細胞包圍,它就會死亡。
2.停滯:如果活細胞被兩個或三個活細胞包圍,它可以繼續存活。
3.如果人口過少:如果活細胞被少於兩個活細胞包圍,它也會死亡。
4.繁殖:如果死細胞被正好三個細胞包圍,它將變成活細胞。

    在程式裡我們設定0為死細胞,1為活細胞,利用Numpy及Pygame做成演變動畫
透過一直循環執行這些規則,可以出現美麗和意想不到的圖案,
有些已死的區域或是長時間不再變化的區域,經由更長的時間演變
因外來的細胞將再重新活耀起來。這遊戲迷人的地方在於它不完全是
由隨機亂數產生,他有上述的幾個規則存在,但是結果又是那麼不可預期,
好像是真的生命細胞在自己演化一般,然而實質上這只是一段程式代碼。


<圖一>隨機產生的細胞自由演化



2016年11月17日 星期四

機器學習(1)--使用OPENCV KNN實作手寫辨識

 
      這一篇我們要來利用OPENCV 所提供的kNN(k-Nearest Neighbour )來實作手寫辨識。在程式實作中,我稍微改變了OPENCV官版原本的範例程式,除了修正在Python3.5+OPENCV3.x
build code 會error以外,程式最後並加入自己手畫的數字圖進行預測。可以使用小畫家直接手繪一20x20 pixel 黑底白字數字圖當作自己輸入預測的樣本。如下<圖一>

<圖一>上方為輸入的手寫樣本圖片,下方是使用OPENCV KNN辨識出的結果


OPENCV(10)--Canny Edge Detection(Canny邊緣檢測)


    這篇介紹Canny 邊緣檢測原理,即OPENCV提供的Canny演篹法函式庫並實作一範例程式
可用兩個Trackbar 去調整minVal(T1) ,maxVal(T2)閥值,可以清楚看出minVal ,maxVal閥值對Canny 邊緣的變化影響。




原理:
    Canny  邊緣檢測是一種非常流行的邊緣檢測演算法,是 John  F.Canny 在
1986  年提出的。它是一個有很多步驟形成的演算法,我們接下來逐步介紹。

Canny邊緣檢測演算法步驟:

Step 1.雜訊去除
由於邊緣檢測很容易受到雜訊影響,所以第一步是使用 5x5 的高斯濾波器 去除雜訊。

Step 2.計算圖像梯度
    對平滑後的圖像使用 Sobel 運算元計算水平方向和垂直方向的一階導數(Gx  和 Gy),
根據得到的這兩幅梯度圖(Gx  和 Gy)找到邊界的梯度和方向,公式如下:


2016年11月16日 星期三

OPENCV(9)--Image Gradients(圖像梯度)



這篇文章介紹Image Gradients(圖像梯度),Gradient(梯度)簡單來說就是求導數(微分)。
利用Gradient(梯度)可以找出圖像邊界,通常會將圖像先灰值化,而邊界就存在像素變化差異大的地方。
    例如:鄰近連續的黑像素(0)與白像素(255)之間必然存在一邊界,鄰近像素值差異越大,存在的邊界越明顯。可以把鄰近連續的像素值變化看作一函數,而利用Gradient(梯度)便可查知其形成的可能邊界。


Sobel 運算元和 Scharr 運算元

        Sobel,Scharr 可求一階或二階導數。
        Scharr 其實是Sobel在kernel 核心3X3時的優化。
        Sobel 運算元是高斯平滑與微分操作的結合體,所以它的抗雜訊能力很好。
        你可以設定求導的方向,x方向或y方向(即對X或Y作偏微分)。也可以設定使用的卷積核的大小ksize)。
        如果 ksize=-1,會使用 3x3 的 Scharr 濾波器,它的的效果要 比 3x3 的 Sobel 濾波器好
        3x3 的 Scharr 濾波器卷積核如下:

Sobel 濾波器卷積核如下:



Laplacian 運算元

         Laplacian 是求二階導數,其找出邊界效果佳,但是對於抗雜訊能力不佳。
可假設其離散實現類似於二階Sobel 導數,事實上,OpenCV 在計算拉普拉斯運算元時直接調用Sobel 算子。計算公式如下:


拉普拉斯濾波器使用的卷積核:

OpenCV 提供了這種不同的梯度濾波器,或者說高通濾波器。Sobel,Scharr 和 Laplacian。
使用到的函數為:cv2.Sobel(),cv2.Schar(),cv2.Laplacian()        
下圖為其程式範例結果:

<圖一>Sobel ,Scharr ,Laplacian 


2016年11月14日 星期一

OPENCV(8)--Histogram & Histograms Equalization(長條圖與長條圖均衡化)


        這篇文章介紹長條圖原理及OPENCV對長條圖的處裡,包含如何均等化長條圖。

長條圖原理:
        什麼是長條圖呢?通過長條圖你可以對整幅圖像素的分佈有一個整體的瞭解,特別是對灰階圖。
        長條圖的 x 軸是灰度值0(黑) 到 255(白),y 軸是圖片中相同灰度值數量。
透過長條圖我們可以 對圖像的對比度,亮度,灰度分佈等有一個直觀的認識。

   如下<圖一> 左上圖為一對比不強烈的原圖,其對應的右上角長條圖可以看出像素值大多集中在中間像素,通常一張亮度,對比均衡的圖片應當像左下角,而可以看出其對應的右下角長條圖可以看出像素值分布較為均衡。而實際上在圖中下方圖片是經過長條圖均衡化後的結果,底下即來介紹如何用OPENCV,Numpy,MatplotLib來製作長條圖。

<圖一>





2016年11月6日 星期日

OPENCV(7)--2D Convolution ,Image Filtering and Blurring (旋積,濾波與模糊)


        這篇介紹OPENCV提供的對影像作空間濾波的工具,透過2D Convolution(旋積或譯卷積),可以達到對影像作濾波的功能,而對影像實施低通濾波(LPF),實質上就是對影像作去除雜訊,模糊化的作用,而高通濾波(HPF)實質上對影像的作用就是銳利化,以及可以凸顯出影像的邊緣。

2D Convolution 

        跟信號一樣,我們也可以對 2D 圖像實施低通濾波(LPF),高通濾波(HPF)等。OpenCV 提供的函數 cv.ftlter2D() 可以讓我們對一幅圖像進行卷積操作。
如下圖<一>我們對一幅圖像做Convolution (旋積),底下是使用一個 3x3 kernel (核)的運算範例圖。

        操作如下:將核放在原圖像的一個像素A 上,求與核對應的圖像上 3x3個像素的和,用這個值替代像素 A 的值。重複以上操作直到 將圖像的每一個像素值都更新一遍。

圖<一>2D Convolution演算法

此圖來源:



人工神經網路(2)--使用Python實作後向傳遞神經網路演算法(Backprogation artificial neature network)

     這篇文章介紹後向傳遞神經網路演算法(Backprogation artificial neature network),並使用Python語言實作實現一XOR邏輯功能的多層網路模型。
     在底下前一篇文章單一神經元感知器的實作上知道,單一感知器無法實作出具XOR邏輯運算的功能,在這篇會改用多層網路模型並使用後向傳遞神經網路演算法(Backprogation artificial neature network)來實現XOR的邏輯功能。

人工神經網路(1)--使用Python實作perceptron(感知器)


多層神經網路:

          多層感知器是有一個或是多個隱含層的神經網路,通常網路包含一個來源神經元的輸入層,至少包含一個計算元的隱含層,以及一個計算神經元的輸出層,輸入號信一層一層的向前傳遞,這動作也稱之為前饋式傳遞神經網路,其模型如下圖<一>所示
          多層神經網路,各層多有其特定的功能,輸入層為接受外部的輸入信號,輸出層從隱含層接受輸出信號,為整個網路建立輸出形樣類別。
          隱含層的神經元發現特徵,其權重表示了其輸入型樣中的特徵,輸出層再根據這些特徵確定輸出型樣。
          利用一個隱含層,可以表示輸入信號的任何連續ˋ函數,利用兩個隱含層甚至可以表示不連續的函數,換言之,多個隱含層也可以解決單一感知器只能做單一線性分割的問題。


<圖一>有兩個隱含層的多層感知器神經網路



多層神經網路如何學習?

           最常用的是後向傳遞神經網路演算法,在1969年被首次提出(Bryson和Ho),但是由於對計算要求過於嚴苛而被忽略,直到20世紀80年代這種演算法才又被重新重視。
          多層網路的學習過程與感知器類似,提供輸入信號經過權重調節加總,計算出實際輸出,跟期望輸出比較算出誤差,再藉由調整權重來減小收斂誤差。
         在感知器中,每個輸入Xi僅有一個相對應的權重Wi和一個輸出Y,但在多層神經網路中,每一個權重對每一個輸出都有貢獻,而每一個輸入信號Xi,連接到各隱含層的神經元都有相對應的權重Wij,每個隱含層輸出也會有相對應的Wjk連結到每個輸出Yk,如下<圖二>所示:
         其中i為輸入層第i個輸入,j表示隱含層第j個神經元感知器,k為輸出層第k個輸出。
在後向傳遞網路中,學習演算法過程分為兩個階段,第一階段與感知器前饋式演算雷同,信號由輸入端向隱含層一層一層傳遞直到輸出層,如果實際輸出與預期的輸出不同,則計算其誤差,而第二階段則是將此誤差反向從輸出端經過隱含層再傳遞回輸入層,在這過程則同時調整其權重Wjk和Wij。反覆這樣的動作直到誤差收斂到一定的滿足條件值。


<圖二>三層後向傳遞網路