2018年2月26日 星期一

常聽音樂集錦

人的五官中,眼耳鼻舌口,耳為第二項。相對於眼的空間感,耳在人的抽象思維上,扮演著更吃重的角色。音樂的定義和類型這麼多,私自認為,能自己演奏(唱)或現場聽最好。聽CD、廣播或Youtube及串流音樂,稍嫌被動,只是怡情養性,較難表現自我。

以下是平日常聽音樂列出,數量多且都是單曲為主,當然心中知道好音樂是要一系列聽下來才能有深刻感受,不過網路音樂當道,單曲還是比較吃香。

轉換動作是依靠 YOUTUBE轉換成音樂檔。若論到音樂品質,轉換取樣率是192kbps,雖然比不上Spotify提供的320kbp或CD直接燒錄成無損WAV或FLAC,對我這木耳也是足夠。

演奏


節奏強


岸部真明吉他演奏曲,Time Travel,聽著就能想像自己在青海湖邊騎單車的景緻。這是練習連結
youtube : 連結
Local檔名 : (純音樂)Masaaki Kishibe岸部真明-Time Travel時光旅行

把愛找回來電影原聲
youtube : 連結
Local檔名 : Bari Improv - August Rush

Alan Walker的成名洗腦歌,因為女兒的關係幾乎被聽到爛,類似壞掉音樂結構,讓人印象深刻。
youtube : 連結
Local檔名 : Alan Walker - Fade [NCS Release]
這是演唱版本,當個參考 youtube : 連結 Local檔名 : Alan Walker - Fded

火神咒 傳統北管曲牌的重新演繹 收尾融合東西風 (同片CD還有風入松 民俗風又太過了)
youtube : 連結
Local檔名 : 生祥樂隊 - 火神咒

功夫配樂 闖將令
youtube : 連結

情感動人

偏向比較低迴吧
貝多芬大公三重奏,四個樂章,層次豐富且動人。讀海邊的卡夫卡時文中提及,介紹
百萬三重奏1 
Local檔名: Beethoven Piano Trio No 7 Archduke - 1st (Rubinstein Heifetz Feuermann)  強烈復古,各自獨立  11:52
百萬三重奏2 
Local檔名: Beethoven Piano Trio No 7 Archduke - 2nd (Rubinstein Heifetz Feuermann)   06:14
百萬三重奏3 連結
Local檔名: Tercer Movimiento Archiduque 10:31
百萬三重奏4 連結
Local檔名: Beethoven Piano Trio No. 7 Archduke Cuarto Movimiento 06:20
和所有古典樂相同,名曲總有多種版本流傳。有些清晰、動人,有些較早錄製,收音品質濛濛,但聽久仍喜愛這耐聽演奏法。四樂章 : 連結 下載後檔名 IMSLP74472-PMLP19591-beethoven_o97n7  美國SOLISTI : youtube : 連結 Local檔名 : 貝多芬鋼琴三重奏 大公三重奏   都因為太甜被移走。

孟德爾頌的第64號e小調小提琴協奏曲,溫柔激昂兼容。三大小提琴協奏曲之一 美女小提琴家希拉蕊.韓 演奏。
youtube : 連結
Local檔名 : Mendelssohn Violin Concerto E Minor OP.64 (Full Length)  Hilary Hahn  FRSO

貝多芬第五號 諸大明演奏,(還在尋覓piano concerto @2 -3. Moderato 諸大明 簡文斌 NSO 專輯 樂典 04 盧炎)
youtube : 連結
Local檔名 : Daming Zhu Plays Beethoven Piano Concerto No.5 Emperor

拉赫曼尼諾夫,衝突與激情的代表
youtube : 連結
Local檔名 : Rachmaninoff plays Piano Concerto 2

柴可夫斯基 小提琴協奏曲 第一樂章。是電影常客也是比賽名曲
youtube : 連結
Local檔名 : 海飛茲 柴可夫斯基小提琴協奏曲 第一樂章

巴赫的夏康舞曲,「Partita no.2 BWV1004 (1720)」小提琴獨奏


旋律優美

坂本龍一合集,老婆非常讚賞他作品,多年前就看"音樂即自由",耳濡目染也愛上了。這曲算是集錦,前面就很好聽,而24:12開始的christmas鋼琴提琴版,(網路還有宇多田光翻唱吉他Kaori Muraji 村治佳織)。今年有中文字幕記錄片上映,這是影評
youtube : 連結 
Local檔名 : Ryuichi Sakamoto (坂本龍一) _– 1996

君的名子電影配樂,口嚼酒。
youtube : 連結
Local檔名 : 你的名字bgm - 口嚼酒之行 (Your Name Kuchikamizake trip)

haruka nakamura 中村遼 鋼琴   類似內在風景的音樂實在相當吸引我,覺得生命被豐富了
youtube:連結
Local檔名:Live at Arumakan - AMC Vol.9 - haruka nakamura Session
加入提琴 根本 理恵  youtube:連結
Local檔名:Live at Arumakan - AMC Vol.9 - haruka nakamura音楽のある風景 アルマカンver
youtube:連結 LOCAL還沒下載


Zbigniew Preisner 著名作曲家
youtube : 連結
Local檔名 : Zbigniew Preisner - Danse Macabre

Max Richter - On the Nature of Daylight 馬克思.李希特,極簡主義作曲家,哀傷。連結
youtube : 連結

棉花糖人,marshmello。女兒推薦歌單。有個形容很好,他用電音傳達正面力量。這首音樂很好懂,節奏也相當的慢(好像剛醒來的感覺)。充滿了很容易吸收的元素。
youtube : 連結
Local檔名 : Marshmello - Summer (Official Music Video) with Lele Pons

舒伯特 蘭德勒結構 366 是個可當早餐陪襯的好音樂
youtube : 連結
Local檔名 : Schubert - Ländler D.366 - Richter Paris 1961

Mozart 類似牧歌作品,充滿田園風光
youtube : 連結
Local檔名 : Mozart -  Clarinet Concerto In A Major K 622 Adagio

梁祝,小提琴名家吕思清版本。甜死人但就是好聽。
youtbue : 連結
Local檔名 : 梁祝小提琴协奏曲 - 吕思清 (指挥:夏小汤) Butterfly Lovers Violin Concerto - Lü Siqing (conductor Xia Xiaotang)

雲雀高飛,有梁祝東方精神的小提琴協奏曲。
可以想像雲雀在山谷間盤旋高升的畫面,喜愛。還至和女兒提到,未來就以此當成灑骨灰時的背景音樂吧
youtube:  連結 連結
Local檔名: The_Lark_ascending_-_Ralph_Vaughan_Williams

泰伊思冥想曲,少年時期常聽廣播節目(尋夢園)的主題音樂,現今來聽實在太甜。
youtube : 連結
Local檔名 : 泰伊思冥想曲  帕爾曼
另外還有 經典版 youtube : 連結   二胡版本 youtube : 連結  就沒下載了

德布西 月光,抒情音樂代表作
youtube : 連結
Local檔名 : 德布西 月光

here there every where : 這是FRIENDS某集中,菲比結婚橋段,用鋼鼓演奏出here there every where的旋律。雖然這應該屬於搭配影像才適合看的方式,不過FRIENDS伴隨著我成長(裡面 i will be my something blue 更是有趣)
youtube : 連結
Local檔名 : Friends Phoebes Wedding

時間機器time machine類似史詩節奏
youtube : 連結

舒曼兒時情景,各段落解說
youtube : 連結
Local檔名 : 舒曼 兒時情景

久石讓音樂不錯,但還是沒有阪本龍一好聽,阪本的東西有宏大的基礎感。動畫音樂因為有故事加持,比較屬於洗腦音樂。
Summer
youtube : 連結
魔法公主
youtube : 連結
youtube : 連結
神隱少女
主題 The Name of Life 白龍找自己名子 連結  演唱
片尾 Always With Me : 連結 演唱 難得的幸福感

花樣年華
youtube : 連結

演唱



偈 民歌時代最具文學味作品
youtube : 連結
Local檔名 : 王海玲【偈】Official Lyric Video

好樂團,這種聲音,只能說是天賦
youtube : 連結
Local檔名 : 好樂團 GoodBand ─《我把我的青春給你》Official Music Video

好樂團,主唱假音飄啊飄,是首關於無助(無奈?)的音樂
youtube : 連結
Local檔名 : 【好樂團 GoodBand】-我們一樣可惜 Demo

忘我的愛

Hello Nico- 接下來如何
youtube : 連結
Local檔名 : Hello Nico- 接下來如何

蘇打綠 當我們一起走過
youtube : 連結

倆忘煙水裡,喜歡很大原因是黃霑的詞,還有天龍八部和少年時期記憶的重疊
youtube : 連結
Local檔名 : 倆忘煙水裡 關正傑關菊英

原著民
Lulimai 細雨灑落群山,出自"歌,飛過群山"第三首。真誠人聲對自然的禮贊與感恩,同時也是治癒靈魂的聲音。youtube介紹
歌詞  Lu qu li ma yi yi na qa ya qa qu yi yi ma lju lja qa yi nu ua yi
1.Di masu yina dimasu qama, qa qusu sa sa qa mi li mi lin
妳是哪個家族的女孩?為何如女神般美麗?
2. Tu sa yi ve yi ge ma tu qu wan ki ni qa va qa re qe nge ran
灑落群山的細雨,是想念妳而流下的眼淚。
youtube : 連結
Local檔名 : LULIMAI

卑南族除草歌,聲音嘹亮轉折優美,渾然天成
youtube : 連結
Local檔名 : 20121013 PuyumaMowing卑南族除草歌

青蛙的眼睛


外語英
All I Wanna Do,原為HEART(紅心)單曲,Halestorm用更猛烈的硬式搖滾翻唱。女主唱甜美外表和渾厚嗓音衝突但又和諧。因為這首歌,可能得選有重低音的喇叭才行啊。
youtube : 連結
Local檔名 : Halestorm - All I Wanna Do (Is Make Love To You)

艾爾頓強,有搖滾樂界的莫扎特之稱,這首歌雅俗共賞,歌詞,尤其是自己越來越懶的為老婆準備小禮物,聽來更是愧疚啊。
youtube : 連結
Local檔名 : Elton John - Your song

Father and Son
youtube : 連結
Local檔名 : Father And Son - Rod Stewart

白日夢冒險王中配樂,隨著時鐘點滴,體會時間流逝
youtube : 連結
雲端備份 : 連結
Local檔名 : José González - Stay Alive

Journey樂團成名曲 很好的情歌,對當時漂泊的樂團下了很好的註解
youtube : 連結
Local檔名 : Faithfully (Official Video)

here there every where : Beatles Paul McCartney小品,憂鬱中帶點輕快。
Local檔名 : Here There and Everywhere (Take 14)
最早是Friends中非比結婚音樂(連結 連結),讓我覺得未來女兒結婚我也可以彈奏歐(連結)
Paul老年版本也很好(連結)
日本女生的東方版本也很喜歡(連結)
年輕人版本也很好(連結)

LOST STAR 抒情電影中獨特假音
youtube : 連結
Local檔名 : Adam Levine - Lost Stars

BEE GEES熱門歌曲,歌曲單純到不太耐聽,純粹因為有年少記憶啊
youtube : 連結
Local檔名 : Bee Gees - You Win Again

小紅莓 cranberries 主唱空靈又沙啞唱聲
youtube : 連結(這個不能下載) 連結
Local檔名 : The Cranberries - Linger (Acoustic Version)

if you leave me now ,Chicago合唱團經典曲,抒情名曲
youtube : 連結
Local檔名 : Chicago - If you leave me now - 1977 (HQ)

O MIO BABBINO CARO我親愛的爸爸
Hayley Westenra youtube : 連結
這首歌有眾多版本 聲樂式 例如荷蘭小女孩Amira Willighagen youtube : 連結  和 Maria Callas 1965 youtube : 連結 都很好,但Hayley版本 更為耐聽
LOCAL 荷蘭達人秀天使女孩:Amira Willighagen:O Mio Babbino Caro (中文字幕)

LOVE OF MY LIFE
QUEEN
連結  這個影片被看2億次了
韓國J.Fla COVER 連結


外語日

解憂雜貨店reborn,女聲,只能說太好聽
youtube : 連結
Local檔案 : 「REBORN」(セリver.)

日本民謠红蜻蜓
youtube : 連結
Local檔名 : 日本童謡-《赤とんぼ》(红蜻蜓)



音樂觀


世上音樂這麼多,哪些是我喜愛的音樂呢?這牽涉到個人音樂觀,像我等庸才,大致不會脫離下面三個條件。
1.旋律好聽
2.洗腦歌,大多都是太普遍化且沒有個人特色,僅是迎合市場需求的作品,可是放久了,就像果凍般凝固在腦中。
3.青少年期記憶,這其中不少作品,以現在標準看來都太甜了,不耐聽,但好歹也是伴隨成長啊。
類型上則是演奏和演唱都很愛,但前者偏愛程度漸增。

廣義來說,音樂是聲音的一種。同樣是聲音,語言和音樂就有很大差別,語言是天生必備的項目,需要學習才能生存。音樂和宗教很像,並不是必備能力,也很難以言語形容。不需要言傳,卻可以有相當大的感染力。在編曲人豐富的創作與想像力之下,我們荒無的生命,總是如同被啟發,深深被吸引。心會平靜。所以有句話說,音樂始於文字衰退之時(where words fail, music speaks),就是這個意思吧。

就因為音樂有如此廣大魔力,即使是最憂鬱嚴肅的人,獨處時,哼上一兩段自己懷想的小旋律,也是種幸福和安慰。所以我相信,情感可說是音樂的最終目的。

另外,這幾年跟著老婆接觸不少現代藝術,也漸漸開始接觸幫助冥思及潔浄心靈,讓自己靈魂超脫的現代音樂,篇幅比較多,另開篇章

2018年2月21日 星期三

[小說集]星塵Stardust

StarDust

作者 尼爾·蓋曼 是說故事高手,尤其魔幻與冒險題材更是他的強項。趁著年假,一口氣看完電影和原著小說,既有大螢幕的緊張刺激,又兼顧文字的雋永趣味,雙重享受,十分過癮。

故事背景是十六或十七世紀的英國鄉間,一座名為WALL的小鎮開始,這裡的農民平日忙於耕種和採集,是恪守基督教義和社會禮法的老實人,我們知道這種封閉性格,日後成為了現代社會的基礎,但當時還在中期,人們對這世界外還存在的魔法世界,並沒有全盤否認,不過這個情形維持不了多久,人類世界邊緣已經建起道石牆,這是一個很重要的分界線,區分著人類這邊的世界跟那邊的世界。WALL小鎮就在這彼此唯一缺口旁,倚靠著九年才出現一次的魔法市集,讓彼此仍然互相知悉。

不像很多小說一開頭就落落長一大段,作者只用逐漸封閉的石牆、以及人類立下的種種規定,隱喻固步自封的心態。所以隨著男主角為了愛而跨了界線,因為追逐著星星而啟動的冒險歷程,也可以說就是我們對魔法世界最後的想像。

雖然那個世界,有與我們相同的峽谷、平原、森林、高山。不過卻四處充滿著自然靈。他們相信大地是從混沌中產生,而山脈是由夸父巨人倒下後生成。天上星星各有靈性,甚至會被打落墜入人世,變成人型。

植物有靈,所以樹木可互相溝通,動物有靈,所以像獨角獸之類通靈神獸也不稀奇。除人外,精靈與女巫遊走各地。甚至人死去的靈魂,也是存在。人類本身,過著農耕漁牧的村莊生活,雖然受到暴風城堡領主的管制,但仍然自由。這個充滿"自然靈"的世界,就是作者建構的世界。雖然沒有提到文化和歷史,給人的印象也有些原始,卻是異常生猛有力。

在這世界中旅行,無疑要經過許多飢餓、艱險、傷害的考驗。男主角從來不是執意要面對,但臨到了頭上,也只能硬著頭皮上了。一次次,靠著自己的努力,和他人協助,從稚嫩青年轉成為勇敢擔當的成年人。到這又變成成長小說。

看著作者對想像中的生物的描述跟覺得不可能出現的東西,真是覺得神奇和不可思議。對年紀已經漸長,常覺得世事平凡無奇的我來說,好的奇幻小說總讓我想著,世上,還有這麼多地方沒看過,那麼多人要認識,還有要看的風景,更不用提陪伴愛我與我愛的人成長。自然就會湧起樂觀活力。

既然兩者都看了,也順便比較原著和電影版本。小說文筆雋永讓人愛不釋手,電影為配合劇情需要,對捕雷海盜船做了很大改動,終段還加入了女巫魔法大戰,雖然稍嫌誇張,卻也讓內容更為緊湊富有娛樂性。尤其推薦片中風景,美麗且讓人神往。

--------------

最後,節錄電影中,女主角對著變成睡鼠男主角的獨白

You know when I said I knew little about love? That wasn't true. I know a lot about love. I've seen it, centuries and centuries of it, and it was the only thing that made watching your world bearable. All those wars. pain, lies, hate... It made me want to turn away and never look down again. But when I see the way that mankind loves... You could search to the furthest reaches of the universe and never find anything more beautiful.

So yes, I know that love is unconditional. But I also know that it can be unpredictable, unexpected, uncontrollable, unbearable and strangely easy to mistake for loathing, and... What I'm trying to say, Tristan is... I think I love you. Is this love, Tristan?

I never imagined I'd know it for myself. My heart... It feels like my chest can barely contain it. Like it's trying to escape because it doesn't belong to me anymore. It belongs to you. And if you wanted it, I'd wish for nothing in exchange - No gifts. No goods. No demonstrations of devotion. Nothing but knowing you loved me too. Just your heart, in exchange for mine.

你知道嗎,當我說不懂愛情的時候,那不是真的.
關於愛情我知道很多,我看到過了,看了幾百年了.
唯一能支撐我繼續,看著人類世界的東西,就是愛.
所有的戰爭,痛苦,謊言,仇恨,這些東西想讓我轉過頭去,不再往下看,
我就是來看人類是如何愛的.
我是說,你可以到遙遠的世界的深處去尋找,卻找不到比愛更美的東西,
所以,是的,我知道愛是無條件的,但我也知道愛是不可預知的,無法預料的,無法控制的,無法忍受的,
奇怪的是,愛很容易被錯認為是憎惡.
Tristan,我想說的是...我認為我愛上你了.
我的身體幾乎不能包容住我的心了,好像它不再屬於我了,而是屬於你.
如果你要的話,我會無償的給伱,不需要禮物,不需要條件,不需要證明,什麽都不需要.
我只要你愛我.只要你的心.換取我的心.

2018年2月8日 星期四

技術筆記 微型影像模組


我的左眼

以往提到影像模組,浮上的印象就是WebCam搭配PC執行OpenCV,提供防盜監視或停車場車牌辨識。這些年,硬體技術進步,設備上除了CMOS影像外,還加入如LIDAR和紅外線雷射,軟體上更有強大CPU和GPU、大量訓練資料庫、日益普及的類神經網路模組幫助。讓自駕車在複雜天候和路況中自動行駛,萬千人海中的人臉辨識也成為可行。可以預見的是,這進程將會越來越快,影響層面也會更廣。

但也因為設備和軟體平台專門化,這領域也將成為大公司才能進入的領域。以價格便宜、體積小、功耗低取勝的微型影像模組,必須更專精於自己領域,才能在像白堊紀時,地表上都是大恐龍橫行狀況下,找到個陰暗角落,努力爭取生存空間。

光源與影像


微型影像模組第一種特色就是,輸入光源和影像數量的多樣化。

紅外LED。Leap Motion。C# SDK HACK。最近類似產品是DepthEye 3D visual TOF Depth Camera。價格200美元(好貴啊)
Provide Pointcloud  and RAW depth data
FOV(D* H*V ) :90 * 75 * 59
2 850nm band infrared LED
TI OPT8320 sensor

紅外邊射型雷射LD,例如自己曾經參考過CSK的鍵盤專案就是利用這種直線性雷射光,用亮點形狀偵測位置和距離。常聽的商業工具是LIDAR。CSK的陳士凱有個陽春版本RoboPeak,後來延伸為恩嵐,算是窮人版本LIDAR。

掃描出來的空間地圖

紅外面射型雷射VCSEL。從KINECT開始,就以此種雷射發射結構式紅外雷射,分析拍攝畫面後,就可以取得各點的距離深度。最近的APPLE FaceID也是運用相同原理。

結構光是上述技術的延伸,除紅外雷射外也可採用DLP技術的3D投影出來,Opto有量產品。原理是將數位光圖形 (digital light pattern) 投射在物件上,再利用相機從已知的位置角度拍攝光圖形,以三角量測的方法取得3D數據。投射的光圖形通常是黑白相間的光條。


程式上,最基本範例可以參考這裡

最後是模擬兩眼立體視覺的方案,這也是我現在公司主力產品。兩張圖片依照相同方式找出特徵點,接著計算這兩組點的偏移位置,就可以建構距離模型。參考 項目 範例 YOUTUBE位置 。中文 介紹1 介紹2 介紹3


辨識能力


MCU能達到的辨識能力。

1)規則式比對,如OptRec(STM32)的OCR辨識。

2)統計式(數學式)比對,如HAAR辨識。這篇文章對OpenCV能達到的程度有完整介紹。OpenMV範例。

Eigenfaces

OpenMV

3) 類神經網路比對,如Google AIY的TensorFlow架構,連結
使用INTEL的圖像處理晶片 Movidius MA2450,或是 Orange Pi(文章介紹),完整DIY步驟如下。有了 Google 提供的 3 個基於 TensorFlow 的神經網路模型,用 Vision Kit 進行 DIY 的裝置能夠識別上千種常見物品、識別面部表情或探測拍攝到的人、貓和狗。Google 還提供了 Vision Kit 的模型編譯工具,這樣您就可以在工作站或任何雲服務上用 TensorFlow 對模型進行的訓練和再訓練。

Google AIY

類神經網路其他範例,例如movidius。若嘗試以STM32來運作,最有可能是移植計算的部分,讓複雜的Train交給大型電腦運作,資料存入MCU,MCU只負責算分。

1) STM:複雜運算、奇怪的平台機制  這兩個都不太可行

2) TENSORFLOW:google給手機用的、正在尋找範例,或是這裡
最近更是看到一個介紹,Google提供的TensorFlow Lite for Microcontrollers(連結),直接在Cortex M3就能執行TensorFlow啦,就連OpenMV都有可能可以使用(連結),實在太特別。

3) CAFFE移植CAFFE

其他


幾個可能應用例子工廠案例。

2018年2月7日 星期三

技術筆記 MicroPython


印表玩具
   STM32技術

說明


Python是基本程式語言,可直譯,也可編藝執行。而Micro Python就是運行在MCU上的Python 3(github)。MCU上有完整Python詞法分析器,解析器,編譯器。可離線運行,也可透過命令動態互動。非常適合做時間緊迫,運算複雜度高的應用。缺點是,MicroPython本身佔據不少記憶體空間,MCU上記憶體錙銖必較,或許會有排擠效應。

英文說明如下
MicroPython (GRPL-uPython) is a rewrite of the Python 3.4 programming language tailored for STM32 devices. It offers on-chip compiler, virtual machine and runtime to enable the rapid prototyping of applications. Extension modules provide direct access to the peripherals of the STM32 device. Custom components written in C or C++ can easily be integrated.

移植版本


目前MicroPython可運行於類unix系統、PIC16、ARM、esp8266等平台。STM部分,各種型號的支援程度不同。這裡有目前為止支援的MCU列表。詳細說明在這。分列如下:

1)401開發板,CANNON藍芽開發板

2)405,The pyboard reference development board is a small form-factor electronic circuit board based on a STM32F405 running MicroPython on the bare metal. The STM32 peripherals are exposed via a set of Python functions and classes.

3)407開發板

4)429開發板,有方案,沒套件

運作架構


使用Micro Python需要先產生出空的main.c。
類似空的框架中,INIT和PYTHON_C的對應都會被建立好。main函數位於stmhal/main.c  MCU啟動後進入main函數。

在main函數中大概是初始化MCU的時鐘、各種外部IO的setup,然後執行python的垃圾回收器gc_init(), 初始化python對象列表,相當於啟動了python的虛擬機。

後面緊接着啟動了python的REPL,bind到uart,允許使用者通過外部串口來執行python代碼。

f_res = f_stat("main.py", NULL);
// Parse, compile and execute the main script.
pyexec_file("main.py");
// If there's no script ready, just re-exec REPL
while (!usbdbg_script_ready())
{
    // run REPL
    pyexec_friendly_repl();
  牽涉CONSOLE交互作用的部分,從這個連結可以看到
}
if (usbdbg_script_ready())
{
    // parse, compile and execute script
    pyexec_str(usbdbg_get_script());
}

MicroPython安裝與使用


大致了解後,再來看安裝與使用方式。下載並安裝GNU Tools for ARM Embedded Processors。
sudo apt-get install gcc-arm-none-eabi
window系統下載並安裝ST的DfuSe軟件。
下載MicroPython的源碼,micropython-master.zip
展開MicroPython源碼,打開 stmhal\boards\ 目錄


新建一個CANNON目錄,將NUCLEO_F401RE下的文件複製到CANNON目錄下
在Terminal中進入micropython-master\mpy-cross目錄下

輸入編譯:make
進入micropython-master\stmhal目錄下,輸入 make BOARD=CANNON,就可以編譯了。不過這時編譯出的代碼是不能運行的,因為兩個板子的參數不同。

打開 stmhal\boards\CANNON目錄,先修改文件stm32f4xx_hal_conf.h
找到#define HSI_VALUE    ((uint32_t)8000000)
將數字8000000改為16000000,因為小鋼炮使用了16M的外部時鐘
打開文件 mpconfigboard.h
找到#define MICROPY_HW_CLK_PLLM (8)
將數字8改為16
修改#define MICROPY_HW_HAS_SWITCH  (1)
將1改為0,因為小鋼炮上沒有用戶按鍵
修改#define MICROPY_HW_LED1             (pin_A5) // Green LD2 LED on Nucleo
將pin_A5改為pin_B3,因為兩個板子的LED使用不同的GPIO
修改#define MICROPY_HW_LED_ON(pin)      (mp_hal_pin_high(pin))
將 (mp_hal_pin_high(pin))改為 (mp_hal_pin_low(pin)),因為電路驅動電平不同
修改#define MICROPY_HW_LED_OFF(pin)      (mp_hal_pin_low(pin))
將 (mp_hal_pin_low(pin))改為 (mp_hal_pin_high(pin)),因為電路驅動電平不同
添加下面RTC的定義
// The pyboard has a 32kHz crystal for the RTC
#define MICROPY_HW_RTC_USE_LSE      (1)
#define MICROPY_HW_RTC_USE_US       (0)
#define MICROPY_HW_RTC_USE_CALOUT   (1)
添加UART1
#define MICROPY_HW_UART1_TX      (pin_A9)
#define MICROPY_HW_UART1_RX       (pin_10)
修改SPI1的NSS引腳
#define MICROPY_HW_SPI1_NSS      (pin_A4)
打開文件pins.cvs,這裡預定義了GPIO的名稱
修改LED的GPIO為PB3
修改SW的GPIO為PC13

現在可以再次編譯source code。編譯時建議在Linux下編譯,因為速度快很多,在windows下編譯速度很慢,需要等數分鐘。

準備3個短路塊,連接P1,將BOOT0連接到VCC,BOOT1連接到GND。
將開發板用macroUSB線連接到計算機,因為設置了BOOT0/BOOT1,所以上電後會進入DFU模式。在Windows下如果是第一次使用,會提示安裝驅動,驅動程序就在DfuSe軟件的安裝目錄下。使用DfuSe打開編譯後的dfu文件,並下載到開發板。


從開發角度來看,MicroPython因為結合Python和C,IDE部分,KEIL和uVision都找不到可能的編譯方式。似乎得用gcc編譯。

真正使用時,對話型式的開發環境:

1) openmv有提供一個整合環境( QT產生 )  這是個非常有吸引力的方式。

2) 網路上還有uPyCraft ( 通用型 ) 可以對應處理幾種不同的開發板。

使用方式:透過Python語言控制系統


ESP8266有許多範例,OpenMV操作相似。

因為Micropython已經把開發板各個模組都移植完畢,所以可以直接用Python來控制embedded system,根本不需要加入任何C語言與硬體有關語言,可以快速寫出應用系統。

打開一個串口終端軟件,如kitty、xshell、超級終端等,設置波特率為115200,就可以開始玩micropython了。
先試試直接控制LED
import pyb
pyb.LED(1).on()
pyb.LED(1).off()

在試試用GPIO控制LED。
from pyb import Pin
led=Pin.cpu.B3
led.init(Pin.OUT_PP)
led.value(1)
led.value(0)

用PWM控制LED的亮度
from pyb import Pin, Timer
         
tm2=Timer(2, freq=100)
led=tm2.channel(2, Timer.PWM, pin=Pin.cpu.B3, pulse_width=100)
led.pulse_width_percent(100)
led.pulse_width_percent(1)

呼吸燈
# main.py -- put your code here!
from pyb import Timer, Pin

tm2=Timer(2, freq=200)
led=tm2.channel(2, Timer.PWM, pin=Pin.cpu.B3)

# LED breathing lamp
ia = 1
da = 1
def fa(t):
    global ia, da
    if (ia==0)or(ia==100):
        da=100-da
    ia=(ia+da)0
    led.pulse_width_percent(ia)

tm1=Timer(1, freq=100, callback=fa)

stm32f4如何使用SD

如何製作開發板,第一步,以C程式製作LIB


OpenMV為範例。

若有需要純軟體,例如opencv或是未來的dither,核心C程式,會以LIB形式編譯完成,將interface轉為python可以呼叫的項目,讓Python mapping使用。

例如face_eye_detection.py 內
face_cascade = image.HaarCascade("frontalface", stages=25)
img = sensor.snapshot()
objects = img.find_features(face_cascade, threshold=0.5, scale=1.5)
for face in objects:
    img.draw_rectangle(face)


對應的可以使用的LIB在src\omv\py\py_image.c

static const mp_map_elem_t globals_dict_table[] = {
    {MP_OBJ_NEW_QSTR(MP_QSTR_HaarCascade), (mp_obj_t)&py_image_load_cascade_obj},
};

而對應的function是
mp_obj_t py_image_load_cascade(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
  cascade_t cascade; //這是opencv的結構了
  // Return micropython cascade object
  py_cascade_obj_t *o = m_new_obj(py_cascade_obj_t);
  o->base.type = &py_cascade_type;
  o->_cobj = cascade;
  return o;
}

如何製作開發板,第二步,針對不同開發板,架構MicroPython與硬體對應關係


畢竟不是每個硬體都已經被PYTHON包含,要如何讓板子上的裝置讓PYTHON可用。以DAC為例。啟動之後單片機底層的操作通過micropython-master\stmhal\hal\f4目錄下的HAL驅動來完成,那幺在串口敲下的命令又是如何調用底層的驅動的呢?

拿簡單的DAC來説,與之相關的文檔為micropython-master\stmhal\下的dac.h, dac.c, dac.x文檔聲明並定義了MicroPython board DAC類的方法與屬性,通過MP_DEFINE_CONST_FUN_OBJ_KW或MP_DEFINE_CONST_FUN_OBJ_x等註冊給MicroPython的內建對象。比如下面的函數:pyb_dac_write()函數調用STM32 的HAL lib實現硬件的操作,通過MP將此函數註冊為pyb_dac_write_obj

/// \method write(value)
/// Direct access to the DAC output (8 bit only at the moment).
STATIC mp_obj_t pyb_dac_write(mp_obj_t self_in, mp_obj_t val) {
pyb_dac_obj_t *self = self_in;
if (self->state != DAC_STATE_WRITE_SINGLE) {
DAC_ChannelConfTypeDef config;
config.DAC_Trigger = DAC_TRIGGER_NONE;
config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_DISABLE;
HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel);
self->state = DAC_STATE_WRITE_SINGLE;
}
// DAC output is always 12-bit at the hardware level, and we provide support
// for multiple bit "resolutions" simply by shifting the input value.
HAL_DAC_SetValue(&DAC_Handle, self->dac_channel, DAC_ALIGN_12B_R,
mp_obj_get_int(val) << (12 - self->bits));
HAL_DAC_Start(&DAC_Handle, self->dac_channel);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_dac_write_obj, pyb_dac_write);
最後將所有的方法註冊給MicroPython
STATIC const mp_map_elem_t pyb_dac_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_dac_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_dac_write_obj },
#if defined(TIM6)
{ MP_OBJ_NEW_QSTR(MP_QSTR_noise), (mp_obj_t)&pyb_dac_noise_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_triangle), (mp_obj_t)&pyb_dac_triangle_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_timed), (mp_obj_t)&pyb_dac_write_timed_obj },
#endif
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_NORMAL),      MP_OBJ_NEW_SMALL_INT(DMA_NORMAL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CIRCULAR),    MP_OBJ_NEW_SMALL_INT(DMA_CIRCULAR) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_dac_locals_dict, pyb_dac_locals_dict_table);
const mp_obj_type_t pyb_dac_type = {
{ &mp_type_type },
.name = MP_QSTR_DAC,
.make_new = pyb_dac_make_new,
.locals_dict = (mp_obj_t)&pyb_dac_locals_dict,
};
該結構體在dac.h中聲明為外部變量:
extern const mp_obj_type_t pyb_dac_type;
#if MICROPY_HW_ENABLE_DAC
{ MP_OBJ_NEW_QSTR(MP_QSTR_DAC), (mp_obj_t)&pyb_dac_type },
#endif
因此如果想添加內建的對象或方法應該遵循如下的步驟與原則:
1. 創建mp對象:
const mp_obj_type_t pyb_led_type = {
{ &mp_type_type },
.name = MP_QSTR_LED,   ///name
.print = led_obj_print,       ///重載的print方法
.make_new = led_obj_make_new, ///構造函數
.locals_dict = (mp_obj_t)&led_locals_dict, ///該對象所擁有的方法字典
};

2. 創建方法字典led_locals_dict:


3. 實現方法
實現上圖中畫橫線的方法以及第一步中的重載的print方法,構造方法等。
4. 將mp對象pyb_led_type 添加到modpyb.c中的pyb_module_globals_table[]全局python對象表裏:{ MP_OBJ_NEW_QSTR(MP_QSTR_DAC), (mp_obj_t)&pyb_dac_type }

使用PYBOARD的範例。

編譯MicroPython
一般Build方式 連結
Docker 參考連結

2018年2月4日 星期日

技術筆記 OCR


印表玩具

OptRec專案之分析及測試
因為想多了解STM32在影像分析可達到什麼程度,開始在網路上蒐羅確實可行的範例。OptRec就是其中之一。這是位捷克研究生的碩士論文專案,篇名是Optical Recognition and Analysis for Home Metering。專案與OCR有關。區分成兩個階段。第一階段,是STM32和Camera互動範例技術報告。第二階段是完整流程。YouTube範例作者論文

功能很單純,就是透過鏡頭讀取畫面,送入OCR模組分析文字,再將資料顯示螢幕上,並且記錄入SD卡。互動方式使用觸碰螢幕。

GOCR原理


ocr_gocr : 是入口ocr_algorithm
    job_t job1, *job;
    job=OCR_JOB=&job1;
    // Picture buffer allocation
    img_buffer = malloc(crop_width*crop_height);
    img = malloc(crop_width*crop_height);
    grayscale
    // Assign picture to job
    job->src.p.p = img;
    job->src.p.bpp = 1;
    // Main OCR loop
    img2asc(job);   主要準備開始啟動
    印出結果
    // Free memory
    free_textlines(&(job->res.linelist));
    job_free_image(job);
    free(img);

運作的方式是JOB,可以簡單區分成下面步驟

  scan_boxes( job, pp );
從上往下,分別在X,Y軸方向投影,得到box list


  remove_dust( job ); /* from the &(job->res.boxlist)! */
  detect_barcode( job );  /* mark barcode */
  detect_pictures( job ); /* mark pictures */

所有box的平均寬度為avgwidth,平均高度為avgheight,符合box.width > 4 * avgwidth || height > 4*avgheight條件並且相近大小的box少於4個的box認為是圖像box。

  remove_pictures( job ); /* do this as early as possible, before layout */
  glue_holes_inside_chars( pp ); /* including count subboxes (holes)  */
  detect_rotation_angle( job );
  detect_text_lines( pp, job->cfg.mode ); /* detect and mark job->tmp.ppo */

Line detection is very important for good recognition. For example it is difficult to distinguish between lowercase letter p and uppercase letter P without having a baseline (same total height). The lowercase version of p has a depht (the lower end is below the baseline) and therefore its easy to distinguish from the uppercase version if the baseline is known. The line detection is responsible for finding the baseline of every text line.
Lines of characters are detected by looking for interline spaces. These are characterized by a large number of non-black pixels in a row. Image rotation (skewing) presents a problem, therefore the program first looks only at the left half of the image. When a line is found, the left half of the right side is scanned, because lines are often short. The variation in height gives an indication of the rotation angle. Using this angle, a second run detects lines more accurately. Line detection may fail if there is dust on the image.

  add_line_info( job /* , &(job->res.boxlist) */);
  divide_vert_glued_boxes( pp, job->cfg.mode); /* after add_line_info, before list_sort! */
  remove_melted_serifs( job, pp ); /* make some corrections on pixmap */
  glue_broken_chars( job, pp ); /* 2nd glue */
  remove_rest_of_dust( job );
  list_sort(&(job->res.boxlist), sort_box_func);
  measure_pitch( job );
  char_recognition( pp, job->cfg.mode);

gocr的識別不是機器學習式的學習,沒有training過程,完全靠先驗的規則,因此只能識別英文字符,數字,標點等。識別主要是一個filter鏈路,每個filter決定box是否是該字符,是則略過後續filter。

a,從box外引出一條射線從某個方向(左,右,上,下)某個坐標(x,y)向box內部,第一個交點位置必須符合某個字符的先驗規則;


 b,經過box的一條直線與字符的交點個數必須符合某個字符的先驗規則,算法:計算這樣的點(如從左向右:Pixel(x,y) = white && Pixel(x+1,y) = black ) 的個數


 c,孔洞的個數必須符合某個字符的先驗規則,比如A有一個洞;這一步只是判斷,實際工作在第5步已經完成。


  compare_unknown_with_known_chars( pp, job->cfg.mode);
  try_to_divide_boxes( pp, job->cfg.mode);
參考來源

各檔案列表
output : debug使用
unicode : 只是顯示文字

GOCR移植OptRec


硬體內容
  stm32f429 discovery (相同)
  ov7670 (相同)
  sdcard (具備)
軟體內容
  console tool chain (非keil)
  sdcard : fatfs
  ocr : GOCR v0.50

這功能在尋常桌機加OpenCV看來,實在是一塊小蛋糕。但在嵌入式系統,包含這個多程式碼,且有UI互動界面,實屬難得啊。分析模組如下。

main.c
   宣告許多起始動作
   控制流程
while(1){
     很特別的command dispatch架構
    /* TASK 1 - Home page display/refresh */
    if (Time_elapsed(200, &task_arr[1])){
        if (sys_mode == SYS_INIT) {
                // Display main page
                LCD_ILI9341_Button_DisableAll();
                Display_Home_Page();
                sys_mode = SYS_HOME;
            }
    }
      /* TASK 2 - Buttons/touch service */
     if (Time_elapsed(100, &task_arr[2])){
            // Home page buttons
            // - Manual mode
            if (button_pressed == BUTTON_MANUAL_MODE){
                LCD_ILI9341_Button_DisableAll();
                Camera_Enable();
                sys_mode = SYS_MANUAL_MODE;
            }
            // - Automatic mode
            else if (button_pressed ==  BUTTON_AUTOMATIC_MODE){
                LCD_ILI9341_Button_DisableAll();
                Display_Automatic_Mode_Page();
                sys_mode = SYS_AUTOMATIC_MODE;
            }
            // - Display data logs
            else if (button_pressed == BUTTON_DISPLAY_LOGS){
                LCD_ILI9341_Button_DisableAll();
                Display_Data_Logs_Page();
                sys_mode = SYS_END;
            }
            // - Settings
            else if (button_pressed == BUTTON_SETTNGS_MODE){
                LCD_ILI9341_Button_DisableAll();
                Display_Settings_Page();
                sys_mode = SYS_SETTINGS_MODE;
            }
            ...還有很多... 這種寫法很特別
     }
     /* TASK 3 - Clock display/refresh */
     if (Time_elapsed(1000, &task_arr[3])){
            if (sys_mode == SYS_HOME) {
                Display_Clock();
            }
     }
     /* TASK 4 - Battery voltage display/refresh */
        if (Time_elapsed(2000, &task_arr[4])){
            if (sys_mode == SYS_HOME) {
                Display_Battery();
            }
     }
}
包括一些callback的handler

/* DCMI DMA interrupt */
void DMA2_Stream1_IRQHandler(void){

/* LCD SPI interrupt */
void DMA2_Stream4_IRQHandler(void){

/* Button GPIO interrupt */
void EXTI0_IRQHandler(void) {
 
/* TOUCH GPIO interrupt */
void EXTI15_10_IRQHandler(void) {

其他程式

1)err_handler : 顯示一些文字,並且一直繞while

2)fatfs_control : APP用到的指令
fats_spi : 一開始設定
fat有個目錄有七個相關檔案

3)lcd_fonts : 字型resource
lcd_ili9341 : 畫圖畫線等
lcd_ili9341_button : 畫出按鈕,並且按下去會有相對記錄
lcd_spi : 設定和DMA等等
background : 印出圖片背景固定顏色

4)ov7670_control : camera固定設定

5)rtc_awu_control : RTC_AWU_SetDateTime RTC_AWU_GetUnixTimeStamp
     RTC_AWU_GetDateTime RTC_AWU_SetAlarm

6)system_control : init一堆東西 顯示各個不同畫面
stm32f4xx_it 固定寫法
system_stm32f4xx 固定寫法

7)touch_i2c : touch
touch_stmpe811

記憶體使用


是影像處理很重要的部分。
fmc_sdram : 只有init,真正使用應該是malloc 不過下載項目中沒有sct之類檔案
syscalls
* Modification of system memory management (e.g. malloc etc.).
* Simply moves heap region to external SDRAM.
* Important is to initialize FMC for SDRAM soon as possible.
* Optimized for 32F429IDISCOVERY board.
會換掉 _sbrk
caddr_t _sbrk(int incr) {
    static char *heap_end;
    static char *sdram_start = (char*) SDRAM_MEM_START;
    static char *sdram_end = (char*) SDRAM_LCD_START1;
    重點應該是 static char * 雖然是function內部變數,但
    char *prev_heap_end;
    // Modify system memory management
    if (heap_end == 0) {
        heap_end = sdram_start;
    }
    prev_heap_end = heap_end;
    if (heap_end + incr > sdram_end) {
        return  (caddr_t) -1;
    }
    heap_end += incr;
    return (caddr_t) prev_heap_end;
}