blog.Ring.idv.tw

Articles

淺談Tuple

Tuple.在Python程式語言中是一個immutable data structure,也可以將它當做是immutable list,也由於它是不可變的,所以它沒有像list擁有的一些append、remove等函式可供使用,那這樣的話為何還需要它呢?大致上有下述三點:

1. 它可以讓程式更具安全性,這裡的安全性指的是它具備不被更改的可能

2. 由於它是immutable,所以也可以用來當作dictionary的key來使用。

3. 和list相較之下,Tuple在建構時的速度上較快

下述來看一些實例:

>>> def a():
...     x = [1,2,3]
... 
>>> def b():
...     x = (1,2,3)
... 
>>> import dis
>>> dis.dis(a)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 BUILD_LIST               3
             12 STORE_FAST               0 (x)
             15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        
>>> dis.dis(b)
  2           0 LOAD_CONST               4 ((1, 2, 3))
              3 STORE_FAST               0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

從上述這兩個bytecode instructions來看,在建構Tuple所需要的指令較少,也意謂著在建構時的速度較快,實證如下:

python -m timeit "x=(1,2,3,4,5,6,7,8,9,10)"
10000000 loops, best of 3: 0.0261 usec per loop
python -m timeit "x=[1,2,3,4,5,6,7,8,9,10]"
10000000 loops, best of 3: 0.177 usec per loop

透過Tuple大約只耗費了「0.0261 usec」,至於List則需要「0.177 usec」左右~ 但如果比較兩者存取的速度上來看,List會顯得較有效率上的優勢。

python -m timeit -s "x=(1,2,3,4,5,6,7,8,9,10)" "y=x[3]"
10000000 loops, best of 3: 0.0649 usec per loop
python -m timeit -s "x=[1,2,3,4,5,6,7,8,9,10]" "y=x[3]"
10000000 loops, best of 3: 0.0584 usec per loop

相關資源

Are tuples more efficient than lists in Python?

32.12. dis — Disassembler for Python bytecode

2009-08-23 17:11:13 | Add Comment

Google Street View 心得

Google在今日正式對外開放在台灣的街景服務(Google Street View),根據幕後秘辛的說明,Google街景拍攝車的上頭主要使用「9」部朝向不同方向的照相機所組成,以提供「水平 360°」和垂直「290°」的街道全景圖,雖然目前只有提供台北地區的街景,不過未來還會有下述地點:

P.S. 筆者幼時的家鄉「鹿港」居然也包含在內 ^^

雖然台灣街景服務今天才剛正式開放,不過已經有許多先行者分享了相關心得(請見底下相關資訊),所以本篇的介紹傾向從Web的角度來看。

Google Street View - 淡江中學

筆者以不能說的秘密電影拍攝地「淡江中學」來介紹,透過上圖的影像可以得知,左方側欄是提供Google Maps的相關資訊,右方側欄則是一個採用Flash動畫的街景服務,利用Firefox外掛Firebug的資訊攔截,在XHR的面版上可以得知有三個請求,其一就是提供左方側欄資訊的JSON資料交換格式(實際範例)。

第二個應該是提供可替換的「衣夾人」組態設定(這個名字的由來是因為它的形狀像一個衣夾。),他出現在「Google 地圖」視窗左側的縮放工具列上方。若他變成黃色,即表示目前的位置可提供「街景服務」,從這個實際例子中可以得知,裡頭包含了五個不同的衣夾人圖形,不過筆者實際測試的結果,目前所提供的五個圖形URL只有兩個是正確的,它們分別為「Legopeg」和「Panda」,這部份未來也許是可以替換的。

至於最後一個請求則是提供右側Flash形式的街景服務中的XML文字資訊(如上圖:真理街),這部份應該是直接透過街景服務的Flash直接下請求(筆者猜測),透過此Flash動畫資訊中的metadata得知它是採用Adobe Flex 3開發的,此動畫裡頭包含了11張基本工具列的影像資訊:

至於實際的街景影像則是一張張512*512由Google處理過的JPEG影像去組合起來的(如:實際影像),而關於如何組合這樣的全景影像可參考The Stanford CityBlock Project,最後暫且不論Google為何採用Flash來呈現街景服務,Flash在網路上不可或缺的地位又提升了不少。

附帶提一下,Google的伺服器不只多~ 主機名稱也挺多的,上述這些請求的伺服器主機名稱就有「gws」(這比較好猜)、「LocalTrends/1.0」、「mfe」和「Alleycat Server 1.0」(野貓?)

相關資訊

Google Maps開放台灣版街景地圖(Street View)

oogle Maps Street View 台北街景地圖上線&!上網遊覽台北101 | 電腦玩物

台北的Google Street View(Google街景)上線了!

iPhone上的Google Street View (Google街景)

2009-08-18 23:29:49 | Add Comment

標籤雲(Tag Cloud)

Tag Cloud(或word cloud).它屬於視覺化介面的一種呈現方式~ 基本上是透過字母的排列順序和次數權重來決定字型大小的呈現,根據wikipedia的記載~ Tag Cloud最初是由Flickr率先開始使用,至於這個詞是由誰提出來的.. 筆者尚未找到有力的參考文獻~

另外Tag Cloud - Wiki也提供了「Computation of the tag size」公式計算,如下所示:

套用此公式的結果:

從上圖的結果可以發現,上述公式對於權重和字型大小之間的運算結果,會導致字型範圍「1px」至「20px」的情形發生,但基本上當字型大小小於「10px」就不容易閱讀和點選,所以筆者修改了此公式,希望它能自行定義Tag Cloud的字型大小範圍「10px」至「20px」,如下圖所示:

如此便能依照權重比例和字型大小形成相互的對應:

index.py

#! /usr/bin/python
from mod_python import psp

def index(req):
        param = {}
        req.content_type = 'text/html'
        tags = [('aggregators',2),('blogs',3),('wikis',4),('usability',5),('widgets',6),('ajax',7),('social',10),('Folksonomy',15)]
        tags.sort()
        param['Tags'] = tags

        tmpl = psp.PSP(req,'index.tmpl')
        tmpl.run(param)

index.tmpl

<html>
<head>
<title>Tag Cloud</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css" media="all">
.tagcloud
{
        width: 200px;
        height: 100px;
}
</style>
</head>
<body>
<div class="tagcloud">
<%
Clist = [_t[1] for _t in Tags]
Tmax = max(Clist)
Tmin = min(Clist)
Fmax = 20
T = Tmax - Tmin

for _t in Tags:
        if _t[1] > Tmin:
                si = Fmax * (_t[1] - Tmin) / T 
        else:
                si = 1
        
%>
<span style='font-size: <%=si%>px'><a href="#"><%=_t[0]%></a></span> 
<%
# end for
%>
</div>
<div class="tagcloud">
<%
Fmin = 10

for _t in Tags:
        if _t[1] > Tmin:
                si = (Fmax - Fmin) * (_t[1] - Tmin) / T + Fmin
        else:
                si = Fmin
        
%>
<span style='font-size: <%=si%>px'><a href="#"><%=_t[0]%></a></span> 
<%
# end for
%>
</div>
</body>
</html>

2009-08-12 01:02:07 | Add Comment

Read Later - bookmarklet 分析

去年筆者曾寫了一篇「Instapaper - 網頁暫存器」po文來介紹此工具~ 前陣子發覺它的「Bookmarklet - 書籤小程式」有了改版~

它的Bookmarklet主要利用「Dynamic Script Tag」的方式載入一個外部的js檔,下述是此js檔的原始碼:

var d=document;
d.title = d.title.substring(12);
if (document.location.href == 'http://www.instapaper.com/i4') { alert("The bookmarklet is correctly installed."); throw(0); }
var w=window,
    e=w.getSelection,
    k=d.getSelection,
    x=d.selection,
    s=(e? e(): (k)? k(): (x?x.createRange().text: 0)),
    l=d.location,
    e=encodeURIComponent,
    n=d.getElementsByTagName('html'),
    h=0,    z=d.createElement('scr'+'ipt'),
    p='k=CHN8G1125OCh&u=' + e(l.href) + '&t=' + e(d.title) + '&s=' + e(s.length > 6144 ? s : '');
/* Lauderdale, start your photocopiers! http://bit.ly/NdDJj :) */
i=document.createElement('iframe');
i.setAttribute('name', 'ipb596873');
i.setAttribute('id', 'ipb596873');
    c = 'left:10px;top:10px;width:168px;';
i.setAttribute('style', 'z-index: 2147483647; position: fixed;'+c+'width:168px;height: 100px; border: 3px solid #aaa;');
document.body.appendChild(i);
i.onload = function(){ setTimeout(ipb596873_close, 350); }

function ipb596873_close() 
{ 
    var f = document.getElementById('ipb596873');
    f.style.display = 'none'; 
    f.parentNode.removeChild(f);
}

window['ipb596873'].document.write(
    '<html><body style="color: #555; background-color: #fff; text-align: center; margin: 0px; font-family: Georgia, Times, serif; font-size: 26px;">' +
    '<img style="display: block; position: fixed; bottom: 4px; left: 72px;" src="data:image/gif;base64,R0lGODlhGAAYAPQAAP///wAAAM7Ozvr6+uDg4LCwsOjo6I6OjsjIyJycnNjY2KioqMDAwPLy8nZ2doaGhri4uGhoaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAHAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAGAAYAAAFriAgjiQAQWVaDgr5POSgkoTDjFE0NoQ8iw8HQZQTDQjDn4jhSABhAAOhoTqSDg7qSUQwxEaEwwFhXHhHgzOA1xshxAnfTzotGRaHglJqkJcaVEqCgyoCBQkJBQKDDXQGDYaIioyOgYSXA36XIgYMBWRzXZoKBQUMmil0lgalLSIClgBpO0g+s26nUWddXyoEDIsACq5SsTMMDIECwUdJPw0Mzsu0qHYkw72bBmozIQAh+QQABwABACwAAAAAGAAYAAAFsCAgjiTAMGVaDgR5HKQwqKNxIKPjjFCk0KNXC6ATKSI7oAhxWIhezwhENTCQEoeGCdWIPEgzESGxEIgGBWstEW4QCGGAIJEoxGmGt5ZkgCRQQHkGd2CESoeIIwoMBQUMP4cNeQQGDYuNj4iSb5WJnmeGng0CDGaBlIQEJziHk3sABidDAHBgagButSKvAAoyuHuUYHgCkAZqebw0AgLBQyyzNKO3byNuoSS8x8OfwIchACH5BAAHAAIALAAAAAAYABgAAAW4ICCOJIAgZVoOBJkkpDKoo5EI43GMjNPSokXCINKJCI4HcCRIQEQvqIOhGhBHhUTDhGo4diOZyFAoKEQDxra2mAEgjghOpCgz3LTBIxJ5kgwMBShACREHZ1V4Kg1rS44pBAgMDAg/Sw0GBAQGDZGTlY+YmpyPpSQDiqYiDQoCliqZBqkGAgKIS5kEjQ21VwCyp76dBHiNvz+MR74AqSOdVwbQuo+abppo10ssjdkAnc0rf8vgl8YqIQAh+QQABwADACwAAAAAGAAYAAAFrCAgjiQgCGVaDgZZFCQxqKNRKGOSjMjR0qLXTyciHA7AkaLACMIAiwOC1iAxCrMToHHYjWQiA4NBEA0Q1RpWxHg4cMXxNDk4OBxNUkPAQAEXDgllKgMzQA1pSYopBgonCj9JEA8REQ8QjY+RQJOVl4ugoYssBJuMpYYjDQSliwasiQOwNakALKqsqbWvIohFm7V6rQAGP6+JQLlFg7KDQLKJrLjBKbvAor3IKiEAIfkEAAcABAAsAAAAABgAGAAABbUgII4koChlmhokw5DEoI4NQ4xFMQoJO4uuhignMiQWvxGBIQC+AJBEUyUcIRiyE6CR0CllW4HABxBURTUw4nC4FcWo5CDBRpQaCoF7VjgsyCUDYDMNZ0mHdwYEBAaGMwwHDg4HDA2KjI4qkJKUiJ6faJkiA4qAKQkRB3E0i6YpAw8RERAjA4tnBoMApCMQDhFTuySKoSKMJAq6rD4GzASiJYtgi6PUcs9Kew0xh7rNJMqIhYchACH5BAAHAAUALAAAAAAYABgAAAW0ICCOJEAQZZo2JIKQxqCOjWCMDDMqxT2LAgELkBMZCoXfyCBQiFwiRsGpku0EshNgUNAtrYPT0GQVNRBWwSKBMp98P24iISgNDAS4ipGA6JUpA2WAhDR4eWM/CAkHBwkIDYcGiTOLjY+FmZkNlCN3eUoLDmwlDW+AAwcODl5bYl8wCVYMDw5UWzBtnAANEQ8kBIM0oAAGPgcREIQnVloAChEOqARjzgAQEbczg8YkWJq8nSUhACH5BAAHAAYALAAAAAAYABgAAAWtICCOJGAYZZoOpKKQqDoORDMKwkgwtiwSBBYAJ2owGL5RgxBziQQMgkwoMkhNqAEDARPSaiMDFdDIiRSFQowMXE8Z6RdpYHWnEAWGPVkajPmARVZMPUkCBQkJBQINgwaFPoeJi4GVlQ2Qc3VJBQcLV0ptfAMJBwdcIl+FYjALQgimoGNWIhAQZA4HXSpLMQ8PIgkOSHxAQhERPw7ASTSFyCMMDqBTJL8tf3y2fCEAIfkEAAcABwAsAAAAABgAGAAABa8gII4k0DRlmg6kYZCoOg5EDBDEaAi2jLO3nEkgkMEIL4BLpBAkVy3hCTAQKGAznM0AFNFGBAbj2cA9jQixcGZAGgECBu/9HnTp+FGjjezJFAwFBQwKe2Z+KoCChHmNjVMqA21nKQwJEJRlbnUFCQlFXlpeCWcGBUACCwlrdw8RKGImBwktdyMQEQciB7oACwcIeA4RVwAODiIGvHQKERAjxyMIB5QlVSTLYLZ0sW8hACH5BAAHAAgALAAAAAAYABgAAAW0ICCOJNA0ZZoOpGGQrDoOBCoSxNgQsQzgMZyIlvOJdi+AS2SoyXrK4umWPM5wNiV0UDUIBNkdoepTfMkA7thIECiyRtUAGq8fm2O4jIBgMBA1eAZ6Knx+gHaJR4QwdCMKBxEJRggFDGgQEREPjjAMBQUKIwIRDhBDC2QNDDEKoEkDoiMHDigICGkJBS2dDA6TAAnAEAkCdQ8ORQcHTAkLcQQODLPMIgIJaCWxJMIkPIoAt3EhACH5BAAHAAkALAAAAAAYABgAAAWtICCOJNA0ZZoOpGGQrDoOBCoSxNgQsQzgMZyIlvOJdi+AS2SoyXrK4umWHM5wNiV0UN3xdLiqr+mENcWpM9TIbrsBkEck8oC0DQqBQGGIz+t3eXtob0ZTPgNrIwQJDgtGAgwCWSIMDg4HiiUIDAxFAAoODwxDBWINCEGdSTQkCQcoegADBaQ6MggHjwAFBZUFCm0HB0kJCUy9bAYHCCPGIwqmRq0jySMGmj6yRiEAIfkEAAcACgAsAAAAABgAGAAABbIgII4k0DRlmg6kYZCsOg4EKhLE2BCxDOAxnIiW84l2L4BLZKipBopW8XRLDkeCiAMyMvQAA+uON4JEIo+vqukkKQ6RhLHplVGN+LyKcXA4Dgx5DWwGDXx+gIKENnqNdzIDaiMECwcFRgQCCowiCAcHCZIlCgICVgSfCEMMnA0CXaU2YSQFoQAKUQMMqjoyAglcAAyBAAIMRUYLCUkFlybDeAYJryLNk6xGNCTQXY0juHghACH5BAAHAAsALAAAAAAYABgAAAWzICCOJNA0ZVoOAmkY5KCSSgSNBDE2hDyLjohClBMNij8RJHIQvZwEVOpIekRQJyJs5AMoHA+GMbE1lnm9EcPhOHRnhpwUl3AsknHDm5RN+v8qCAkHBwkIfw1xBAYNgoSGiIqMgJQifZUjBhAJYj95ewIJCQV7KYpzBAkLLQADCHOtOpY5PgNlAAykAEUsQ1wzCgWdCIdeArczBQVbDJ0NAqyeBb64nQAGArBTt8R8mLuyPyEAOwAAAAAAAAAAAA=="/>' +
    '<div style="text-align: center; width: 80%; padding-bottom: 1px; margin: 0 auto 15px auto; font-size: 13px; border-bottom: 1px solid #ccc; color: #333;">Instapaper</div>' +
    'Saving...' +
    '<form action="http://www.instapaper.com/bookmarklet/post_v5" method="post" id="f">' +
    '<input type="hidden" name="p" value="'+p+'"/>' +
    '<input type="hidden" name="b" id="b" value=""/>' +
    '</form>' +
    '<scr'+'ipt>setTimeout(function() { document.getElementById("b").value = decodeURIComponent("'+e(h)+'"); document.getElementById("f").submit(); }, 1);</scr'+'ipt>' +
    '</body></html>'
);

從它的原始碼可以發現,它主要採用「iframe」的方式並設定CSS z-index為:2147483647,以及透過「Base64」的編碼方式將GIF圖檔內容直接內嵌在js檔中,最後利用「form」來觸發後端的記錄動作,實在是一個不錯的技巧!!

經由筆者測試之後,透過這樣的方式就算在瀏覽全版面的Flash網站時,仍然可以讓視窗保持在最上層!

2009-07-24 00:55:28 | Add Comment

Panasonic LX3 - 初試HDR

HDR(High Dynamic Range).簡單來說就是利用多張不同曝光值的影像,並藉由軟體的合成來營造出能呈現亮部及暗部曝光細節的影像。

而攝影的動態範圍(Dynamic Range)指的就是亮度從最暗到最亮之間的距離,假設考量一個拍攝場景的亮度差異極大時,這時候亮部或暗部的細節就需要有所取捨,因為相機的感光元件可能無法捕捉到所有的細節,這時HDR就相當適合發揮,下述是筆者初試的結果(還有很大的努力空間^^")

0 EV

+1 EV

-1 EV

HDR

(請注意屋簷下柱子所呈現的細節)

相機:Panasonic LX3

軟體:Photomatix Pro

拍攝:Joby Gorillapod 章魚小腳架、自拍模式2秒(防止按下快門時的震動)、ISO 80(盡量壓低,因為合成後顆粒會變明顯)、手動模式、手動對焦、自動曝光包圍(0EV, -1EV, +1EV)

心得:好想要有一台單眼來玩看看~ XDDD

參考資訊

HDR Tutorial: How to create ‘High Dynamic Range’ images using Photomatix

2009-07-17 22:24:21 | Add Comment

Next Posts~:::~Previous Posts
Copyright (C) Ching-Shen Chen. All rights reserved.

::: 搜尋 :::

::: 分類 :::

::: 最新文章 :::

::: 最新回應 :::

::: 訂閱 :::

Atom feed
Atom Comment