Slide 1

Slide 1 text

Raspberry Pi Camera + Python 台灣樹莓派 May 31, 2015 / PyCon APAC 2015

Slide 2

Slide 2 text

2

Slide 3

Slide 3 text

姓名標示 — 非商業性 — 相同方式分享 CC (Creative Commons) 姓名標示 — 你必須給予 適當表彰、提供指向本授權 條款的連結,以及 指出(本作品的原始版本)是否已 被變更。你可以任何合理方式為前述表彰,但不得以 任何方式暗示授權人為你或你的使用方式背書。 非商業性 — 你不得將本素材進行商業目的之使 用。 相同方式分享 — 若你重混、轉換本素材,或依本 素材建立新素材,你必須依本素材的授權條款來 散布你的貢獻物。

Slide 4

Slide 4 text

4 ● Raspberry Pi 官方經銷商 ● 專注 Raspberry Pi 應用與推廣 , 舉辦社群活動 關於我們

Slide 5

Slide 5 text

5 ● COSCUP,MakerConf,PyCon,HKOSCon 講者 ● 投影片 ● https://speakerdeck.com/piepie_tw ● 程式碼 ● https://github.com/piepie-tw 分享 x 教學

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

● Raspberry Pi Camera 簡介 ● 基礎 Camera 使用 ● 寫程式控制 今天會講

Slide 8

Slide 8 text

沒有螢幕與鍵盤如何使用樹莓派?

Slide 9

Slide 9 text

9 環境設定: Serial + WiFi 1. 樹莓派 Serial 連線 2. 樹莓派 WiFi 連線 用 Serial 來設定 WiFi 3. 筆電、手機、樹莓派 在同一個 LAN

Slide 10

Slide 10 text

10 ● 以 USB 轉 TTL 傳輸線和 Pi 相連 ● 接線方式 ● 黑色: Pin 6 (GND) ● 白色: Pin 8 (Tx) ● 綠色: Pin 10 (Rx) ● 紅色:不接 Serial 連線方式

Slide 11

Slide 11 text

11 Raspberry Pi B 的 GPIO (P1) 黑色線接 6 號 ( 第三根 ) 白色線接 8 號 ( 第四根 ) 綠色線接 10 號 ( 第五根 ) http://elinux.org/RPi_Low-level_peripherals

Slide 12

Slide 12 text

12 Raspberry Pi B+ 的 GPIO (P1) 黑色線接 6 號 ( 第三根 ) 白色線接 8 號 ( 第四根 ) 綠色線接 10 號 ( 第五根 ) http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/

Slide 13

Slide 13 text

13 ● 安裝驅動程式 , http://goo.gl/QC5Q3O ● 從裝置管理員找到 COM 的埠號 ( 本例為 COM9) ● 下載 putty, http://goo.gl/zdD9G9 ● 執行 putty ● Session ● Serial line 填 COM9 ● Speed 填入 115200 ● Open ! ● 沒畫面 , 重新插拔電源 Serial Port in Windows

Slide 14

Slide 14 text

14 ● $ ls /dev/ttyUSB* ● 開啟 putty ● 選擇 Session ● 在 Serial line 填入 /dev/ttyUSB0 ( 本例為 ttyUSB0) ● Speed 填入 115200 ● Open ! ● 無法連線時 , 使用 sudo 執行 putty Serial Port in Linux

Slide 15

Slide 15 text

15 ● 安裝驅動程式 , http://goo.gl/htlt3F ● 重開機生效 ● $ ls /dev/cu* ● 如果有 /dev/cu.usbserial ● $ screen /dev/cu.usbserial 115200 ● 如果沒畫面,重新插拔電源 Serial Port in Mac

Slide 16

Slide 16 text

16 ● 預設帳號 / 密碼: pi / raspberry ● 如果沒有畫面,將電源重新插拔 ● 如果出現亂碼,確定 baud rate 為 115200 連線成功

Slide 17

Slide 17 text

17 ● 登入畫面 ● pi 是登入的使用者 ● @ 表示”在” ● raspberrypi 是主機名稱 ● ~ 表示在家目錄 (home directory) ● $ 表示該使用者所使用的 shell( 一種文字工具介面 ) ● 例如 $ nano myfile.txt ● 表示用 nano 編輯器開 myfile.txt 檔案 符號說明

Slide 18

Slide 18 text

18 使用: nano 離開: Ctrl + x > 令存新檔: y > 不存離開: n > 離開: Ctrl + c nano 編輯器使用

Slide 19

Slide 19 text

19 $ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf # /etc/wpa_supplicant/wpa_supplicant.conf ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 ● 請參考“ [ 基礎 ] 命令列設置無線網路” ● http://www.raspberrypi.com.tw/2152/setting-up- wifi-with-the-command-line/ 在文字模式下設定無線網路

Slide 20

Slide 20 text

20 $ sudo ifdown wlan0 $ sudo ifup wlan0 $ sudo kill -9 $(ps -ef | grep wpa | awk '{print $2}') $ sudo wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf $ sudo dhclient wlan0 指令列設定 WiFi - 連線

Slide 21

Slide 21 text

21 $ ifconfig wlan0 IP = 192.168.43.102 連線成功 查詢 IP

Slide 22

Slide 22 text

22 ● 預設帳號 / 密碼: pi / raspberry 有了 IP, 用 SSH 連線

Slide 23

Slide 23 text

23 ● Raspberry Pi 端 ● $ sudo apt-get install tightvncserver ● $ vncserver ● PC 端 ● Linux 使用 vncviewer ● Windows 下載 TightVNC ● 連線 Raspberry Pi ( 下為範例 IP) ● vncviewer 192.168.43.102: 5901 ● tightvnc 192.168.43.102::5901 ● 更多使用方法 ● http://www.raspberrypi.com.tw/586/setting-up-vnc/ 想要視窗 , 設定 VNC( 今天不需設 定 )

Slide 24

Slide 24 text

● $ sudo apt-get install -y vlc ● $ sudo apt-get install -y gpac mplayer ● $ sudo apt-get install -y mencoder ● $ sudo apt-get install -y python-opencv ● $ sudo apt-get install -y python-pip ● $ sudo pip install requests ● $ sudo pip install flask 安裝今日所需軟體

Slide 25

Slide 25 text

Raspberry Pi Camera 簡介

Slide 26

Slide 26 text

從手機相機模組講起 http://www.phonearena.com/news/13MP-camera-tipped-for-Samsung-Galaxy-S-IV_id35168 1. Lens( 透鏡 ) 2. VCM( 音圈馬達 ) 3. IR-Cut( 紅外光濾片 ) 4. Sensor( 感光元件 ) 5. PCB( 印刷電路板 ) 6. ISP( 影像訊號處理器 )

Slide 27

Slide 27 text

● 問:樹葉為什麼看起來是綠色的? ● 答:因為樹葉吸收了大部分可見光,只反射綠色光 基礎光學原理 https://www.raspberrypi.org/learning/infrared-bird-box/worksheet/

Slide 28

Slide 28 text

Type of Raspberry Pi Camera http://elinux.org/Rpi_Camera_Module Raspberry Pi Camera Module NoIR Camera Module

Slide 29

Slide 29 text

● Sensor: OmniVision OV5647 Color CMOS QSXGA (5M) ● 靜態拍照最高解析度: 2592 x 1944 pixel ● Pixel Size: 1.4 x 1.4 um ● Lens: f=3.6 mm, f/2.9 ● Angle of View: 54 x 41 degrees ● Field of View: 2.0 x 1.33 m at 2 m ● Fixed Focus: 1m to infinity ● 動態攝影最高解析度: 1080p@30 FPS with H.264/AVC 技術規格

Slide 30

Slide 30 text

Raspberry Pi Camera Module https://www.modmypi.com 15-Pins, CSI 介面 綠色 PCB 板

Slide 31

Slide 31 text

● No IR = No 'IR cut filter' installed ● 因此 CMOS 可吸收到不可見光 (Infrared) ● No IR 相機 ≠ 夜視相機 ● 除非有額外的紅外線發光源 No IR Camera 黑色 PCB 板

Slide 32

Slide 32 text

兩種相機效果比較 http://www.themagpi.com/issue/issue-18/ 1. 非 NoIR 相機 2. NoIR 相機 3. NoIR 相機 4. NoIR 相機 + 藍色濾光片

Slide 33

Slide 33 text

Raspberry Pi Camera 應用簡介

Slide 34

Slide 34 text

移動偵測攝影 http://www.codeproject.com/Articles/665518/Raspberry-Pi-as-low-cost-HD-surveillance-camera

Slide 35

Slide 35 text

IP Camera 以樂高做外殼 加上 Camera 與按鍵

Slide 36

Slide 36 text

36 雲端相機 http://learn.adafruit.com/diy-wifi-raspberry-pi-touch-cam 可做影像辨識的相機 5

Slide 37

Slide 37 text

人臉辨識與追蹤 https://github.com/tasanakorn/rpi-mmal-demo/tree/develop

Slide 38

Slide 38 text

脈博辨識 https://github.com/thearn/webcam-pulse-detector

Slide 39

Slide 39 text

3D 建模計算深度 /2 Cameras http://www.raspberrypi.org/real-time-depth-perception-with-the-compute-module/

Slide 40

Slide 40 text

360 度照片 https://vimeo.com/77218985

Slide 41

Slide 41 text

效果

Slide 42

Slide 42 text

3D 掃描 /50 Cameras http://www.pi3dscan.com/

Slide 43

Slide 43 text

效果 + Autodesk Recap http://www.pi3dscan.com/

Slide 44

Slide 44 text

Camera 改裝套件

Slide 45

Slide 45 text

固定的機構 http://www.modmypi.com/

Slide 46

Slide 46 text

鏡頭改裝 http://www.modmypi.com/

Slide 47

Slide 47 text

惡改鏡頭 http://www.truetex.com/raspberrypi

Slide 48

Slide 48 text

外殼改裝 http://www.modmypi.com/ http://blog.pi3g.com/2013/11/coming-soon-raspberry-with-case-mounted-camera/

Slide 49

Slide 49 text

Camera 安裝

Slide 50

Slide 50 text

安裝 Raspberry Pi Camera http://goo.gl/7LqyMY

Slide 51

Slide 51 text

$ sudo raspi-config

Slide 52

Slide 52 text

啟用 Raspberry Pi Camera

Slide 53

Slide 53 text

進階選項

Slide 54

Slide 54 text

設定記憶體分配 >128M

Slide 55

Slide 55 text

實戰 Camera 使用

Slide 56

Slide 56 text

使用 Camera 前先消除靜電吧 http://www.wikihow.com/Remove-Static-Electricity

Slide 57

Slide 57 text

57 實驗 1 : Hello Camera 目的:練習照相和攝影的指令

Slide 58

Slide 58 text

● 只預覽 2 秒 (-t), 不存檔 ● $ raspistill -t 2000 ● 5 秒後拍照 , 檔案 test.jpg(-o), 印出詳細訊息 (-v) ● $ raspistill -v -o test.jpg ● 3 秒後拍照 , 並編碼成 png 格式 (-e), 長 640x 寬 480 ● $ raspistill -t 3000 -o test.png -e png -w 640 -h 480 RaspiStill https://www.raspberrypi.org/documentation/usage/camera/raspicam/raspistill.md

Slide 59

Slide 59 text

常見 Camera 問題?

Slide 60

Slide 60 text

● 錯誤訊息: Camera is not enabled in this build ● 解法:進 raspi-config 重新 enable camera ● $ sudo raspi-config

Slide 61

Slide 61 text

● 錯誤訊息: Camera is not detected ● 解法:重新安裝 camera, 或是更換排線 或是檢查 camera module 是否鬆脫 https://www.modmypi.com/blog/how-to-replace-the-raspberry-pi-camera-cable

Slide 62

Slide 62 text

● 錄 5 秒 (-t) 1080p30 影片 ( 預設 w/h = 1920/1080) ● $ raspivid -t 5000 -o video.h264 ● 影片存檔名稱 video.h264(-o), bitrate 為 3.5MBits/s(-b) ● $ raspivid -t 5000 -o video.h264 -b 3500000 ● 錄 5 秒的 1080p30 影片 , 長 640x 寬 480 ● $ raspivid -t 5000 -w 640 -h 480 RaspiVid https://www.raspberrypi.org/documentation/usage/camera/raspicam/raspivid.md

Slide 63

Slide 63 text

$ nano camera_effect.sh ● #!/bin/bash for effect in none negative solarise sketch denoise emboss oilpaint hatch gpen pastel watercolour film blur saturation colourswap washedout posterise colourpoint colourbalance cartoon do echo $effect raspivid -d -ifx $effect done $ chmod 755 camera_effect.sh $ ./camera_effect.sh 用 RaspiVid 看 Camera 內建的效果 http://www.ics.com/blog/raspberry-pi-camera-module

Slide 64

Slide 64 text

64 DEMO ./camera_effect.sh

Slide 65

Slide 65 text

65 $ git clone https://github.com/raspberrypi-tw/camera-python.git $ cd camera-python $ cd 01_hello_camera $ ./camera_effect.sh 需要接上螢幕才能看到效果 執行方式

Slide 66

Slide 66 text

更多參數或用法請看文件 http://goo.gl/VhyBaL https://www.raspberrypi.org/wp-content/uploads/2013/07/RaspiCam-Documentation.pdf

Slide 67

Slide 67 text

如何看照片和影片?

Slide 68

Slide 68 text

68 ● 是一種圖形應用標準 ● Client/Server 架構 ● X Client : 應用程式 ● X Server : 管理硬體輸入 / 輸出 ● 可透過網路傳輸 ● TCP/IP 或是 Unix Domain Socket ● X11 是通訊協定名稱 X Window System http://keyj.emphy.de/files/linuxgraphics_en.pdf

Slide 69

Slide 69 text

69 ● Windows( 使用 Xming + putty) ● Xming 安裝 (http://sourceforge.net/projects/xming/)+ 下一步到底 ● putty > SSH > X11 > Enable X11 forwarding ● Linux/Mac : ssh -X [email protected] X11 Forwarding using SSH

Slide 70

Slide 70 text

● 看照片 ● $ gpicview image.jpg ● 看影片 ● H.264 格式可直接用 VLC 看 ● $ vlc video.h264 ● 或是將 H.264 轉成 MP4 後用 mplayer 看 ● $ MP4Box -fps 30 -add video.h264 video.mp4 ● $ mplayer video.mp4 X11 Forwarding 連線成功後

Slide 71

Slide 71 text

● 第一步:編輯 /etc/sshd_config 修改這行 # X11Forwarding no 把它改成 yes 並且把註解拿掉 ● 第二步:下載安裝 XQuartz 並重開機 http://xquartz.macosforge.org/landing/ ● 感謝 Dami 和 YUN-TAO CHEN 的貢獻 “Can not open display” on Mac https://hackpad.com/X11-Forwarding-FcyKHioKxmW

Slide 72

Slide 72 text

嫌慢的話直接用網路線對接 https://pihw.wordpress.com/guides/direct-network-connection/

Slide 73

Slide 73 text

● 在 Pi ● $ sudo ifconfig eth0 192.168.2.2 netmask 255.255.255.0 ● 在 Windows ● 在 Linux/Mac ● $ sudo ifconfig eth0 192.168.2.1 netmask 255.255.255.0 網路設定

Slide 74

Slide 74 text

74 實驗 2 :縮時攝影 目的:簡單合成影片做特效

Slide 75

Slide 75 text

縮時攝影 (Time-Lapse Photography) http://en.wikipedia.org/wiki/Time-lapse_photography

Slide 76

Slide 76 text

● 每間隔一段時間拍一張 ● 再將所有的照片接在一起 ● 調整播放速度 x = x 倍速的視覺效果 概念 http://en.wikipedia.org/wiki/Time-lapse_photography

Slide 77

Slide 77 text

● 60 秒內每 1 秒拍一張 , 檔案名稱遞增 (4 位數 ) ● $ raspistill -t 60000 -tl 1000 -o image%04d.jpg -bm -w 640 -h 480 ● 所有的照片接在一起 ● $ ls *.jpg > stills.txt ● 調整播放速度 4 = 4 倍速的視覺效果 ● $ mencoder -nosound -ovc lavc -lavcopts vcodec=mpeg4:aspect=4/3:vbitrate=8000000 -vf scale=640:480 -o timelapse.avi -mf type=jpeg:fps=4 mf://@stills.txt 實做 http://www.raspberrypi.org/learning/timelapse-setup/

Slide 78

Slide 78 text

78 DEMO ./time_lapse.sh vlc timelapse.avi

Slide 79

Slide 79 text

79 $ cd ../02_time_lapse $ ./time_lapse.sh 執行完畢後會多一個 timelapse.avi 檔案 , 使用 VLC 觀看 $ vlc timelapse.avi 執行方式

Slide 80

Slide 80 text

80 實驗 3 :用手機 App 控制 目的:沒有螢幕也可以玩 camera

Slide 81

Slide 81 text

RaspiCam Remote @ Android

Slide 82

Slide 82 text

連線 & 錄影

Slide 83

Slide 83 text

調整效果:亮度

Slide 84

Slide 84 text

84 實驗 4 :網路串流 目的:用播放器看結果

Slide 85

Slide 85 text

Streaming Media 技術架構 http://www.consilient-tech.com/strmmeda.shtml

Slide 86

Slide 86 text

RTSP 通訊協定 RTSP Client RTSP Server RTSP (TCP) : initiate RTP (UDP) : content RTCP (UDP) : control

Slide 87

Slide 87 text

● 在 Raspberry Pi $ raspivid -o - -t 0 -w 320 -h 240 -n | cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554/}' :demux=h264 ● 在 Windows/Linux 使用 VLC ● rtsp://raspberrypi 的 ip:8554/ ● 在 iPhone/iPad 上 ● rtsp://raspberrypi 的 ip:8554/ ● 8554 後面的斜線很重要 , 要加 如何使用 RTSP + H.264 ? http://www.raspberry-projects.com/pi/pi-hardware/raspberry-pi-camera/streaming-video-using-vlc-player

Slide 88

Slide 88 text

Live Media Player @ iPhone

Slide 89

Slide 89 text

開啟 RTSP 串流

Slide 90

Slide 90 text

90 DEMO ./rtsp_stream.sh 要配合電腦或手機觀看

Slide 91

Slide 91 text

● 在 Raspberry Pi 上 ( 需要先安裝 UV4L) ● cvlc v4l2:///dev/video0 --v4l2-width 320 --v4l2-height 240 --sout '#transcode{vcodec=MJPG,width=320,height=240,vb =1000}:duplicate{dst=std{access=http{mime=multipar t/x-mixed-replace;boundary=-- 7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,d st=:8080/video.mjpg}'} ● 開啟 Browser ● http://raspberrypi 的 ip:8080/video.mjpg HTTP + MJPEG https://goo.gl/U9zhEO

Slide 92

Slide 92 text

v4l2:///dev/video0 這是什麼東西? - 非官方的 V4L2 Driver

Slide 93

Slide 93 text

回來看 camera 你有用過 webcam 嗎?

Slide 94

Slide 94 text

94 Webcam http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals

Slide 95

Slide 95 text

● 預定義好的 Userspace API ● Video and radio streaming devices ● video cameras ● analog and digital TV receiver cards ● AM/FM receiver cards Video4Linux 2nd(V4L2) http://free-electrons.com/doc/embedded_linux_multimedia.pdf /dev/video0 Driver Hardware App1 (fd1) App2 (fd2) ioctl() ioctl() read() write() Identifying App1 and App2 by different file descriptors, the driver can send them different data.

Slide 96

Slide 96 text

Camera ≠ Webcam

Slide 97

Slide 97 text

97 Modern Device Internal http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals

Slide 98

Slide 98 text

98 Image Processing Pipeline http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals

Slide 99

Slide 99 text

99 Image Processing Pipeline http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals ISP 在做的事 (HW) color space/format 轉換 (SW)

Slide 100

Slide 100 text

100 http://elinux.org/Raspberry_Pi_VideoCore_APIs

Slide 101

Slide 101 text

101 ● 開放多媒體加速層 (Open Media Acceleration) ● 由 Khronos Group 提出的標準 ● 統一的介面,加速大量多媒體資料的處理 OpenMAX https://www.khronos.org/openmax/

Slide 102

Slide 102 text

102 Multimedia Stack Example http://wiki.maemo.org/Documentation/Maemo_5_Developer_Guide/Architecture/Multimedia_Domain

Slide 103

Slide 103 text

103 ● Kernel driver ● 使用 camera 像是 webcam 一樣 ● sudo modprobe bcm2835-v4l2 ● 可直接存取 /dev/videoX ● v4l2-ctl --list-devices ● v4l2-ctl --list-formats ● v4l2-ctl -L ×Official V4L2 Driver https://github.com/raspberrypi/linux/blob/rpi-3.10.y/Documentation/video4linux/bcm2835-v4l2.txt

Slide 104

Slide 104 text

104 ● 安裝 ● $ sudo apt-get install v4l-utils ● 缺點 ● closed sourced ● slow because it runs as a user program ● 相關應用 ● Real-time HTTP Streaming Server with the native uv4l-server module(MJPEG/H264/JPEG) ● Object detection and object tracking ● Compute module: stereoscopic vision User Space V4L2 Driver(UV4L) http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=16

Slide 105

Slide 105 text

105 ● 參考這幾隻程式吧 ● raspicam ● https://github.com/raspberrypi/userland/tree/master/h ost_applications/linux/apps/raspicam ● rpi-omx-tutorial ● https://github.com/SonienTaegi/rpi-omx-tutorial ● omxcam ● https://github.com/gagle/raspberrypi-omxcam ● rpi-mmal-demo ● https://github.com/tasanakorn/rpi-mmal- demo/tree/develop 但我想使用 C 語言接到 OpenMAX

Slide 106

Slide 106 text

106 實驗 5 :寫程式控制 Camera 目的:自己的 Camera 自己做

Slide 107

Slide 107 text

使用 picamera (Python library)

Slide 108

Slide 108 text

108 ● 變數 , 物件 , 型別 , 註解 ● 模組 ● 縮排 ● 迴圈 ● 條件判斷 ● 函式 ● 例外處理 ● with as Python 五分鐘速成

Slide 109

Slide 109 text

109 ● 動態型別 (dynamic typing) # 這是註解 i = 3 # 變數 i 指到數字物件 3 i = [1, 2, 3, 4, 5] # 變數 i 指到串列物件 print(i[2]) # 印出串列中第三個元素 i = “abcde” # 變數 i 指到字串物件 print(i[2]) # 印出字串中第三個元素 變數 , 物件 , 型別 , 註解

Slide 110

Slide 110 text

110 # import MODULE import RPi.GPIO # import MODULE as ALIAS import RPi.GPIO as GPIO # from MODULE import FUNCTION from time import sleep 模組 http://programmers.stackexchange.com/questions/187403/import-module-vs-from-module-import-function

Slide 111

Slide 111 text

111 ● 用縮排取代大括號 ● 程式碼的區塊是用縮排分隔 ● 不使用 tab, 使用空白鍵 ● 常見縮排為 4 個空白鍵 縮排

Slide 112

Slide 112 text

112 ● 自動迭代 (iterator) for TARGET in LIST : # aaa ● # bbb # ccc # nameS = ["paul", "mary", "tom", "rita"] # for name in nameS : # print name 迴圈

Slide 113

Slide 113 text

113 if CONDITION_1 : PROCESS_1 elif CONDITION_2 : PROCESS_2 else : PROCESS_3 ● # grade = 60 # if grade > 60 : # print "great" # else : # print "too bad" 條件判斷

Slide 114

Slide 114 text

114 def FUNCTION() : PROCESS def FUNCTION( PARAM ) : PROCESS def FUNCTION( PARAM = 3) : PROCESS # def my_function(input = 5) : # print (input) 函式

Slide 115

Slide 115 text

115 ● 程式何時會結束 ? ● 在正常情況下執行完畢結束 ● 遇到錯誤跳出 ● 受到中斷停止 ( 收到終止訊號 , 例如 Ctrl+c) file = open('demo.py', 'r', encoding='UTF-8') try: for line in file: print(line, end='') except: print(' 讀取檔案發生錯誤 ') finally: file.close() try, except, finally http://openhome.cc/Gossip/Python/WithAs.html

Slide 116

Slide 116 text

116 ● 使用 with as 來簡化 try exception 程式 with open('demo.py', 'r', encoding='UTF-8') as file: for line in file: print(line, end='') with... as... http://openhome.cc/Gossip/Python/WithAs.html

Slide 117

Slide 117 text

#!/usr/bin/python ● import time import picamera with picamera.PiCamera() as camera: ● camera.start_preview() # The default resolution is 1280x800 camera.capture('image.jpg') ● 預設相片解析度為 1280x800 照相 http://picamera.readthedocs.org/en/release-1.8/recipes1.html

Slide 118

Slide 118 text

118 DEMO python picamera_take_photo.py 執行方式 $ cd ../05_picamera $ python picamera_take_photo.py

Slide 119

Slide 119 text

119 ● 使用 scp ● 一個實做 SCP(Secure Copy Protocol) 的應用程式 ● 透過 SSH(Secure Shell) 傳輸資料 ● Windows 請安裝 WinSCP ● http://winscp.net/eng/download.php ● 從 Pi 複製檔案到 PC 上 ● scp [email protected]:/home/pi/file.txt . ● scp file.txt [email protected]:/home/pi 如何讓 Pi 和 PC 互傳檔案? http://winscp.net/

Slide 120

Slide 120 text

#!/usr/bin/python ● import picamera ● ● with picamera.PiCamera() as camera: ● camera.start_recording('video.h264') ● camera.wait_recording(3) camera.stop_recording() ● 錄 3 秒鐘影像 , 儲存到檔案 video.h264 ● 預設錄影格式為 H.264/AVC 壓縮 , 解析度 1280x800 錄影 http://picamera.readthedocs.org/en/release-1.8/recipes1.html

Slide 121

Slide 121 text

#!/usr/bin/python ● import picamera ● ● with picamera.PiCamera() as camera: ● camera.resolution = (640, 480) ● camera.iso = 200 ● camera.exposure_mode = 'off' ● g = camera.awb_gains ● camera.awb_mode = 'off' ● camera.awb_gains = g ● camera.start_recording('video.h264', quality=23) ● camera.wait_recording(3) camera.stop_recording() 更多使用參數 http://picamera.readthedocs.org/en/release-1.8/recipes1.html

Slide 122

Slide 122 text

122 DEMO python picamera_record_video.py python picamera_more.py

Slide 123

Slide 123 text

加上一個按鍵吧

Slide 124

Slide 124 text

124 ● 開關:按鍵式 , 滑動式 , 傾斜式 ... ● 常開 (normal open, N.O.) ● 常閉 (normal close, N.C.) 按鍵 Button / 開關 Switch http://nicegear.co.nz/

Slide 125

Slide 125 text

125 ● 開關:按鍵式 , 滑動式 , 傾斜式 ... ● 常開 (normal open, N.O.) ● 常閉 (normal close, N.C.) 按鍵 Button / 開關 Switch

Slide 126

Slide 126 text

126 按鍵的內部結構 ● 按下前 ● 長邊相連 (1&2, ¾3&4) ● 短邊不相連 ● 按下後 ● 四點都通

Slide 127

Slide 127 text

127 要接哪一個腳位?

Slide 128

Slide 128 text

128 ● GPIO is a flexible software-controlled digital signal ● A generic pin on an IC General Purpose Input Output(GPIO) http://raspberrypihobbyist.blogspot.tw/2012/09/so-many-inputs-so-few-gpio-pins.html

Slide 129

Slide 129 text

129 Model B vs. B+ http://elinux.org/RPi_Low-level_peripherals http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/

Slide 130

Slide 130 text

130 Raspberry Pi Model B 的 GPIO (P1) http://elinux.org/RPi_Low-level_peripherals SPI / I2C / UART / PWM Pin1 Pin2 Pin25 Pin26

Slide 131

Slide 131 text

131 ● 決定是輸入還是輸出 ● 寫值到某根腳位 ● 從某根腳位讀值 ● 決定是前緣觸發還是後緣觸發 ● 等待中斷 (interrupt) 的發生 GPIO 是硬體的事 , 那軟體做什麼 ?

Slide 132

Slide 132 text

132 ● 6 、 9 、 14 、 20 等腳位為接地,可互相交換 GPIO 腳位意義對照表 http://wiringpi.com/wp-content/uploads/2013/03/pins.pdf

Slide 133

Slide 133 text

133 簡單的按鍵接法 BUTTON RPi 腳 1 Pin6 (Ground) 腳 3 Pin11 (GPIO0)

Slide 134

Slide 134 text

134 ● Input 空接會讀到雜訊 問題在哪裡? BUTTON RPi 腳 1 Pin6 (Ground) 腳 3 Pin11 (GPIO0)

Slide 135

Slide 135 text

135 麵包板的種類 https://goo.gl/JipVgH

Slide 136

Slide 136 text

136 麵包板的使用 http://bugworkshop.blogspot.tw/2012/12/diy-breadboard.html 1. 藍色和綠色兩塊不通 2. 藍色垂直相通 3. 紅色水平相通 麵包板的內部結構

Slide 137

Slide 137 text

137 更好的按鍵接法 http://geekgurldiaries.blogspot.tw/2012/12/part-2.html

Slide 138

Slide 138 text

138 上拉電阻 / 下拉電阻 - 兩種電路的接法 http://playground.arduino.cc/CommonTopics/PullUpDownResistor

Slide 139

Slide 139 text

139 上拉電阻 / 下拉電阻 - 還沒按下按鍵時 http://playground.arduino.cc/CommonTopics/PullUpDownResistor

Slide 140

Slide 140 text

140 上拉電阻 / 下拉電阻 - 按下按鍵以後 http://playground.arduino.cc/CommonTopics/PullUpDownResistor

Slide 141

Slide 141 text

141 線路圖 ( 上拉電阻 ) BUTTON RPi 腳 1 Pin6 (Ground) 腳 3 Pin11 (GPIO0) Pin1 (3.3V) 1K 電阻 2K 電阻

Slide 142

Slide 142 text

142 BTN_PIN = 11 GPIO.setup(BTN_PIN, GPIO.IN) try: while True: if GPIO.input(BTN_PIN) == GPIO.LOW: print("Button.Click") except KeyboardInterrupt: print "Exception: KeyboardInterrupt" finally: GPIO.cleanup() 按下按鍵的判斷條件 ( 上拉電阻 )

Slide 143

Slide 143 text

143 DEMO sudo python push_button_poll.py 讀寫 GPIO 會存取 /dev/mem, 需 root 權限 sudo 表示暫時切換身份到其他使用者 (root)

Slide 144

Slide 144 text

144 ● 機械式開關在切換過程中會有訊號彈跳現象 ( 雜訊 ) 開關訊號的彈跳問題 (bounce) http://120.101.72.1/Onechip/PPT/ 實習單元三 .ppt 理想訊號輸出 實際輸出訊號

Slide 145

Slide 145 text

145 ● 硬體方法:以 RC 電路或正回授的比較器電路解決 ● 軟體方法:調整觸發的延遲時間 ● 不同的按鍵會有不同的延遲時間 解決彈跳問題 (de-bounce) 10ms - 20ms

Slide 146

Slide 146 text

146 TIME_LAPSE = 0.2 GPIO.setup(BTN_PIN, GPIO.IN) previousTime = time.time() try: while True: currentTime = time.time() if GPIO.input(BTN_PIN) == GPIO.LOW and \ (currentTime - previousTime) > TIME_LAPSE: previousTime = currentTime print("Button.Click") except KeyboardInterrupt: GPIO.cleanup() 軟體方法:不反應在延遲時間內的觸發

Slide 147

Slide 147 text

147 DEMO sudo python push_button_debounces.py & 一樣的線路圖 , 不一樣的程式

Slide 148

Slide 148 text

148 但是這個程式的 CPU 用量挺大的 $ top -c 跑個按鍵偵測程式 CPU 使用率達 91.9% ( 如果使用 Pi 2 使用率約 2x%)

Slide 149

Slide 149 text

149 ● 輪詢 (polling) ● SoC 每隔一段時間檢查週邊硬體的資料 ● 中斷 (interrupt) ● 當週邊硬體的狀態改變時 , 通知 SoC 輪詢與中斷

Slide 150

Slide 150 text

150 ● 建立回呼函數 ● def callback() ● 綁定事件和回呼函數 ● add_event_detect(gpio, edge, callback=None, bouncetime=0) ● 多個事件可以綁定同樣的回呼函數 中斷的程式寫法 source/py_gpio.c

Slide 151

Slide 151 text

151 BTN_PIN = 11 GPIO.setup(BTN_PIN, GPIO.IN) def callback_function(channel): print("Button.Click...") try: GPIO.add_event_detect(BTN_PIN, GPIO.FALLING, \ callback=callback_function, bouncetime=200) while True: time.sleep(10) except KeyboardInterrupt: GPIO.cleanup() 讀取按鍵

Slide 152

Slide 152 text

152 DEMO sudo python push_button_interrupt.py 一樣的線路圖 , 不一樣的程式

Slide 153

Slide 153 text

153 BTN_PIN = 11 GPIO.setup(BTN_PIN, GPIO.IN) def callback_function(channel): with picamera.PiCamera() as camera: time.sleep(2) camera.capture('image.jpg') try: GPIO.add_event_detect(BTN_PIN, GPIO.FALLING, \ callback=callback_function, bouncetime=200) while True: time.sleep(10) except KeyboardInterrupt: GPIO.cleanup() 按鍵控制拍照

Slide 154

Slide 154 text

154 DEMO sudo python push_button_take_photo.py

Slide 155

Slide 155 text

155 這 code 好像怪怪的 是我手有問題嗎?

Slide 156

Slide 156 text

156 ● R= 電阻 , C= 電容 ● 利用電容放電維持準位 硬體方法:使用 RC 電路 http://www.eng.utah.edu/~cs5780/debouncing.pdf 按鍵還沒按下時 - 充電 按鍵按下後 - 放電

Slide 157

Slide 157 text

157 線路圖 (RC 電路 ) BUTTON RPi 腳 1 Pin6 (Ground) 腳 3 Pin11 (GPIO0) Pin1 (3.3V) Pin14 (Ground) 1k 電阻:棕黑黑棕 ( 棕 1k 電阻:棕黑黑棕 ( 棕 0.1u 電容: 104

Slide 158

Slide 158 text

158 DEMO sudo python push_button_take_photo.py 一樣的程式 , 不一樣的線路圖

Slide 159

Slide 159 text

159 實驗 6 :會認東西的 Camera 目的:串接網路服務

Slide 160

Slide 160 text

影像辨識 http://googleresearch.blogspot.tw/2014/09/building-deeper-understanding-of-images.html

Slide 161

Slide 161 text

更強大的看圖說故事 http://googleresearch.blogspot.tw/2014/11/a-picture-is-worth-thousand-coherent.html CNN : Convolutional Neural Network( 捲積式類神經網路 ) RNN : Recurrent Neural Network( 遞迴式類神經網路 )

Slide 162

Slide 162 text

影像分類服務 https://imagga.com/

Slide 163

Slide 163 text

看 DEMO http://imagga.com/auto-tagging-demo/?key=123#

Slide 164

Slide 164 text

Auto-Tagging http://imagga.com/auto-tagging-demo/?key=123#

Slide 165

Slide 165 text

1. 註冊與認證 – https://imagga.com/auth/signup 2. 取得 API Key 和 API Secret – https://imagga.com/profile/dashboard 3. 串接 – input: 命令列 / 程式 – output: JSON 字串 如何開始使用服務? http://docs.imagga.com/

Slide 166

Slide 166 text

● 驗證方式: Base64 Encode(api_key:api_secret) Base64 Encode - Online https://www.base64encode.org/ 冒號很重要 !

Slide 167

Slide 167 text

● 原型 ● $ curl --request GET \ --url 'http://api.imagga.com/v1/tagging?url=/url/to/image' \ --header 'accept: application/json' \ --header 'authorization: Basic Base64_Encode(api_key:api_secret)' ● 範例(記得將紅色部份換成自己的api_key和api_secret) ● $ curl --request GET \ --url 'http://api.imagga.com/v1/tagging?url=http%3A%2F \ %2Fplayground.imagga.com%2Fstatic%2Fimg%2Fexample_photo.jpg' \ --header 'accept: application/json' \ --header 'authorization: Basic \ YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1N TQ1MmYwNTgzMQ==' 命令列 (shell) 串接 http://docs.imagga.com/

Slide 168

Slide 168 text

● JSON(JavaScript Object Notation) 是一種資料結構 ● 物件 (object) 以 { } 表示 ● 鍵 / 值 (collection) 以 : 表示 ● 陣列 (array) 以 [ ] 表示 回傳結果 (JSON) http://docs.imagga.com/

Slide 169

Slide 169 text

● $ sudo apt-get install -y libtool automake ● $ wget http://stedolan.github.io/jq/download/source/jq- 1.4.tar.gz ● $ tar zxvf jq-1.4.tar.gz ● $ cd jq-1.4 ● $ sudo ln -s /usr/bin/automake-1.11 /usr/bin/automake- 1.14 ● $ ./configure ● $ make 在 shell 解析 JSON 字串 - jq 安裝 http://stedolan.github.io/jq/

Slide 170

Slide 170 text

{ "results": [ { "image": "http://playground.imagga.com/static/img/example_photo.jpg", "tags": [ { "confidence": 100, "tag": "shore" }, ● 取出results : json | ./jq '.results' ● 取出tags : json | ./jq '.results[0].tags' ● 取出第一個tag : json | ./jq '.results[0].tags[0].tag' 在 shell 解析 JSON 字串 - jq 使用 http://stedolan.github.io/jq/

Slide 171

Slide 171 text

171 DEMO

Slide 172

Slide 172 text

import requests url = "http://api.imagga.com/v1/tagging" querystring = {"url":"http://playground.imagga.com/static/img/example_photo.jpg"} headers = { 'accept': "application/json", 'authorization': "Basic YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1 NTQ1MmYwNTgzMQ==" } response = requests.request("GET", url, headers=headers, params=querystring) print(response.text) Python 程式串接 (File URL) - 記得將紅色部份換成自己的 api_key 和 api_secret http://docs.imagga.com/

Slide 173

Slide 173 text

import requests import json ● url = "http://api.imagga.com/v1/tagging" querystring = {"url":"http://playground.imagga.com/static/img/example_photo.jpg"} headers = { 'accept': "application/json", 'authorization': "Basic YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1NTQ1 MmYwNTgzMQ==" } response = requests.request("GET", url, headers=headers, params=querystring) data = json.loads(response.text.encode("ascii")) ● print(data["results"][0]["tags"][0]["tag"].encode("ascii")) 加上解析 JSON - 記得將紅色部份換成自己的 api_key 和 api_secret

Slide 174

Slide 174 text

174 DEMO python imagga_tag_file_url.py

Slide 175

Slide 175 text

● 根據文件得知需要兩個步驟 ● 上傳檔案後取得檔案 uid ● 將 uid 以參數方式送出查詢 Python 程式串接 (Upload File) http://docs.imagga.com/

Slide 176

Slide 176 text

import requests import json ● url = “http://api.imagga.com/v1/content” files = {“file”: open(“/home/pi/file.png”, “rb”)} headers = { 'accept': "application/json", 'authorization': "Basic YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1NTQ1M mYwNTgzMQ==" } response = requests.post(url, files=files, headers=headers) print(response.text) ● data = json.loads(response.text.encode("ascii")) ● print(data["uploaded"][0]["id"]) 上傳檔案取得檔案 uid - 記得將紅色部份換成自己的 api_key 和 api_secret

Slide 177

Slide 177 text

# … 接前頁 ● url = "http://api.imagga.com/v1/tagging" querystring = {"content":data["uploaded"][0]["id"]} response = requests.request("GET", url, headers=headers, params=querystring) data = json.loads(response.text.encode("ascii")) print(data["results"][0]["tags"][0]["tag"].encode("ascii")) ● 將 uid 以參數方式送出查詢

Slide 178

Slide 178 text

178 DEMO python imagga_tag_upload_file.py

Slide 179

Slide 179 text

● Ivan 說 , 短邊 300px 傳輸最快 ● $ sudo apt-get install imagemagick ● $ convert b.jpg -resize widthxheight a.jpg ● $ convert b.jpg -resize widthxheight! a.jpg // 強制 ● 除了印出結果 , 還可以讓 Pi 發聲 ● $ sudo apt-get install festival ● $ echo tag | festival --tts 小技巧 & 延伸功能 由 imagga 回傳的 tag

Slide 180

Slide 180 text

180 DEMO python imagga_tag_upload_and_speak.py

Slide 181

Slide 181 text

181 實驗 7 :人臉偵測 目的:對 Camera 影像做處理

Slide 182

Slide 182 text

● 跨平台的計算機函式庫 , 主要由 C/C++ 撰寫 OpenCV - Open Source Computer Vision Library http://www.embedded-vision.com/technology/computer-vision-algorithms

Slide 183

Slide 183 text

OpenCV 的架構 http://www.cse.iitk.ac.in/users/vision/dipakmj/papers/OReilly%20Learning%20OpenCV.pdf

Slide 184

Slide 184 text

import cv2 ● import sys ● imagePath = sys.argv[1] image = cv2.imread(imagePath) ● ● cv2.imshow("preview", image) cv2.waitKey(0) cv2.destroyAllWindows() ● 載入圖檔並顯示

Slide 185

Slide 185 text

185 DEMO python image_load.py abba.png

Slide 186

Slide 186 text

import cv2 cap = cv2.VideoCapture(0) cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320) cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240) while True: ret, frame = cap.read() cv2.imshow(“preview”, frame) if cv2.waitKey(1) & 0xFF == ord(“q”): break cap.release() cv2.destroyAllWindows() 讀取 Camera 並顯示

Slide 187

Slide 187 text

187 DEMO python camera_preview.py 使用前記得要先載入模組 $ sudo modprobe bcm2835-v4l2

Slide 188

Slide 188 text

● 由 Viola & Jones 提出,並由 Lienhart & Maydt 改善 ● 監督式學習 ● 特徵比對 (Haar features) ● 積分影像計算 (Integral Image) ● 學習機制 (AdaBoost) ● 串接分類器 (Cascade) Face Detection - Haar Classifiers http://www.open-electronics.org/raspberry-pi-and-the-camera-pi-module-face-recognition-tutorial/

Slide 189

Slide 189 text

● Haar-like features ● A "cascade" is a series of "Haar-like features" that are combined to form a classifier Haar-Like Features & Haar Cascade https://www.youtube.com/watch?v=sWTvK72-SPU

Slide 190

Slide 190 text

● Pick a scale (ex: 24x24 pixels) for the feature ● Slide it across the image ● Compute the average pixel values under the white area and the black area ● If the difference between the areas is above some threshold, the feature matches 特徵比對 https://www.youtube.com/watch?v=sWTvK72-SPU

Slide 191

Slide 191 text

● A "summed area table" is created in a single pass across the image ● The sum of any region in the image can be computed by a single formula 積分影像計算 https://www.youtube.com/watch?v=sWTvK72-SPU

Slide 192

Slide 192 text

● Adaptive Boosting ● Adaboost tries out multiple weak classifiers over several rounds, selecting the best weak classifier in each round and combining the best weak classifiers to create a strong classifier AdaBoost https://www.youtube.com/watch?v=sWTvK72-SPU

Slide 193

Slide 193 text

● A single classifier isn't accurate enough ● It's called a "weak classifier" ● Haar cascades consists of a series of weak classifiers - those barely better than 50% correct ● If an area passes a single classifier, go to the next classifier; otherwise, area doesn't match 串接分類器 https://www.youtube.com/watch?v=sWTvK72-SPU

Slide 194

Slide 194 text

faceCascade = cv2.CascadeClassifier(sys.argv[2]) ● image = cv2.imread(sys.argv[1]) ● gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ● ● faces = faceCascade.detectMultiScale( ● gray, ● scaleFactor=1.1, ● minNeighbors=5, ● minSize=(30, 30), ● flags = cv2.cv.CV_HAAR_SCALE_IMAGE ● ) ● for (x, y, w, h) in faces: ● cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2) 載入圖檔並辨識 https://sites.google.com/site/5kk73gpu2012/assignment/viola-jones-face-detection

Slide 195

Slide 195 text

195 DEMO python image_face_detect.py abba.png haarcascade_frontalface_default.xml

Slide 196

Slide 196 text

No content

Slide 197

Slide 197 text

● 搜索視窗 vs. 檢測視窗 ● 搜索視窗在整個影像中移動 , 檢測視窗在搜索視 窗中移動並計算特徵值 ● scaleFactor: 搜索視窗成長比率 ● minNeighbors: 檢測區域鄰域內最少包含的檢測出 的備選人臉區域 ( 次數 ) ● minSize: 檢測視窗的最小尺寸 可調整的參數

Slide 198

Slide 198 text

scaleFactor - minNeighbors=5, minSize=(30, 30) scaleFactor=1.1 1.2 1.3 1.4 1.5 1.6

Slide 199

Slide 199 text

minNeighbors - scaleFactor=1.1, minSize=(30, 30) minNeighbors=1 2 3 5 10 20

Slide 200

Slide 200 text

minSize(x, y) - scaleFactor=1.1, minNeighbosr=5 minSize=(15, 15) (30, 30) (60, 60) (90, 90) (120 ,120) (150, 150)

Slide 201

Slide 201 text

faceCascade = cv2.CascadeClassifier(sys.argv[1]) cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv2.cv.CV_HAAR_SCALE_IMAGE ● ) ● for (x, y, w, h) in faces: cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) 讀取 Camera 並辨識

Slide 202

Slide 202 text

202 DEMO python camera_face_detect.py haarcascade_frontalface_default.xml

Slide 203

Slide 203 text

203 實驗 8 : HTTP Video Streaming 目的:瞭解 Web Server 如何做 streaming

Slide 204

Slide 204 text

● 原理 ● 向 Web Server 請求一個很大的檔案 ● 該檔案是一個即時的資料 使用 HTTP 做 Video Streaming

Slide 205

Slide 205 text

● 一個軟體 ● 回應從 80/8080 port 進來的 HTTP 要求 ● 可透過 CGI 或 module 方式擴充 ● 如 Apache, Nginx, Boa 網頁伺服器 (Web Server) http://www.resultantsys.com/index.php/general/what-is-a-web-application-server/

Slide 206

Slide 206 text

206 Flask - A Python Microframework

Slide 207

Slide 207 text

$ vi app-hello.py from flask import Flask app = Flask(__name__) @app.route("/") def index(): return "Hello Flask" if __name__ == "__main__": app.run(host='0.0.0.0', port=80, debug=True) Hello Flask

Slide 208

Slide 208 text

$ sudo python app-hello.py * Running on http://0.0.0.0:80/ (Press CTRL+C to quit) * Restarting with stat 192.168.11.2 - - [29/May/2015 15:37:31] "GET / HTTP/1.1" 200 - 192.168.11.2 - - [29/May/2015 15:37:31] "GET /favicon.ico HTTP/1.1" 404 - 執行

Slide 209

Slide 209 text

209 DEMO sudo python app-hello.py

Slide 210

Slide 210 text

from flask import Flask, render_template ● ● app = Flask(__name__) @app.route("/") def index(): return render_template('link.html') ● @app.route("/foo") ● def foo(): ● extns = ['Flask', 'Jinja2', 'Awesome'] ● return render_template('bar.html', extns=extns) if __name__ == "__main__": app.run(host='0.0.0.0', port=80, debug=True) 新增一個 route & template

Slide 211

Slide 211 text

$ mkdir templates $ vi templates/link.html

Hello Template

foo $ vi templates/bar.html
    {% for ext in extns %}
  • {{ ext }}
  • {% endfor %}
建立 template

Slide 212

Slide 212 text

$ sudo python app-route.py 執行

Slide 213

Slide 213 text

213 DEMO sudo python app-route.py

Slide 214

Slide 214 text

from camera import Camera ● from flask import Flask, render_template, Response ● app = Flask(__name__) ● ● @app.route("/") ● def index(): ● return render_template('index.html') ● ● def gen(camera): ● while True: ● frame = camera.get_frame() ● yield (b'--frame\r\n' ● b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n') ● ● @app.route('/video_feed') ● def video_feed(): ● return Response(gen(Camera()), ● mimetype='multipart/x-mixed-replace; boundary=frame') Streaming 圖片

Slide 215

Slide 215 text

$ vi stream_pi.py from time import time class Camera(object): def __init__(self): self.frames = [open(f + '.jpg', 'rb').read() for f in ['1', '2', '3']] def get_frame(self): return self.frames[int(time()) % 3] 建立 Camera 類別

Slide 216

Slide 216 text

$ vi templates/stream.html

Hello Stream

● 補個圖 1.jpg, 2.jpg, 3.jpg 修改 template

Slide 217

Slide 217 text

$ sudo python app-stream.py 執行

Slide 218

Slide 218 text

218 DEMO sudo python app-stream.py

Slide 219

Slide 219 text

● MJPEG = Motion JPEG ● 一種視訊壓縮格式 ● 每一個 frame 都使用 JPEG 編碼 ● 對運算能力與記憶體的需求較低 HTTP + MJPEG

Slide 220

Slide 220 text

$ vi camera_pi.py import cv2 class Camera(object): def __init__(self): self.video = cv2.VideoCapture(0) def __del__(self): self.video.release() def get_frame(self): success, image = self.video.read() ret, jpeg = cv2.imencode('.jpg', image) ● return jpeg.tostring() 從 Camera 讀取影像

Slide 221

Slide 221 text

221 DEMO sudo python app-camera.py

Slide 222

Slide 222 text

222 加上 OpenCV 功能做撒尿牛丸吧

Slide 223

Slide 223 text

class Camera(object): ● def __init__(self): ● self.video = cv2.VideoCapture(0) ● self.video.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320) ● self.video.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240) ● ● def get_frame(self): ● success, frame = self.video.read() ● gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) ● faces = faceCascade.detectMultiScale( ● gray, ● scaleFactor=1.1, ● minNeighbors=5, ● minSize=(30, 30), ● flags=cv2.cv.CV_HAAR_SCALE_IMAGE ● ) ● for (x, y, w, h) in faces: ● cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) ● ret, jpeg = cv2.imencode('.jpg', frame) ● return np.array(jpeg).tostring() Camera + OpenCV + HTTP Streaming $ vi camera_pi.py

Slide 224

Slide 224 text

224 DEMO sudo python app-opencv.py

Slide 225

Slide 225 text

Raspberry Pi Rocks the World Thanks

Slide 226

Slide 226 text

226 請幫忙填問卷 http://goo.gl/forms/4gzeuVdrWL

Slide 227

Slide 227 text

227 ● WiFi 連不上怎麼辦 ? ● 接螢幕用 GUI 設定吧 ● WiFi Config 的 Adapter 不見了怎麼辦 ? ● 將 /etc/network/interface 和 /etc/wpa_supplicant/wpa_supplicant.conf 回復成預設值 常見問與答

Slide 228

Slide 228 text

228 $ cat /etc/network/interfaces auto lo iface lo inet loopback iface eth0 inet dhcp auto wlan0 iface wlan0 inet manual wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf iface default inet dhcp $ cat /etc/wpa_supplicant/wpa_supplicant.conf ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 兩個檔案的預設值