├── source ├── focus.md ├── science.md ├── video.md ├── article.md ├── preface.md ├── pdffooter.htm ├── md0.js ├── Makefile ├── convert.exe ├── mimetex.exe ├── title.md ├── tex2img.bat ├── metadata.xml ├── header.htm ├── footer.htm ├── editor.md ├── license.md ├── reflink.md9 ├── home.md ├── video1.md ├── article3.md ├── article3.md0 ├── info.md ├── focus1.md ├── focus1.md0 ├── article1.md ├── article2.md ├── article4.md ├── article6.md ├── focus2.md0 ├── focus2.md ├── article5.md ├── focus3.md ├── focus3.md0 └── focus4.md ├── code.zip ├── book ├── A4.pdf ├── A4.epub ├── ipad.pdf └── ipad.epub ├── img ├── MLP.jpg ├── cover.jpg ├── BridanAN.gif ├── Gradient.jpg ├── coverA4.png ├── queen5.JPG ├── queen8.JPG ├── MLP_neuron.jpg ├── NeuralCell.jpg ├── NeuralNet1.jpg ├── perceptron.jpg ├── image_thumb11.png ├── image_thumb13.png ├── image_thumb15.png ├── image_thumb3.png ├── image_thumb5.png ├── image_thumb62.png ├── image_thumb7.png ├── perceptron2.jpg ├── BridanNeuro_XOR.jpg ├── image_thumb4222.png ├── image_thumb132222.png ├── image_thumb14325.png ├── image_thumb13322222.png ├── SpeakToArduinoDevice1.jpg └── perceptronLinearAnalysis.jpg ├── slide └── neural.odp ├── code └── neural │ ├── myLib.js │ ├── backprop - 複製.js │ ├── backprop_7seg.js │ ├── test.js │ ├── backprop_xor.js │ ├── perceptron - 複製.js │ ├── perceptron_theta.js │ ├── perceptron.js │ ├── backprop.py │ └── backprop.js ├── timg ├── 0a49adc5ecfb.jpg ├── 0a7a7dbd3516.jpg ├── 1faa2e48aea6.jpg ├── 2554a2bb846c.jpg ├── 49e401d40cf4.jpg ├── 4d0383fdb044.jpg ├── 4ec0188cd431.jpg ├── 5ced75ffc852.jpg ├── 6fb8eb2fce33.jpg ├── 7621e383e2fc.jpg ├── 7f0e1a55880d.jpg ├── 856b9cd80d94.jpg ├── 8e42fbb23320.jpg ├── 9fb86666733f.jpg ├── ae4a7a4a574d.jpg ├── b1cacbe18ad7.jpg ├── c139ddae2765.jpg ├── cd7b4072bc59.jpg ├── d7d825c1b95d.jpg ├── deff37e6fc5a.jpg └── fb1e12546ddc.jpg ├── README.md ├── htm ├── video.html ├── article.html ├── preface.html ├── focus.html ├── science.html ├── title.html ├── editor.html ├── license.html ├── video1.html ├── article3.html ├── home.html ├── focus1.html ├── info.html ├── article1.html ├── article2.html └── article4.html └── css ├── pmag_bak.css └── pmag.css /source/focus.md: -------------------------------------------------------------------------------- 1 | # 本期焦點 2 | -------------------------------------------------------------------------------- /source/science.md: -------------------------------------------------------------------------------- 1 | # 程式與科學 2 | -------------------------------------------------------------------------------- /source/video.md: -------------------------------------------------------------------------------- 1 | 2 | # 影音頻道 3 | -------------------------------------------------------------------------------- /source/article.md: -------------------------------------------------------------------------------- 1 | 2 | # 程式人文集 3 | -------------------------------------------------------------------------------- /source/preface.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 3 | 4 | -------------------------------------------------------------------------------- /source/pdffooter.htm: -------------------------------------------------------------------------------- 1 |
# 影音頻道
17 |# 程式人文集
17 |在本期的「程式人雜誌」中,聚焦的主題是「神經網路」,包含理論與實作!
23 |神經網路是「機器學習」與「人工智慧」中的一個重要方法,常被用在「影像處理、語音處理、分群分類」等領域。
24 |雖然神經網路有很多種類,但本期關注的主要技術是「感知器」,包含「單層感知器」與「多層感知器」,以及用在「多層感知器」上的「反傳遞學習演算法」。
25 |當然、本期不只有「神經網路」的相關文章,還有更精彩的 Arduino, VB, OpenNI, 開放電腦計畫等內容,希望讀者會喜歡這期的「程式人雜誌」!
26 |---- (程式人雜誌編輯 - 陳鍾誠)
27 |本雜誌許多資料修改自維基百科,採用 創作共用:姓名標示、相同方式分享 授權,若您想要修改本書產生衍生著作時,至少應該遵守下列授權條件:
23 |另外、當本雜誌中有文章或素材並非採用 姓名標示、相同方式分享 時,將會在該文章或素材後面標示其授權,此時該文章將以該標示的方式授權釋出,請修改者注意這些授權標示,以避免產生侵權糾紛。
28 |例如有些文章可能不希望被作為「商業性使用」,此時就可能會採用創作共用:姓名標示、非商業性、相同方式分享 的授權,此時您就不應當將該文章用於商業用途上。
29 |最後、懇請勿移除公益捐贈的相關描述,以便讓愛心得以持續散播!
30 |Lua 的語法很簡單,執行環境也很簡單,如果您用的是 Linux,應該從 Lua 官網上下載 建置一下就可以了,以下是官網所提供的建置方法:
23 |curl -R -O http://www.lua.org/ftp/lua-5.2.3.tar.gz
24 | tar zxf lua-5.2.3.tar.gz
25 | cd lua-5.2.3
26 | make linux test
27 | 如果您用 MS. Windows ,那麼就可以安裝 Lua for Windows,以下是其網址:
28 |下載安裝後,您會發現在「開始/所有程式」裏有個 Lua 的資料夾,裏面有「iLua, Lua Command Line, Lua Examples, QuickLuaTour」等項目,建議您看看「QuickLuaTour」,它會帶領你快速的熟悉 Lua 的語法與範例。
32 |接著您可以直接起動命令列,然後用任何的編輯器,像是「Notepad++」等,開始寫一些簡單的程式,然後直接用 lua <程式名稱> 去執行您的程式即可。以下是筆者執行幾個 Lua 程式的過程:
D:\Dropbox\Public\pmag\201402\code>lua hello.lua
34 | Hello World!
35 |
36 | D:\Dropbox\Public\pmag\201402\code>lua fact.lua
37 | factorial(5)=120
38 |
39 | D:\Dropbox\Public\pmag\201402\code>lua obj.lua
40 | 10,20
41 | 30,40
42 | 50,60
43 |
44 | D:\Dropbox\Public\pmag\201402\code>lua obj.lua
45 | point(10,20)
46 | point(30,40)
47 | point(50,60)
48 | 您可以以看看下列 Lua 的影片,以便瞭解 Lua 的程式寫法:
49 || 影片 | 53 |連結 | 54 |
|---|---|
| Lua Tutorial #1: Introduction and Setup | 59 |http://youtu.be/dHURyRLMOK0 | 60 |
| Lua Tutorial #2: Hello World | 63 |http://youtu.be/aSxoOCn6Y4E | 64 |
| Lua Tutorial #3: Variables and User Input | 67 |http://youtu.be/ClThmOGuMi4 | 68 |
| Lua Tutorial #4: Basic Mathematics | 71 |http://youtu.be/jQ40M1DObl4 | 72 |
| Lua Tutorial #5: If and Else | 75 |http://youtu.be/vlJftHgeByg | 76 |
當然、多寫多看,應該是學習程式的不二法門。學程式與學習游泳一樣,只有下水開始扭動身體,才有機會真正學會游泳,也只有真正開始上機寫程式,才有可能真正學會寫程式。對於 Lua 、當然也是如此!
80 |NEURO 這門學問是我工作時才學習得的知識,多年前曾有一篇 洗衣機 貼文提到它,當時第一次知道這東西時,已經從研究所畢業好幾年,書局也沒幾本書可以參考,書中一堆數學式,有看沒有很懂,九O年代網路剛興起,沒甚麼資料可查,正好一位大學同學在大同工學院攻讀博士班主攻語音辨識,NEURO 就是用於學習辨識語音模式的解決方案之一,因此跟主管提出學習計畫,對授課教授表達旁聽的想法,就每周固定時間去大同工學院上課,我不需要學分,所以不用繳學費、不必考試、不必交作業,自備課本上了一個學期的課,這種學習方法在我準備插班大學考試也用過,並認識一些朋友。最近上網查,沒什麼人對 NEURO 議題,提供簡單的實例,以供初學者參考入門,現在將個人所知的做個紀錄分享。
23 |類神經網路有很多解決方案,這裡使用 BP 方法。首先認識神經元的數學模型,
24 |
26 | MP (MultiLayer Perceptron) 模型公式:
28 |Ui = Σ Wji Xj – θi
30 |Wji = 連結強度
31 |Xj = 神經元 j 所傳來之訊號
32 |θi = 神經元 i 之閥值
33 |Yi = f(Ui) = Yi 處理單元函數
35 |f = 轉換函數,通常為階梯函數(Step function)
36 |例如 Yi = 1 / (1 + exp(-Ui))
37 |{T}目標輸出量
39 |{Y}推論輸出量
40 |差距量 = 目標輸出量 – 推論輸出量 = δi = Ti – Yi
41 |本文範例採取的修正算式 δi = Yi‧(1 - Yi)‧(Ti – Yi)
42 |η:學習速率,控制權重修正幅度
44 |輸出單元閥值改變量 = △θi = - η‧δi
45 |權重改變量 = △Wji = Xj‧η‧δi
46 |θi = θi + △θi
48 |Wji = Wji + △Wji
49 |總錯誤率 = 誤分類案例總數/範例總數
51 |依問題的複雜層度,利用它組合一知識神經網路,基本上有三大層-輸入層、隱藏層及輸出層。
52 |
54 | 最後整理一個 試算表 提供有興趣的朋友參考,以 XOR 邏輯為例,X1, X2 為輸入,Y為輸出,用 #3, #4, #5 三個神經元學習,H3, H4 是隱藏層(夾在輸入及輸出之間),簡單的問題一個隱藏層就夠,複雜的可能需要兩層。使用四種組合狀態重複訓練,最後它會穩定判別輸入,並給予適合的答案。
56 |以 遞迴或遞歸 (Recursion) 這樣技術,可將非線性數學問題收斂求解, 能處理類似邏輯型式的問題 ,供大家參考。
57 |(本文來自「研發養成所」 Bridan 的網誌,原文網址為 http://4rdp.blogspot.tw/2013/10/artificial-neural-network.html ,由陳鍾誠編輯後納入程式人雜誌)
58 |程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌。
18 || 出刊年月 | 23 |epub | 24 |ipad:PDF | 25 |A4:PDF | 26 |單頁 HTM | 27 |原始碼 | 28 |全部下載 | 29 |
|---|---|---|---|---|---|---|
| 2014年4月 | 34 |epub | 35 |ipad.pdf | 36 |A4.pdf | 37 |pmag.html | 38 |code.zip | 39 |github | 40 |
程式人雜誌預定於每個月 1 日出刊,您可以從下列網址取得程式人雜誌的所有內容 (包含當月最新出刊的雜誌)。
69 | 72 |竭誠歡迎程式人投稿,或者成為本雜誌的專欄作家,現在就可以加入 程式人雜誌社團 一同共襄盛舉。
74 |本雜誌編輯為「陳鍾誠 (@ccckmit)」,若要聯絡編輯,請寄信到 。
80 |在電腦領域,神經網路是指一種模擬神經系統所設計出來的程式,用來模擬人類視覺、聽覺等等智慧行為的原理,企圖讓電腦可以具有人類智慧的一種方法。
23 |下圖是生物神經細胞的結構圖,這個圖看來頗為複雜,如果電腦程式真的要模擬這麼複雜的結構,那程式應該也會非常複雜才對。
24 |
圖、神經細胞的結構
26 |還好、神經網路程式不需要去模擬「細胞膜、粒線體、核醣體」等等複雜的結構,因為學電腦的人可以透過「抽象化」這個伎倆,將上述的神經細胞結構簡化成下圖 (a) 的樣子。
28 |在下圖中,a1 ... an 是輸入,w1 ... wn 是權重,這些輸入乘上權重之後加總(SUM),就會得到神經元的刺激強度,接著經過函數 f() 轉換之後,就得到了輸出的刺激強度。
29 |
圖、神經網路連接模型
31 |上圖 (a)所對應的數學公式如下:
33 |
35 | 其中的 b 值是用來作為門檻的閥值,舉例而言,若 b 是 -0.5,那麼就代表要將總合減掉 0.5,才得到輸入刺激強度,這可以用來調節刺激強度,才不會一直增強上去。
37 |而上圖 (b) 中的網路,是一種單層的神經網路,所謂單層是不計算輸入節點的計算方式,因此只有圖中的大圈圈才算是一層,其中每個大圈圈都是如圖 (a) 中的一個神經元。
38 |最早的神經網路程式稱為感知器(Perceptron),這是由 Frank Rosenblatt 在 1957 年於 Cornell 航空實驗室 (Cornell Aeronautical Laboratory) 所發明的。
39 |但是在 1969 年,Marvin Minsky 和 Seymour Papert 在《Perceptrons》書中,仔細分析了知器為的功能及局限,證明感知器不能解決簡單的 XOR 等問題,結果導致神經網路技術經歷了長達 20 年的低潮期。
40 |後來在 1986 年,Rumelhart 等人於下列論文中提出「反向傳播」(back-propagation) 演算法,並成功的被運用在語音辨識等領域之後,神經網路才又開始成為熱門的研究主題。
41 |42 |44 |Rumelhart, David E.; Hinton, Geoffrey E., Williams, Ronald J. Learning representations by back-propagating errors. Nature. 8 October 1986, 323 (6088): 533–536.
43 |
事實上、反向傳播的方法,並不是 Rumelhart 等人第一個提出來的,Paul J. Werbos 1974 年在哈佛的博士論文中就提出了類似的方法,只是大家都不知道而已。
45 |46 |48 |Paul J. Werbos. Beyond Regression: New Tools for Prediction and Analysis in the Behavioral Sciences. PhD thesis, Harvard University, 1974
47 |
當然、神經網路再度成為研究焦點之後,各式各樣的方法又被發展出來了,大致上這些方法可以分為兩類,一種稱為「有指導者」的神經網路(Supervised Neural Network) ,像是「感知器與反傳遞演算法」等,另一種稱為「沒有指導者」的神經網路 (Unsupervised Neural Network),像是「霍普菲爾德網路 (Hopfield Network) 與自組織神經網路 (Self Organization network)」等等。
49 |當然、神經網路並不是「神奇銀彈」,可以解決人工智慧上的所有問題,神經網路最強大的地方是容錯性很強,而且不需要像專家系統這樣撰寫一堆規則,但是有一得必有一失,神經網路自動學習完成之後,我們根本不知道該如何再去改進這個學習成果,因為那些權重對人類來說根本就沒有什麼直觀的意義,因此也就很難再去改進這個網路了。
50 |不過、程式能夠自我學習畢竟是一件很神奇的事情,光是這點就值得讓我們好好的去瞭解一下神經網路到底是怎麼運作的了!
51 |【本文由陳鍾誠取材並修改自 維基百科,採用創作共用的 姓名標示、相同方式分享 授權】
63 |程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌,如果您願意成為本雜誌的專欄作家,請加入 程式人雜誌社團 一同共襄盛舉。
29 |我們透過發行這本雜誌,希望讓大家可以讀到想讀的書,學到想學的技術,同時也讓寫作的朋友的作品能產生良好價值 – 那就是讓讀者根據雜誌的價值捐款給慈善團體。 讀雜誌做公益也不需要有壓力,您不需要每讀一本就急著去捐款,您可以讀了十本再捐,或者使用固定的月捐款方式,當成是雜誌訂閱費,或者是季捐款、一年捐一次等都 OK ! 甚至是單純當個讀者我們也都很歡迎!
30 |本雜誌每期參考價:NT 50 元,如果您喜歡本雜誌,請將書款捐贈公益團體。例如可捐贈給「羅慧夫顱顏基金會 彰化銀行(009) 帳號:5234-01-41778-800」。(若匯款要加註可用「程式人雜誌」五個字)
31 |給專欄寫作者: 做公益不需要有壓力。如果您願意撰寫專欄,您可以輕鬆的寫,如果當月的稿件出不來,我們會安排其他稿件上場。
33 |給網誌捐贈者: 如果您沒時間寫專欄或投稿,沒關係,只要將您的網誌以 [創作共用的「姓名標示、非商業性、相同方式分享」授權] 並通知我們,我們會自動從中選取需要的文章進行編輯,放入適當的雜誌當中出刊。
34 |給文章投稿者: 程式人雜誌非常歡迎您加入作者的行列,如果您想撰寫任何文章或投稿,請用 markdown 或 LibreOffice 編輯好您的稿件,並於每個月 25 日前投稿到程式人雜誌社團 的檔案區,我們會盡可能將稿件編入隔月1號出版程式人雜誌當中,也歡迎您到社團中與我們一同討論。
35 |如果您要投稿給程式人雜誌,我們最希望的格式是採用 markdown 的格式撰寫,然後將所有檔按壓縮為 zip 上傳到社團檔案區給我們, 如您想學習 markdown 的撰寫出版方式,可以參考 看影片學 markdown 編輯出版流程 一文。
36 |如果您無法採用 markdown 的方式撰寫,也可以直接給我們您的稿件,像是 MS. Word 的 doc 檔或 LibreOffice 的 odt 檔都可以,我們 會將這些稿件改寫為 markdown 之後編入雜誌當中。
37 |您也可以擔任程式人雜誌的編輯,甚至創造一個全新的公益雜誌,我們誠摯的邀請您加入「開放公益出版」的行列,如果您想擔任編輯或創造新雜誌,也歡迎到 程式人雜誌社團 來與我們討論相關事宜。
39 || 公益團體 | 48 |聯絡資訊 | 49 |服務對象 | 50 |捐款帳號 | 51 |
|---|---|---|---|
| 財團法人羅慧夫顱顏基金會 | 56 |http://www.nncf.org/ 02-27190408分機 232 |
62 | 顱顏患者 (如唇顎裂、小耳症或其他罕見顱顏缺陷) | 63 |銀行:009彰化銀行民生分行 帳號:5234-01-41778-800 |
64 |
| 社團法人台灣省兒童少年成長協會 | 67 |http://www.cyga.org/ 04-23058005 |
73 | 單親、隔代教養.弱勢及一般家庭之兒童青少年 | 74 |銀行:新光銀行 戶名:台灣省兒童少年成長協會 帳號:103-0912-10-000212-0 |
75 |
這篇是寫給 amarino 初學者看的,目的是教導你如何執行 Amarino 的 SpeakToArduino 範例程式。SpeakToArduino 這個範例示範如何用 Android 手機聲控 Arduino。
23 |到 http://www.amarino-toolkit.net/ 下載下列 App 並安裝到 Android 手機上:
33 |如果你電腦上還沒有 Arduino IDE,請先到 http://arduino.cc/en/Main/Software 下載軟體,下載後解壓縮即可。
40 |接著下載 MeetAndroid Library,把 MeetAndroid 解到 Arduino IDE 安裝目錄下的 libraries 資料夾。
41 |重新啟動 Arduino IDE,在 Sketch > Import Library 底下應該會看到 MeetAndroid,如下圖:
42 |參考下圖,把紅、綠、藍三顆 LED 分別接到 pin 9, 10, 11,LED 的接法為: 長腳(陽極)接到 pin 腳,而短腳(陰極)串接一顆 220 ohm 電阻接到 GND:
47 |到這裏下載,並使用 Arduino IDE 打開 SpeakToArduino 程式。
52 |程式所用的 baud rate 預設是 57600 bps,如果你的藍芽模組不是 57600 bps,請做適當的調整:
53 |然後把程式上傳到 Arduino 板子上。
57 |我用的是 廣州匯承信息科技 的 HC-0x 系列藍芽模組,下圖是 HC-0x 藍芽模組的外觀:
59 |
▲ HC-0x 藍芽模組 (圖左:正面圖,圖右:背面圖)
61 |連接方法很簡單,照下表把 Arduino 和藍芽模組連接起來就好:
63 || Arduino | 67 |藍芽模組 | 68 |備註 | 69 |
|---|---|---|
| 5V | 74 |VCC | 75 |注意電源不可接錯 | 76 |
| GND | 79 |GND | 80 |注意電源不可接錯 | 81 |
| RXD | 84 |TXD | 85 |86 | |
| TXD | 89 |RXD | 90 |91 | |
有兩點要注意:第一是電源千萬不可接錯,不然可能會燒壞藍芽模組,第二是 Arduino 的 RXD 要接藍芽模組的 TXD,而 Arduino 的 TXD 要接藍芽模組的 RXD。
98 |通電之後,藍芽模組上的 LED 會一直閃爍:
99 |首先,先利用 Amarino 搜尋藍芽設備,找到設備後,將藍芽設備的 MAC Address 抄起來(記得不要在 Amarino 設定任何 Event!):
104 |打開 Android 手機上的 SpeakToArduino App,你會看到這樣的畫面:
108 |選手機 Menu 鍵 Set BT Device Address,手機會跳出這個畫面,此時請輸入剛剛抄下來的 MAC Address,然後按下【Save】鈕:
112 |按一下手機 Back 鍵退出 SpeakToArduino App,然後重新啟動 SpeakToArduino,這樣 App 才會用新的 Mac Adress 跟藍芽模組連線。
116 |如果一切順利,Android 手機就會跟 Arduino 建立連線,並且呈現如下圖的畫面(注意手機上方的 Status bar,若有成功與 Arduino 連線,status bar 上會顯示 Active connection: … 的訊息):
117 |按下【Click and order your color】鈕,手機會跳出語音辨識的畫面:
121 |這時便可以說出想要的顏色,例如 red, green, blue, white, pink, orange, yellow, dark 或 off,這時候 Arduino 上三顆 LED 便會同步改變亮度。比如當我說 red,這時 Android 手機就會叫 Arduino 把紅色 LED 打開:
125 |如果你有 RGB Led,可以用一顆 RGB Led 取代三顆 Led,這樣更可以呈現 LED 顏色變化的效果。
129 |【本文作者為馬萬圳,原文網址為: http://coopermaa2nd.blogspot.tw/2012/07/speaktoarduino.html ,由陳鍾誠編輯後納入本雜誌】
137 |在上一篇的 《OpenNI 2 基本程式範例》 裡,Heresy 基本上是先整理了一下,要使用 Visual Studio 來進行 OpenNI 2 的程式開發的話,要怎樣進專案的設定,另外也用一個最簡單的例子,來說明 OpenNI 2 的程式要怎麼寫。而這一篇,則是再繼續做補充,讓程式更完整。
42 |在上一個範例裡面,Heresy 為了版面、以及簡化程式碼的關係,是假設程式執行都沒有問題,所以把所有錯誤的檢查都拿掉了。不過實際上,程式在執行的時候,其實都是應該要考慮到各種錯誤狀況的!而 OpenNI 2 也有提供一些簡單的介面,可以用來檢查程式執行時,有沒有錯誤。
43 |首先,和 OpenNI 1.x 的時候,OpenNI 大部分的函式,都會回傳一個代表結果的值,讓開發者可以據此判斷該函式是否已正確執行;而在 OpenNI 2,這個回傳的結果,是一個叫做 openni::Status 的列舉型別。基本的使用狀況,大致上如下:
44 |openni::Status eRes = openni::OpenNI::initialize();
45 | if( eRes != openni::STATUS_OK )
46 | {
47 | std::cerr << openni::OpenNI::getExtendedError() << std::endl;
48 | return -1;
49 | }
50 | 如果函式有正確執行的話,所得到的回傳值會是 openni::STATUS_OK;反過來說,只要回傳值不是 STATUS_OK, 就代表函式執行是有問題的。
51 |而基本上 openni::Status 已經定義的一些常見的錯誤狀況,可以用來做進一步處理的判斷。不過如果是想要得到文字性的錯誤說明的話,也可以透過 openni::OpenNI::getExtendedErropr() 這個函式,來取得更完整的錯誤說明文字。不過要注意的是,他取得的會是最後一筆錯誤資訊,如果之後又有呼叫其他函式的話,可能會影響到它的內容。(不過他是 thread-safe 的) 而如果把之前的範例,全部都加上錯誤檢查的話,則會變成類似這樣子:
52 |// STL Header
53 | #include <iostream>
54 |
55 | // 1. include OpenNI Header
56 | #include "OpenNI.h"
57 |
58 | // using namespace
59 | using namespace std;
60 | using namespace openni;
61 |
62 | int main( int argc, char** argv )
63 | {
64 | // 2. initialize OpenNI
65 | if( OpenNI::initialize() == STATUS_OK )
66 | {
67 | // 3. open a device
68 | Device devAnyDevice;
69 | if( devAnyDevice.open( ANY_DEVICE ) == STATUS_OK )
70 | {
71 | // 4. create depth stream
72 | VideoStream streamDepth;
73 | if( streamDepth.create( devAnyDevice, SENSOR_DEPTH ) == STATUS_OK )
74 | {
75 | if( streamDepth.start() == STATUS_OK )
76 | {
77 | // 5 main loop, continue read
78 | VideoFrameRef frameDepth;
79 | for( int i = 0; i < 100; ++ i )
80 | {
81 | // 5.1 get frame
82 | if( streamDepth.readFrame( &frameDepth ) == STATUS_OK )
83 | {
84 | // 5.2 get data array
85 | const DepthPixel* pDepth = (const DepthPixel*)frameDepth.getData();
86 |
87 | // 5.3 output the depth value of center point
88 | int idx = frameDepth.getWidth()*(frameDepth.getHeight()+1)/2;
89 | cout << pDepth[idx] << endl;
90 | }
91 | else
92 | {
93 | cerr << "Can not read frame\n";
94 | cerr << OpenNI::getExtendedError() << endl;
95 | }
96 | }
97 | }
98 | else
99 | {
100 | cerr << "Can not start depth stream\n";
101 | cerr << OpenNI::getExtendedError() << endl;
102 | }
103 |
104 | streamDepth.destroy();
105 | }
106 | else
107 | {
108 | cerr << "Can not create depth stream\n";
109 | cerr << OpenNI::getExtendedError() << endl;
110 | }
111 |
112 | devAnyDevice.close();
113 | }
114 | else
115 | {
116 | cerr << "Can not open device\n";
117 | cerr << OpenNI::getExtendedError() << endl;
118 | }
119 |
120 | // 7. shutdown
121 | OpenNI::shutdown();
122 | }
123 | else
124 | {
125 | cerr << "OpenNI initialize error\n";
126 | cerr << OpenNI::getExtendedError() << endl;
127 | }
128 |
129 | return 0;
130 | }
131 | 這裡比較不一樣的是,Heresy 在前面有加上 using namespace openni;, 指定去使用 openni 這個 namespace,所以之後的程式,都可以把 namespace 省略掉;如此一來,程式寫起來會再簡短一點。 當然,上面的寫法也不是唯一的錯誤檢查的方法。像在官方範例「SimpleRead」裡面,採用的就是另一種程式風格的流程,有興趣的也可以看看。要採用哪種,基本上就是看人習慣了~只是另外也要提一下,理論上在出現錯誤時,main() 應該也要回傳非 0 的錯誤代碼的,Heresy 這邊沒有特別去處理這一塊就是了。
132 |不過…既然都是 C++ 的 API 了,沒有採用 exception(參考)來做處理…Heresy 個人是覺得有點可惜啊…總覺得以各方面來說,OpenNI 的開發團隊,似乎對 C++ 不是很熟悉?雖然 OpenNI 1.x 和 OpenNI 2 都提供了 C++ 的 API,但是實際上,很多介面設計的方式,都還是用 C 的形式來做的…還是其實是有其他考量?所以甚至連陣列都是另外寫一個自己的版本(openni::Array),而沒有直接採用 STL 的版本(也沒有 iterator 可以用)…
133 |【本文來自 Heresy's Space 的網誌,原文網址為: http://kheresy.wordpress.com/2012/12/26/openni-error-handle/ ,由 Heresy 捐出網誌給程式人雜誌,經陳鍾誠編輯後納入雜誌】
134 |什麼是 N Queens Puzzle 皇后問題問題? 通常我們都會用 8 皇后來稱呼它,但將 8 改成動態數字 n,則稱為 n 皇后
42 |什麼是 8 Queens Puzzle 皇后問題問題?
43 |那麼 8 皇后問題又是什麼呢?
44 |45 |47 |八皇后問題是一個以西洋棋為背景的問題:如何能夠在8×8的西洋棋棋盤上放置八個皇后,使得任何一個皇后都無法直接吃掉其他的皇后? 為了達到此目的,任兩個皇后都不能處於同一條橫行、縱行或斜線上。 八皇后問題可以推廣為更一般的n皇后擺放問題 :這時棋盤的大小變為n × n ,而皇后個數也變成n 。 若且唯若 n = 1或n ≥ 4時問題有解[1] 。
46 |
5 皇后總共有 10 組解
52 |8 皇后總共有 92 組解
55 |【1皇后】共1組解
57 | 【2皇后】共0組解
58 | 【3皇后】共0組解
59 | 【4皇后】共2組解
60 | 【5皇后】共10組解
61 | 【6皇后】共4組解
62 | 【7皇后】共40組解
63 | 【8皇后】共92組解
64 | 【9皇后】共352組解
65 | 【10皇后】共724組解
66 | 【11皇后】共2680組解
67 | 【12皇后】共14200組解
68 | 【13皇后】共73712組解
69 | 【14皇后】共365596組解
70 | 【15皇后】共2279184組解
71 | 【16皇后】共14772512組解
72 | 通常跑超過 10 皇后就需要等待不少時間了!
73 |如何使用遞迴與程序導向去實作呢?
74 |Dim QueenXY() ' 棋盤
75 | Dim TempQueenXY(9999) ' 暫存的棋盤
76 | Dim TempNumber ' 數量
77 | Dim QueenNumber ' 正解總數
78 | Private Sub Form_Activate()
79 | Queen = 9 ' 皇后數
80 |
81 | ReDim QueenXY(Queen - 1, Queen - 1) ' 配置棋盤
82 |
83 | For I = 0 To Queen - 1
84 | For J = 0 To Queen - 1
85 | QueenXY(I, J) = 0
86 | Next J
87 | Next I
88 |
89 | QueenNumber = 0
90 | List1.Clear
91 |
92 | For I = 0 To UBound(QueenXY)
93 | Call InputQueen(I, 0)
94 | Next I
95 |
96 | MsgBox "總解有 => " & QueenNumber & " 組"
97 | End Sub
98 |
99 |
100 | Function InputQueen(X, Y) ' 放置皇后
101 | If X >= 0 And X <= UBound(QueenXY) And Y >= 0 And Y <= UBound(QueenXY) Then ' 判斷棋盤是否超過
102 |
103 | If QueenXY(X, Y) = 0 Then ' 判斷是否為可放 (是否被殺)
104 |
105 |
106 |
107 | BackupTemp ' Step 備份目前棋盤狀
108 | Call KillQueen(X, Y) ' 建立被殺
109 | For I = 0 To UBound(QueenXY) ' 放下一個
110 | Call InputQueen(I, Y + 1)
111 | Next I
112 | If Y = UBound(QueenXY) Then
113 | QueenNumber = QueenNumber + 1
114 |
115 |
116 | Temp = ""
117 | List1.AddItem "第 " & QueenNumber & " 組答案為:"
118 | For I = 0 To UBound(QueenXY)
119 | For J = 0 To UBound(QueenXY)
120 | Temp = Temp & QueenXY(I, J) & " "
121 | Next J
122 | List1.AddItem Temp
123 | Temp = ""
124 | Next I
125 | List1.AddItem ""
126 |
127 | End If
128 |
129 | Reductive ' 還原
130 | End If
131 | End If
132 | End Function
133 |
134 | Function KillQueen(KX, KY) ' 跟自己八方被殺
135 |
136 | QueenXY(KX, KY) = "Q"
137 |
138 | For I = 0 To UBound(QueenXY)
139 | For J = 0 To UBound(QueenXY)
140 | If I = KX And J = KY Then
141 | Else
142 | If I = KX Or J = KY Then QueenXY(I, J) = 1 ' 四面
143 |
144 | If (J - KY) <> 0 And (I - KX) <> 0 Then ' 不為 0 (自己)
145 | If Abs((J - KY) / (I - KX)) = 1 Then QueenXY(I, J) = 1 ' 八方 (斜率絕對值 = 1)
146 | End If
147 | End If
148 | Next J
149 | Next I
150 |
151 | End Function
152 |
153 | Function BackupTemp() ' 備份
154 | Temp = ""
155 | For I = 0 To UBound(QueenXY)
156 | For J = 0 To UBound(QueenXY)
157 | Temp = Temp & QueenXY(I, J) & ","
158 | Next J
159 | Next I
160 |
161 | TempQueenXY(TempNumber) = Temp
162 | TempNumber = TempNumber + 1
163 | End Function
164 |
165 | Function Reductive() ' 還原
166 | Temp = Split(TempQueenXY(TempNumber - 1), ",")
167 | TempI = 0
168 | For I = 0 To UBound(QueenXY)
169 | For J = 0 To UBound(QueenXY)
170 | QueenXY(I, J) = Temp(TempI)
171 | TempI = TempI + 1
172 | Next J
173 | Next I
174 |
175 | TempNumber = TempNumber - 1
176 | End Function
177 | 【本文作者為「廖憲得」,原文網址為: http://www.dotblogs.com.tw/0xde/archive/2013/11/11/127531.aspx ,由陳鍾誠編輯後納入本雜誌】
181 |