7.17.2012

創業一年回顧


離開前公司開發app已經一年了,這篇文章可能有點亂,請慎入。

也許有人以為我在離職前就已經動手在開發了,
其實--大。錯。特。錯~!!
在那之前我只會C/C++跟Java(Matlab硬要算的話也會一點),
我是離職後才開始學Objective-C跟Cocoa Touch。

2011年整個夏天都在學這些東西跟寫sample code還有想idea。
9月才開始開發,12月才上架,而且第一次上架一波三折,
被Apple退貨了很多次(App Review Guide的條文太多了,很容易踩到),
1.0上架的東西跟當初第一版送review的真的差很大。

不過記得上架後最開心的事情有三樣:
1. 第一天就有人下載app
2. 下載app的人來自於想都沒想過的國家,能全球的人透過app連結的感覺很妙
3. 第一次有人付費購買app
但是這樣子的快樂並沒有延續多久,因為過了新年以後的下載量就迅速減少了。

因為1.0版只是最小可行性產品,當時覺得有人下載就表示有需求,
也許是個好的開始,卻沒想到也是誤判形勢的開始...

接下來的幾個月時間就是一直在改版和改進穩定性。
在1.0出廠之前就訂下一個月要出一次.1版的進度,因為Apple審app要一週,
所以又抓緊時間修送審後發現的bug或defect,並且在.1版之後馬上送..1版,
一方面是要督促自己要有紀律,另一方面是訓練自己估算時程的能力。
(其他像version control等基本技能當然是必備)
我記得我在書桌旁邊貼了一張版號跟內容的清單,
上面列了洋洋灑灑的功能要做,如今大部份都有做進去了。
但...現在想起來那是app毀滅的開始,因為app應該是要把單一功能做到極致,
我自己卻犯了以往一直嘲笑台廠包山包海包豬肉的問題。

但是做app不是只有開發,銷售也是重要的一環,
也是對工程出身的人來說最弱的一環,
所以這段時間的學習重點之一就是如何銷售app。
由於app產業先天上的限制,有些銷售的手段無法使用,
例如兩套app bundle在一起打折賣。
一般開發者會用的方法還有像價格策略、送promote code、
在論壇介紹、請app review site試用、cross promote等等,
但我學到最重要的就是let the app sells itself.
好的產品是可以讓人願意替你介紹的。

我也有想過用app海來增加廣告收入,
但是我只做了一款"電費估算機"就發現問題了:
我沒辦法maintain這麼多套產品,這樣只會拖累其他app。
還好做"電費估算機"的時間不長,就經驗來說倒是挺有收穫。

以銷售額來說,這個產品是失敗的。
以目的(學習iOS開發、上架、銷售與客服)來說,我已經達到了。
幸好,這個app並沒有借錢開發,也沒有合作夥伴,我只要對自己負責就好了。
創業的壓力真的不小,收入就是個大問題,這完全影響了社會對你的觀感,
我還記得離職第3天去辦信用卡就被洗臉了。
即使你再怎麼吶喊自己學了多少、你有多少實力,
對大多數人來說,沒錢,你就是失敗。
奉勸各位想跳出來做的朋友,仔細想想你夠不夠抗壓性來創業。

可是我完全不後悔創業這件事。
有了外在環境的挑戰,才會去學習以往不會碰觸的東西;
這跟以往只是照興趣去看東西又不一樣,因為自己知道這次是來真的了。
以往只會說"某某sales不知道在搞什麼鬼,他應該怎麼樣怎麼樣...",
轉眼間已經變成我應該要這樣那樣...
我還是熱愛做一個工程師的感覺,但我也不甘只是一個工程師。

我也了解到我不是萬能的,像美工就不在行。
雖然大部份的圖都是我自己畫的,但是一看就知道水準在哪。
所以下次一定要找美術來合作(以下開放報名 XD)。

這一年來有開心的時候,也有難過的時候,
有沒日沒夜埋首苦幹的時候,也有覺得白做工的時候,
重點是你所相信的是什麼,那才是支持你走下去的動力。
就像我相信我能改善人們的生活,降低資源的浪費,
我相信我能透過app做這件事,所以弄了一個"購物記憶王"。
它不賣,但是實現了我所相信的事。

10.29.2011

What iOS Simulator does not simulate: free()

在開發iOS app時一定要用實機測試,因為simulator跟實機的行為很多地方並不相同。Simulator除了不支援某些硬體功能外,在根本的運作機制上也有不同,這篇要分享的是在memory上的運作機制。

不過我也不打算寫太長,只寫要注意的地方就好了(因為太晚了~)。
我們先來看一段將Pixel array轉成UIImage的程式碼:

// 產生要畫的圖
unsigned char *pixels = malloc(nImageSize);
/*
 * (省略繪圖步驟)
 */
// 用畫好的圖產生image用的context
CGContextRef context = CGBitmapContextCreate(pixels, width, height, ...);

// 用完的記得要還,要養成好習慣!
free(pixels);

// 產生UIImage
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage image = [UIImage imageWithCGImage:imageRef]; 

// 要release才不會leak
CGContextRelease(context);
CGImageRelease(imageRef);

這段code在simulator能將pixels正確地轉成UIImage,使用Intruments也沒有發現memory leak,看起來沒問題吧!

很不幸地,在iPhone上完全不是這麼回事,你只會看到一片空白。

你看出問題在哪了嗎?是的,問題就在於pixels太早free了!應該要產生完image之後再free pixels。在iPhone上執行時,一呼叫free就會將memory清掉了,但simulator是在Mac OS上面執行,呼叫free時模擬的行為可能跟在iOS上面不一樣(可能是因為Mac OS X有GC的機制而iOS沒有)。如果只在simulator上面執行,就永遠找不到這個bug了!

所以如果你有在程式碼中呼叫free的話,記得在實機上也要測過喔!

P.S. 以後有機會再來分享在Android emulator中開發的心得。話說用i7-2600K來跑Android emulator還是很慢啊...

10.28.2011

追求細節

寫程式或是做產品跟畫漫畫其實有很多相似的地方,除了都是追求藝術外,也都講究細節。
這邊我所謂的細節不是指筆觸多精密,而是指漫畫中沒有留白的地方。

許多人看漫畫其實是在看“有圖的小說”,意思是說除了主要人物跟對白以外其實並沒有注意太多畫面上的細節(例如貼網點),而這些是使得畫面更加圓滿的必要元素;諷刺的是,當這些細節不存在時才會被人注意到似乎少了什麼東西,或是更直接一點就罵作者太混(我絕對不是在說富X)。

產品也是這麼回事,許多的小細節能使平凡的產品變得與眾不同,而堅持做出這些小細節的你也就變得與眾不同。

題外話:過度設計跟沒有細節一樣糟糕。

9.19.2011

[雜談] 近況更新

距離上次在這邊發文已經過了一年多了,更新一下近況順便做點記錄。

首先是...我又失業了 XD (Yeah~繼續練功~)

其實已經離開公司一陣子了,這段期間雖然也有許多公司的邀約(例如HTC),但是都婉拒了。每次HTC打來都很想問他們"我可以事情做完6點就下班嗎?"
工作也好些年了,好不容易對某些事情有了熱情,於是想趁還年輕、還沒有家庭跟小孩的時候好好去闖。

之前Android也玩了幾年,最近則開始接觸Apple iOS的開發,之後也會陸續分享在iOS上的開發心得,敬請不要期待,haha。

最後就是要給自己的小提醒:

我是很討厭加班文化的人,尤其是常態加班,那簡直是慢性自殺!
台灣人總覺得衰事不會輪到自己,而我過去就因為每天熬夜寫code到最後搞壞身體,差點連命都沒了。
長期加班也會造成效率低落的惡性循環,變成晚上寫bug白天debug。
我一直期許自己能在架構以及實作上做到預防勝於治療,對我來說一個好的工程師可以解很多bug,但是優秀的工程師能少寫幾個bug。(能寫到沒bug的稱為神)
因此我要求自己要在上班時間內提高效率做完當天的工作,不管上面長官會不會因此黑掉我。

但是這幾天晚上都寫到2, 3點,今天警覺到惡性循環的開始:昨晚寫的東西有32 bytes的memory leak,結果今天又花了一個早上來抓漏,最後發現是某個該用assign的property寫成了retain。Oh,也許有人說32 byte leak算什麼,但是我相信最不起眼的問題總有一天會在最不希望的時候反咬自己一口。

雖然有點經濟上的壓力,但是要相信自己,就算不加班不熬夜也可以做到!

8.20.2010

[舊稿] [Q&A] Layout of blogger 版面配置

發現這篇從08年年底到現在一直在草稿狀態,雖然只有一點點,不過還是貼上來好了,因為接下來不知道什麼時候才有時間更新...

偶爾嘗試點不同的寫作風格,就先用這篇開刀好了。本來想用敘事的方式來說明一下這個blog的排版原因和某些小細節,不過寫一寫發現有點難閱讀,所以改用Q&A的方式看看會不會有所改善。以下是左腦跟右腦的訪談:

Q:感謝你接受我的訪問,能不能請你大概聊一下整個版面的設計理念?
A:我希望我的讀者能在第一眼就很清楚文章的位置在哪裡,尤其是使用手持式裝置(PDA、SmartPhone甚至PSP)的讀者,這樣的讀者已經愈來愈多了。當然我也想提供行動裝置版的版面,不過在Blogger現有的template下是蠻難實現的。除此之外,在右側我放了一些Gadget,主要是希望能多些人交流。

Q:那配色呢,有什麼特別的原因嗎?
A:我想藍色是很貼近科技本質的一種顏色,所以我就用它當標題的顏色了。我曾經在白底黑字跟深底淺字兩種方式做徘徊,深底淺字的好處包括對行動裝置來說比較省電、對眼睛來說比較溫和,但是白底黑字才是大多數習慣閱讀的方式,另一方面由於blog可能會出現大量的貼圖,我不太喜歡貼圖跟背景色的反差太大(我想很多人都有在深色投影片貼過圖的經驗),所以最後選擇的是白底黑字。

在Framework中加入自己開發的API

大家好久不見,今天要分享的是如何將自有API跟系統一起build並且能將build出來的SDK放在Eclipse裡面用,不過這招不適合要放到android market上的程式,如果是這種情況,你需要的是git並且做好管理(包括把Eclipse的sync選項打開,好像越扯越遠...)

我想很多人應該也跟我一樣,開發程式時會寫出很多共用的API(通常是utility API),或是很多程式都會去bind同一樣一個service,而這些code(包括AIDL檔)通常會有很多份copy在各個Eclipse的project內,造成sync上的問題。這還不是主要的問題,更主要的問題在於,如果你的程式用到了hidden API,那可是連在Eclipse中build都build不過,更別想直接跑在emulator或是透過新版adb install到target上(因為Eclipse有error就無法產生apk檔)。

為了解決這兩個問題,我想最好的方式就是把code放在frameworks中一起build,而build出來的SDK正好可以給Eclipse用。

假設今天com.blogspot.dejob這個package有a.java及b.aidl要放進framework,那麼請試著這麼做:
1. 把這兩個檔案放在frameworks/base/core/dejob/java/com/blogspot/dejob/底下
2. 更改build/core/pathmap.mk,在FRAMEWORKS_BASE_SUBDIRS最後面加上"dejob \"
3. 更改frameworks/base/Android.mk:
  • 在LOCAL_SRC_FILES這一段的最後加入dejob/java/com/blogspot/dejob/b.aidl,這樣就可以讓AIDL檔build到framework中,但是這樣還不夠,你還需要下一步才能將AIDL檔內的javadoc build到SDK的document內。
  • 在aidl_files這一段的最後加入frameworks/base/dejob/java/com/blogspot/dejob/b.aidl
  • 在packages_to_document這一段的最後加入com/blogspot,意思是說com.blogspot底下的所有package都build進document。
4. 照下列順序來build code:
  1. 先確認你不是用root權限來build code!
  2. 裝好所有toolchain及下載android source code(騙一點篇幅,雖然沒稿費...)
  3. 切換到android目錄下打". build/envsetup.sh",請注意最前面那個"點"
  4. lunch sdk-eng
  5. make sdk
5. 接下來就可以先去運動一陣子(除非你的電腦配有12 core CPU+SSD RAID+16GB以上的RAM)

如果你的code沒寫錯,應該就可以看到SDK已經build完並且壓成zip檔了,接下來只要將這個zip檔解開,然後在Eclipse中指定SDK的位置到這個目錄就可以了。另外也建議在Eclipse的project中選clean將project重新build一次才能知道有沒有成功。

講一些題外話,最近一直在想要不要去應徵聯發科的android工程師,不過應該會被打槍吧,不知道還有沒有其他android相關的工作...

6.15.2009

在Eclipse下看framework的source code

參考: View Android Source Code in Eclipse

簡單來說,trace ADT的code會發現ADT會去android.jar同個目錄下的sources這個目錄找source code,
所以我們只要將android的java source code撿一撿,照package放到sources這個目錄就可以了。
所以參考link中的python script就是在幹這件事,不過我有兩點建議:
1. 在沒有make過的source code目錄下執行這個script:因為out這個目錄下有重複的java code
(而且out這個目錄有夠肥)
2. 把zippath = match.group(1).replace('.', '/') + '/' + file改成
zippath = 'sources/' + match.group(1).replace('.', '/') + '/' + file
這樣解出來的檔案和目錄就會放在sources目錄裡面了.

最近還在研究怎麼debug native code,之前make的gdb不能debug multi-thread的程式 = ="
看看android-ndk有沒有進展好了

6.14.2009

Eclipse JEE vs Java 6 Update 14

如果你更新到Java 1.6 Update 14, 而且原本能跑的Eclipse突然不能跑的話,
將eclipse.ini中的-Xmx512m改成--launcher.XXMaxPermSize所指定的size試看看,
我是改成-Xmx256m就能跑了

3.28.2009

不知不覺都變月刊了

這個月的頭條就是筆者找到工作了,從事Android UI的設計。最近發現API Demo的sample已經不夠參考了,因為不同的device跟輸入方式所需要的UI是大大不同,而API demo基本上是以手機的應用為主,今天如果我是要設計成Nettop或是TV用的UI,絕不是把畫面放大就能草草交差的事。雖然筆者滿懷雄心壯志,但是在業界打滾幾年後也知道公司根本不會有那個耐心等我好好設計架構、做user survey甚至是發好幾版的demo template;"time to market" kills designs,難怪路上滿滿都是山寨UI。

大家也都知道現在工作難找,筆者也被凹了。對我來說,這也就只是一份工作罷了,如果可以,我還寧願自己寫程式去賣。

2.18.2009

癮科技也有Android專屬子頻道了

網址是 http://android.cool3c.com/
這是比較偏向user端的site,開發者也可以藉此觀察使用者的需求。

順便更新一下近況,歷經過年,最近的工作機會“似乎”有那麼多了一些,所以最近忙著更新自傳履歷還有K書,不管未來是做什麼工作,基本功是一直要練的。明天又要去面試了,先這樣。

1.04.2009

[C語言] Rounding 四捨五入

前陣子有公司找我去面談,結果被打槍了,心情低落了一陣子,所以一段時間沒文章。最近在實驗室BBS有學弟妹分享如何在Matlab呼叫C寫的code(因為Matlab實在跑太慢了,更不用說Mac版的),不過這不是重點,因為我的畢業論文就用過這招了,那段程式是用inline assembly做四捨五入,所以我想就來分享一點使用C語言實作Rounding(四捨五入)的各種方法與經驗。

一般人想到用C實作四捨五入,會有幾種方法?就我所知,至少有將近10種或是更多(不好意思,學藝不精),以下分享最簡單到稍難的方法,除此以外大概還有C++專屬的用法、CPU限定的用法(跟32/64-bit有關)以及使用magic number的用法,這些我就不多著墨了,有興趣的讀者可以用我前面提供的線索去找找。

1. 利用C語言中浮點數轉整數會把小數點去掉的特性,這是ANSI C裡頭制定的規格,所以大部份的平台都可以使用(沒有浮點數的就別來亂了),程式大概長這樣:

inline int myIntRound(double dInput)
{
    if(dInput >= 0.0f)
    {
        return ((int)(dInput + 0.5f));
    }
    return ((int)(dInput - 0.5f));
}

2. 使用math.h中的round()函式,唯一要特別注意的是接回傳值是用double或int,永遠別忽略type casting所帶來的effort,使用方法很簡單,把值丟進去就行了:
double dResult = round(dInput);

3. GCC的math.h中可以找到nearbyint()這個函式,用法跟round()一樣:
double dResult = nearbyint(dInput);

4. 接下來這個方法其實有點脫褲子放屁,如果你的math.h沒有提供round()可以派上用場。一樣include math.h,我們改用floor()及ceil()來實作,程式碼如下:

inline double myFloorRound(double dInput)
{
    if(dInput >= 0.0f)
    {
        return floor(dInput + 0.5f);
    }
    return ceil(dInput - 0.5f);
}

5. 接下來要介紹的方法就比較不那麼跨平台了,我們要使用frndint這個FPU指令,並且以inline assembly實作,在使用x86 CPU的Win32上的實作上大概長得像這樣:
inline double myDoubleRound(double dInput)
{
    double dResult;
    __asm__ (
        "frndint;": "=t" (dResult) : "0" (dInput)
    );

    return dResult;
}

順道一提的是,某些math.h中的round就是這樣寫的。

6. 一樣用inline assembly,我們用到了fld及fistp這兩個指令,程式碼如下:

inline int double2int(double dInput)
{
    int nResult = 0;
    __asm {
        fld dInput
        fistp nResult
    }
    return nResult;
}
其實在使用fistp之前應該要先用fldcw設定rounding的方式,可以設定為最近的int,或是floor/ceil等。

=========== 我是分隔線 ===========
現在讓我們來測試一下各種方法的效能如何,筆者使用的環境是Mac OS X 10.5.6(Intel)、GCC 4.0.1,compile參數為-O2 -fasm-blocks,每個方法呼叫100000000次,以-3.5做為input,測試結果如下:
Math.round:     0.048509 sec, result = -4
Math.nearbyint: 0.045757 sec, result = -4
myIntRound:     0.045828 sec, result = -4
myDoubleRound:  0.045824 sec, result = -4
myFloorRound:   0.045940 sec, result = -4
double2int:     0.222163 sec, result = -4

前面的5種方法速度都在誤差範圍內,只有double2int的速度特別慢,這件事告訴我們:拔獅子的鬃毛不一定會長出頭髮,就算用inline assembly也不一定會比較快!另外不知道是不是筆者的compiler特別愛作怪,inline assembly加上volatile甚至還會拖慢,以myDoubleRound來說好了,我在__asm__後面加上__volatile__,測試結果竟然要0.457702 sec,足足慢了10倍!

小小做個總結好了,其實C語言有很多不起眼卻可以探討的主題,翻一翻GCC的code也可以挖到不少寶。以四捨五入來說,每種方法都各有優缺點,使用math.h的方法最容易實作,卻也會讓program image變大;使用myIntRound的方法如果回傳後是塞到double就需要cast的effort;採用myDoubleRound的方法需要FPU指令。要使用何種方法就見人見智囉。

12.22.2008

Manage items with codes 用條碼管理物品

不知道各位有沒有這種經驗,筆者小時候曾經在家裡冰箱的冷凍庫中找到兩年前的冷凍包子,每年過年冰箱都要進行一次“新陳代謝”,看起來好像沒什麼,最多就是吃壞肚子罷了,但是東西堆在冰箱內會影響氣流的流動,使得冰箱變得更為耗電,以及冷媒的消耗和加速冰箱的折損率;雖然沒有正式的統計,但是我相信全台灣堆在冰箱內的過期食物應該會造成不少多餘的碳排放。事實上,不只是冰箱內的食物可以管理(藏在冰箱內的私房錢也需要管理),所有買回家的東西,都可以管理,問題是,怎麼管理?其中一個簡單的解決方案是:透過條碼管理。
拜照像手機與內建鏡頭的的筆電所賜,現在越來越容易取得商品上的Barcode。在日本,到處都可以見到印上
QR Code 的商品,QR Code就是所謂的二維條碼,可以嵌入比一維條碼更多的資訊以及更高的污損容錯率(簡單來說,就是弄髒一點甚至破掉都還可以還原),這張圖就是內嵌本站網址的二維條碼:
只要拿起有QR Code辨識軟體的手機對著螢幕拍下這張圖,馬上就可以方便地連上本站(或是加入書籤);而在台灣,幾乎所有商品都有印上一維條碼,最常見的就是13個數字的EAN-13 編碼,以及圖書專用的ISBN碼,現在甚至連去大賣場買水果也有Barcode,我們可以把這些Barcode當作是物品的ID來進行管理。以上是整個系統的概念。
在實作上,已經有Open Source的project可供取用,目前最方便的,應該是使用Java所寫的ZXing。ZXing支援了各多種Platform與Barcode的應用,平台方面除了基本一定要有的J2SE/J2ME,也支援RIM、Android、iPhone(QR Code only,用Obj-C寫的)等平台,簡直就是佛心來著!有興趣的朋友可以嘗試玩看看,筆者小測了一下覺得還蠻好玩的。
在Android上,有套叫CompareEverywhere的軟體就是將Barcode scanning與Google API整合,除了透過Barcode查詢物品與比價,還能在地圖上顯示附近有賣這項物品的商店,在Youtube上可以找到Demo影片。而Android平台中就有內建SQLite,可以將物品資訊存在DB中更方便使用。
在Mac上比較著名的軟體大概就是Delicious Library,目前已經推出到2.0版,這個版本可以輸出對iPhone最佳化的的web格式,可以參考Mobile01上的介紹 。功能看起來是不賴,不過筆者一向是比較支持Open source……
從單純的管理冰箱過期食物為出發點,可以延伸出相當多的應用,例如家庭主婦最愛的比價功能,或是查詢過去的購買記錄(可以避免買到一樣的東西,像最近筆者又不小心多買了一條洗面乳)、家中的庫存(螢幕顯示冰箱還有一把空心菜),歷史價格、網路上的折價券,或是幫助記帳(終級的記帳方式就是在消費的同時就記帳),可以說是一個很實用的個人/家庭進銷存系統。透過手機的普及以及Open source的貢獻,現在一般家庭也能享用大賣場及便利商店的科技;筆者希望能透過這個小小的科技能減少碳排放以及資源的浪費。
後記:雖然說照像手機很普及,不過筆者剛好沒有照像手機,在找到工作賺夠錢之前,請原諒我先打打嘴砲…

12.16.2008

[DDMS] Capture screen 擷取畫面

所謂工欲善其事,必先利其debugger,想要在Android上面開發程式,總免不了要跟DDMS親蜜親蜜…(快說不下去了),由於日後免不了要和大家分享使用畫面,或是有撰寫使用說明的需要,所以擷取畫面是必不可少的功能。在Android中當然可以寫個utility把Activity的畫面抓下來,不過,這種小事當然不需要用到牛刀,DDMS就可以做到了。以下的說明是在Eclipse,也就是Google官方所建議的開發環境中,使用其他IDE的話,如果沒有和DDMS結合得很好,可能需要手動把DDMS叫出來。

在Eclipse的右上角有個DDMS的tab,不過我剛裝好ADT的時候,其實並沒有找到DDMS的tab,而是像這樣:


這時候要按一下 會出現下拉式選單,選擇Others會出現這樣的視窗,然候選取DDMS按OK:


接著就會在右上角看到DDMS的圖示(如果找不到請拉一下左邊斜斜的地方,可以調整工具列):


點選DDMS以後就可以看到DDMS的視窗,此時還沒有跑模擬器,當然是空空如也。所以接下來就是要Run要跑的程式囉!Run程式基本上不在本篇的範圍內,所以我假設各位都已經有先玩過了,當程式Run起來後,點選剛剛那個DDMS的圖示切換到DDMS視窗,我們可以在左上的窗格看到這樣的畫面:


這個Window的功能是顯示所有正在模擬器上面跑的process以及相關的功能,還有…我們所要的Screen capture功能(都已經用圖提示這麼明顯了)!在模擬器執行的狀態下,我們可以擷取到任何顯示在Android上的畫面,包括開機畫面。另外,我們也可以在獨立執行的DDMS中使用快速鍵Ctrl + s來抓畫面。以下就是API Demos中的OpenGL ES畫面:


是不是又大又清晰呢?雖然筆者用Mac可以很容易地按下cmd+shift+4來抓螢幕的任何畫面,不過還是沒有DDMS來得方便,在DDMS中還可以隨時Update要抓的畫面,對一些畫面變化很多的程式來說,DDMS提供了蠻方便的工具,希望對各位有幫助。往後如果還有其他有關DDMS的心得也會放上來看各位分享。

參考資料: Using DDMS - Android

12.13.2008

Face detection in Android

以前曾經做過Face detection的研究(雖然指導教授認為這個topic已經被做到爛了),拜數位相機普級所賜,人臉偵測一下變成了人人口袋都有的技術。人臉偵測在相機的應用上之所以普級,在我的觀察中有幾個因素:
1. 自動對焦。一般消費者用DC拍有人臉的照片(自拍或是合照),都是希望能人臉能是對焦的部份,但是過去的DC所設計的對焦點並無法完全反映出人臉所在的位置,於是常常發生脫焦的現象。人臉偵測解決了這項缺失,有些廠商更進一步發展出了微笑快門等等的應用。
2. 自動曝光。除了脫焦的困擾外,另一項困擾DC使用者的還有「臉色太難看」,也就是臉色不是太白就是太黑,這也是因為早期的DC大概只有點測光、中央區域以及全域測光,雖然稍懂攝影觀念的人知道可以用曝光鎖定的方式來得到正確的曝光,但對一般使用者來說太煩複了,另一方面也不是每一台相機都提供曝光鎖定的功能,這時候人臉偵測技術就成瞭解決方案之一。
3. 方便編修。當人臉可以被偵測出來以後,就可以套用很多影像處理在人臉上了,簡單一點的像磨皮、去紅眼(去紅眼不一定要人臉偵測,不過有人臉做參考比較好處理)等,或是套用魚眼效果、少女漫畫效果,進一步還可以直接把臉換掉變成史瑞克。沒有人臉偵測的話,要做這些事就只能把人臉一個一個慢慢框起來…
那人臉偵測跟手機結合在一起有沒有搞頭?當然有!我們先看一段VCR:

手機跟相機最大的差別當然就在手機可以打電話,因此手機比相機多出了通訊錄的功能,結合網路或是手機內建的相機就可以很方便地將聯絡人的照片加入通訊錄中;另外再加上人臉辨識的話還可以讓手機遺失時減少被盜用的危險。

不過前面說了那麼多,除了給外行的看熱鬧以外,對於像正在看這篇文章的Android開發者來說,有哪些門道呢?該不會要porting OpenCV到Android平台上吧?放心, Google早就很貼心地幫各位準備好android.media.FaceDetector這個package了,只要將參數設好,然後將讀到的image (Bitmap格式)丟進去,它就會吐出一堆Face的Array了,而且不但有座標,連角度都有(你不會真的認為每個人都會安份地給你拍照吧),而且是三維的角度都有!有興趣的朋友可以試試這個package,並且試試能不能想出更kuso、更imba的應用(例如加在遊戲當中)!

12.07.2008

Android 3D UI

最近對Android的3D部份有興趣,先請大家看看這段影片:
很炫吧?

Android使用OpenGL ES,在Android平台上可以同時顯示3D與2D,跟iPhone相較之下,Android賦予開發者極大的彈性。不喜歡內建的撥號程式? 沒問題,換掉!不喜歡內建的桌面?沒問題,通通換掉!對許多開發者來說,Android平台可以說是別於iPhone的另一種天堂,但是事情就真的這麼美好嗎? Android的3D效能如何? 有什麼樣的極限? 穩定性如何? 3D的耗電量如何?這些都將是我會親自去實作與探討的部份,歡迎有興趣的同好一起來討論喔!