OpenGL 閱讀筆記 (二) OpenGL基本操作

這邊虎喵跳過glfw/glew的初始化,
先來提一下OpenGL的基本操作方式

前面也提到過, OpenGL是一個類C的語言,
因此使用C/C++的攻城獅們應該會感到很熟悉.
OpenGL的基本動作循環如下:


每一行code的解釋如下:

// 本地變數, 用來獲取操作物件的索引值(index)
int object;

// 向OpenGL獲取對應的index, 數量numbers可以自己指定, 需要跟你傳進來的object指針匹配 
// 由於此時帶進來的object只有一個int, 因此這邊number會填1
glGenXXXObject(OBJECT_NUMBERS, &object);

// 綁定該index到操作物件上, 操作物件的類型都是OpenGL定義好的, 需要依照使用來選擇
glBindBXXXObject(SOME_OPENGL_DEFINED_TARGET, object);

// 將資料傳送對應的操作物件上面
glBufferData(SOME_OPENGL_DEFINED_TARGET, sizeof(YOUR_DATA), YOUR_DATA, object);

// 解綁操作物件
glBindBXXXObject(SOME_OPENGL_DEFINED_TARGET, 0);

// 釋放操作物件
glDeleteXXXOject(OBJECT_NUMBERS, &object);

從上述的流程我們也可以看出:
真正負責管理物件的人是OpenGL
我們從CPU端可以做的事情是向OpenGL索取操作物件的index,
在CPU操作的時候都需要透過這個index來進行.

有了這個基本概念以後,
我們接著開始介紹繪製圖形必要的兩個著色器 (Shader)
只要使用這兩個著色器就可以畫出圖形了~

OpenGL 閱讀筆記 (一) 基礎工作環境

最近虎喵要開始學習OpenGL啦~
做為自己的閱讀筆記與心得, 希望也能幫助到各位

1. OpenGL是幹啥用的?

OpenGL = Open Graphics Library
顧名思義, 是開放圖形函式庫
主要的功能是用來繪製2D/3D向量圖形
OpenGL是一個規範, 定義了對應的API要有的行為, 與平台/開發語言沒有相關性.

儘管OpenGL的實作可以完全依靠軟體實現, 但它其實是為了硬體加速而設計的,
跟平台相關的細節將由不同的作業系統進行實現,
而OpenGL的硬體加速支援則是由顯卡廠商負責實現.

OpenGL的定義方式類似於C語言, 但他是語言獨立的,
因此你可以看到不同的開發語言上都對於OpenGL的使用進行了封裝.
(例如你可以在開發Android Apps使用Java的GLES20類別來呼叫OpenGL)

2. GLEW 與 GLFW

聽從丁小喵的建議, 我的開發環境是使用Ubuntu 14.04, 搭配的IDE是Eclipse
如果要直接使用OpenGL的函式庫的話, 必須要先抽取出相關函式,
像是這樣:

const char *name = "glGenBuffers";
void *p = (void *)wglGetProcAddress(name);
if (p == 0 ||
   (p == (void*)0x1) || (p == (void*)0x2) ||
   (p == (void*)0x3) || (p == (void*)-1)) {
 HMODULE module = LoadLibraryA("opengl32.dll");
 p = (void *)GetProcAddress(module, name);
}

如果每個Function都要這樣幹一次就太疲勞了,
GLEW (OpenGL Extension Wrangler Library) 已經幫你幹好這件事情啦
只要編譯的時候連結到glew的函式庫, 加上對應的header就可以無痛使用

再來是剛剛提到的平台無關的特性, 這點就交給GLFW完成囉!
可以到GLFW的官網下載對應OS的函式庫, 當然他也有提供Source code可以自行編譯.
設置好這兩個函式庫之後就可以開發啦, 這時候你的.cpp內會有

// GLEW (Warp the GL library, you don't need to retrieve function by yourself)
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW (Setup the window which support OpenGL operation on different platform)
#include <GLFW/glfw3.h>

這樣就完成最基礎的開發環境設置囉!

[OPENCV] FaceDectection - (四) 模型訓練

前面幾篇關於FaceDetection的文章已經介紹如何應用openCV內建的 library
以及分析臉部辨識所需要的xml檔案

這一篇文章將會介紹如何產生出 xml 檔案提供給 openCV使用

獲取人臉資料庫

因為要重新訓練出模型, 因此需要有大量的人臉圖案
喵使用了FERET的資料庫

[OPENCV] FaceDectection - (三) 實務剖析

HaarCascade Xml

的程式碼當中, 最主要的參數是去讀取 haarcascade_frontalface_alt.xml
1
2
3
4
5
6
7
8
9
int main(int argc, char** argv) {

  // Load preconstructed classifier
  face_cascade.load("data/haarcascade_frontalface_alt.xml");
  Mat inputImage = imread(argv[1]);
  detectFaces(inputImage);
  waitKey(0);
  return 0;
}

這邊開始, 喵要詳細的解構這xml檔案
一開始的對於整個cascade的參數

<opencv_storage>
<cascade type_id="opencv-cascade-classifier"><stageType>BOOST</stageType>
  <featureType>HAAR</featureType>
  <height>20</height>
  <width>20</width>
  <stageParams>
    <maxWeakCount>213</maxWeakCount></stageParams>
  <featureParams>
    <maxCatCount>0</maxCatCount></featureParams>
  <stageNum>22</stageNum>


FeatureType: HAAR / LBP / HOG
Height: Mask 高度
Widht: Mask 寬度
stageParams --> maxWeakCount: 最多有幾個weak nodes in a classifier
maxCatCount: 最多串幾個 nodes (設定為0, 代表沒有使用串接)
stageNum: 共有多少個 Stage

[ML] Back propagation 推導

我們來推導一下 Back propagtion 的公式,
首先先設想一個只有兩層的 Neural network 如下:



從上圖我們先列出公式如下:

Z = a * W'
hx = sigmoid( Z )

由前面的經驗我們可以得到,
當我們要對 W 進行更新來最小化分類誤差時, 使用 Gradient descent 來更新 W.

那麼如何求出 W 的 Gradient 呢?
我們可以把這個式子使用連鎖律展開!

第一個跟你的Cost function直接相關的是 output layer (a)
而 a 又是經過 sigmoid (z) 得到的
那 z 就可以跟Wij扯上關係啦!
這樣就可以把式子展開如下:

第一層的微分項, 也就是你的 Cost function 對 prediction value 微分, 可以得到 (y - a)
第二層的微分項, 可以得到 a * (1-a)
第三層的微分項則是可以得到再上一層的output layer a

那麼如果再看到上一層的 Wij 呢?
我們看到回到上述第三層的 partial z 部分, 我們知道它是由前一層的 a * Wij 來的,
所以我們在這邊使用連鎖律再把它展開, 可以得到下面的式子

 

依此類推就可以得到每一層權重 W 的 gradient 項了~

[OPENCV] FaceDectection - (二) 深入研究

深入研究演算法

為了能夠即時地計算出Face, 使用了三個的方式來達到目的
1. Integral Image
2. AdaBoost
3. Cascade filter

Integral Image - 積分圖

當計算一個圖像當中某個區域的積分

按照正常的方法, 開始累加每一點的值

這樣子計算量跟所要計算的區域成正比, 如果是一個 NxN的圖案, 那麼複雜度會是 O(N^2)
integral image提供了一種方式可以將計算複雜度簡化到一個常數 O(c)
怎麼做到的呢?

[OPENCV] FaceDetection - (一) 初步探索


Face Detection Example

今天喵把課題提升到 FaceDetection的 Level
感覺FaceDetection是個非常高深的題目
不過, 使用了openCV所提供的 library, 喵一下子就做到了臉部偵測~
主程式為
int main(int argc, char** argv) {

  // Load preconstructed classifier
  face_cascade.load("data/haarcascade_frontalface_alt.xml");
  Mat inputImage = imread(argv[1]);
  detectFaces(inputImage);
  waitKey(0);
  return 0;
}

[ML] 想到就寫 - Octave 的眉眉角角 (一) 用 index 取值?

先拋開 Octave, Machine Learning 這些學問,
我們用 Word 或是 Excel 這些文書處理軟體工作的時候, 一般習慣把資料做下列樣子的編排:

No.HeightWeightAge
11708030
21757035
=> 以資料的"內容物來說" (我們去掉標題跟No.), 這是一個 2 x 3 的矩陣,
表示有2筆資料, 而每一筆的元素有3個.

我們用 Octave 儲存資料的時候, 令 T 等於上述這個 2 x 3 的表格,
使用 T(1, :) 可以取出第一行的資料 (Row = 1, Colume = 1~3)
T(1, :) == T(1, 1:3) => [170, 80, 30]

但是, 使用T(1:3) 的話會取出甚麼?
T(1:3) => [170, 175, 80]

 何...だと...!!

在Octave裡面, 預設的處理方式都是以向量 (Vector) 的形式來呈現,
所以用 sum 來加總上面的 T 表格時, 你會得到 [345 150 65]
=> 對每一個 Column 做 Summation
(從資料的形式來看, 同屬一列 Column 的單位也都會是相同的, 所以這個操作其實蠻合理的)

所以在取一個陣列的值的時候, 盡量避免直接用 index 的方式來拿取,
還是乖乖地使用陣列的表示法吧!

Example. 對表格T進行正規化:

取得每一個 Column 的 mean:
    meanT = sum(T) ./ size(T,1) ==> mean(T)

取得每一個 Column 的 variance
    varT = sum((T - meanT).^2) ==> var(T)

取得每一個 variance 的平方根
    sqrtT = varT .^ 0.5 ==> sqrt(T)

進行正規化:
nT = (T - meanT) ./ sqrtT

[OPENCV] Gaussian Filter

在一些圖形分析上我們使用到了Gaussian Filter (如 Edge Detect)
這一篇就要來介紹

Gaussian Filter

Gaussian Filter的用途是在模糊圖片

這道理是因為圖片上通常都會有雜點, 雜點會造成誤判, 另外一個方面是要降低細節, 因為細節太過突兀也會造成誤判, 為了降低這些問題, 因此才會導入了一種方式來模糊圖片

[ML] Regression Analysis 的基本概念 (一) Linear Regression

依照使用情境來說, 我們可以將機器學習問題分成兩類, 預測以及分類:

[預測問題]
豪斯先生手上有1000筆已經成交房屋的資料, 它的內容會有房間數目, 地坪大小, 房屋年齡...等
還有他最關心的成交價格.
他希望用這1000筆資料來預估看看, 如果給定這些資料, 那麼成交的價格大概可以落在哪邊.

[分類問題]
邁爾先生的信箱裡面有一些關於財務的信, 一些廣告垃圾, 一些旅遊訊息
他希望可以讓信件自動分類成三群, 方便查找.

[ML] 在 Windows 環境下使用 Octave (一)


在學習 Machine Learning 時, 通常大家都會使用 Matlab 與 Octave 來進行程式的運算.
Octave 也是直譯式的語言, 最初它的目標就是提供一套相容於 Matlab語法的 free software,
所以如果你已經學過了 Matlab, 那麼使用 Octave 對你來說應該不是太大的問題.

[OPENCV] Camera capture

今天要介紹的東西很容易
相對於之前一個所介紹的 Trackbar, 這次要介紹的就像是一塊小蛋糕 (a piece of cake)

Camera Capture

使用openCV最大的好處, 就是方便
人家都說我們要在站在巨人的肩膀上
在這裡就體現了這句話

喵這次主要介紹的就是
VideoCapture

[OPENCV] TrackBar and Mat

這次要介紹Trackbar的使用方式, 以及連帶的說明一下 Mat
先把完成品貼上來給心急的人看一下

[OPENCV] 基本影像操作

完成了OpenCV的安裝後, 接著來熟悉一下 OpenCV當中的基本影像操作

打開eclipse, 然後創建一個專案, 專案當中的設定請參照openCV安裝

這次的程式碼很容易


1
2
3
4
5
6
7
8
9
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char** argv) {
  Mat inputImage = imread(argv[1]);
  imshow("Input Image", inputImage);
  waitKey(0);
  return 0;
}

[OPENCV] Ubuntu 14.04 安裝 + Eclipse 整合

這篇文章要介紹給大家如何在 ubuntu 14.04當中安裝上 OpenCV 3.3
另外還要加上Eclipse的整合

Install OpenCV_3.3 on Ubuntu_14.04


首先下載 OpenCV 3.3的source code

[C/C++] 最大公因數 - GCD (greatest common divisor)

最大公因數 - GCD

最近喵在寫演算法的時候, 偶然發現這最大公因數還蠻好用的
但在說這之前
我們還是來複習一下最大公因數

定義:

    兩個或多個整數共同具有的最大因數 (引用自wiki - 最大公因數)

[BLOG] 張貼Code block

Code Block

喵們在寫程式的時候, 常常用一些wiki來記錄
其中也只需要增加一些plug-in
在接上 <pre> </pre> 以及相對應的敘述就可以了
不過blogger似乎沒這麼愜意
找了幾個介紹都沒有達到很好的效果
直到....

OpenGL 閱讀筆記 (二) OpenGL基本操作

這邊虎喵跳過glfw/glew的初始化, 先來提一下OpenGL的基本操作方式 前面也提到過, OpenGL是一個類C的語言, 因此使用C/C++的攻城獅們應該會感到很熟悉. OpenGL的基本動作循環如下: 每一行code的解釋如下: // 本地變數,...