2012年2月24日 星期五

Simulate Switch in Lua

因為Lua不知道為啥沒有Switch的流程控制可以使用,Lua製作團隊應該也是被問到煩死了才寫了Lua switch wiki的吧,因為目前沒有涉略很深,就直接用個最簡單的範例吧。

A simple version of a switch statement can be implemented using a table to map the case value to an action. This is very efficient in Lua since tables are hashed by key value which avoids repetitive if <case> then ... elseif ... end statements.
action = {
  [1] = function (x) print(1) end,
  [2] = function (x) z = 5 end,
  ["nop"] = function (x) print(math.random()) end,
  ["my name"] = function (x) print(x) end,
}
Usage (Note, that in the following example you can also pass parameters to the function called) :-
action[case](params)
example: action["my name"](" is tkdstkdstkds");
This is pseudocode for the above:
switch (caseVariable) 
  case 1: print(1)
  case 2: z=5
  case "nop": print(math.random())
  case "my name": print(" is tkdstkdstkds")
end

2012年2月22日 星期三

Edge Detection--Sobel Filter

Edge Detection最基本的想法就是值的變化程度(gradient magnitude),當前處理的pixel的值與周遭旁邊的值如果有急遽的變化的話,代表這目前的pixel可能是處於影像的邊緣。所以通常會設一個Threshold來決定當值的變化量到一定程度時,當前處裡的pixel就視為邊緣。

最基本的Sobel Filter可以參考到Wiki的Sobel operator這篇。目前自己實作過的也只有Wiki的Formulation所提到的方式,在每個pixel convolution 水平和垂直的矩陣之後的Gx、Gy,最後平方相加再開根號完取得G就是值的變化程度。為什麼可以這樣,主要是因為Sobel Filter的矩陣可以看到所有Element相加一定是為0的,所以如果當前的pixel與周圍相鄰的八個pixel值如果相同的話,做完convolution取得值的變化程度一定是0。

實作程式可以看到真00無雙的這篇。要注意的地方是當矩陣做convolution時超出image的範圍時該怎麼做,通常是那邊的矩陣元素就不要乘了。

這邊只是簡單的虛擬碼,沒考慮矩陣超出image的範圍。重點是要容易了解演算法的結構,簡單的邏輯判斷就不管了。
foreach(pixel)
{
    float pixelValue[9]
    {
          leftup,      up, rightup
            left, current, right
        leftdown,    down, rightdown 
    };
 
    float sumX = 0, sumY = 0;
    for(i = 0; i < 9; i++)
    {
     sumX += pixelValue[i] * horizontalMatrix[i];
     sumY += pixelValue[i] * vertical Matrix[i];
    }
 
    gradient = sqrt(sumX * sumX + sumY * sumY);
 
    // threshold could be percent value for current pixel.
    // and we suppose pixel value range is [0, 1], and follow wiki common 
    // sobel matrix, the threshold range must be [0, 4].
    return (gradient > threshold * pixelValue[4]) ? edge : background;
}