Raspberry Pi Camera + Python
台灣樹莓派 <[email protected]>May 31, 2015 / PyCon APAC 2015
2
3
●投影片下載●http://goo.gl/mLdZ18
●範例下載●https://goo.gl/1JdAT5
●Hackpad 小抄●https://goo.gl/U9zhEO
姓名標示 — 非商業性 — 相同方式分享
CC (Creative Commons)
姓名標示 — 你必須給予 適當表彰、提供指向本授權條款的連結,以及 指出(本作品的原始版本)是否已被變更。你可以任何合理方式為前述表彰,但不得以任何方式暗示授權人為你或你的使用方式背書。
非商業性 — 你不得將本素材進行商業目的之使用。
相同方式分享 — 若你重混、轉換本素材,或依本素材建立新素材,你必須依本素材的授權條款來散布你的貢獻物。
5
● Element14 指定台灣地區 Raspberry Pi 獨家經銷商
about 台灣樹莓派
http://farnell.com/raspberrypi-consumer/approved-retailers.php?region=apac&MER=MER-LM-OB-RPICC-76315
● 專注於 Raspberry Pi 應用與推廣
● 舉辦社群聚會 / 工作坊 / 讀書會 / 黑客松
● Website :● https://www.raspberrypi.com.tw/
● Facebook : ● 搜尋 RaspberryPi.Taiwan● https://www.facebook.com/RaspberryPi.Taiwan
about 台灣樹莓派
7
● COSCUP, MakerConf, PyCon 講者
● 投影片
● http://www.slideshare.net/raspberrypi-tw/presentations● 程式碼
● https://github.com/raspberrypi-tw
分享 x 社群
● Raspberry Pi Camera 簡介
● 基礎 Camera 使用
● 寫程式控制
今天會講
沒有螢幕與鍵盤如何使用樹莓派?
10
環境設定: Serial + WiFi
1. 樹莓派 Serial 連線
2. 樹莓派 WiFi 連線
用 Serial 來設定 WiFi
3. 筆電、手機、樹莓派 在同一個 LAN
11
● 以 USB 轉 TTL 傳輸線和 Pi 相連
● 接線方式● 黑色: Pin 6 (GND)● 白色: Pin 8 (Tx)● 綠色: Pin 10 (Rx)● 紅色:不接
Serial 連線方式
12
Raspberry Pi B 的 GPIO (P1)
黑色線接 6 號 ( 第三根 )
白色線接 8 號 ( 第四根 )
綠色線接 10 號 ( 第五根 )
http://elinux.org/RPi_Low-level_peripherals
13
Raspberry Pi B+ 的 GPIO (P1)
黑色線接 6 號 ( 第三根 )
白色線接 8 號 ( 第四根 )
綠色線接 10 號 ( 第五根 )
http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/
14
● 安裝驅動程式 , http://goo.gl/QC5Q3O
● 從裝置管理員找到 COM 的埠號 ( 本例為 COM9)● 下載 putty, http://goo.gl/zdD9G9
● 執行 putty● Session● Serial line 填 COM9● Speed 填入 115200● Open !
● 沒畫面 , 重新插拔電源
Serial Port in Windows
15
● $ ls /dev/ttyUSB*
● 開啟 putty● 選擇 Session● 在 Serial line 填入 /dev/ttyUSB0 ( 本例為 ttyUSB0)● Speed 填入 115200● Open !
● 無法連線時 , 使用 sudo 執行 putty
Serial Port in Linux
16
● 安裝驅動程式 , http://goo.gl/htlt3F● 重開機生效● $ ls /dev/cu*
● 如果有 /dev/cu.usbserial● $ screen /dev/cu.usbserial 115200
● 如果沒畫面,重新插拔電源
Serial Port in Mac
17
● 預設帳號 / 密碼: pi / raspberry● 如果沒有畫面,將電源重新插拔● 如果出現亂碼,確定 baud rate 為 115200
連線成功
18
● 登入畫面
● pi 是登入的使用者
● @ 表示”在”● raspberrypi 是主機名稱
● ~ 表示在家目錄 (home directory)● $ 表示該使用者所使用的 shell( 一種文字工具介面 )● 例如 $ nano myfile.txt
● 表示用 nano 編輯器開 myfile.txt 檔案
符號說明
19
使用: nano
離開: Ctrl + x
> 令存新檔: y
> 不存離開: n
> 離開: Ctrl + c
nano 編輯器使用
20
$ 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/
在文字模式下設定無線網路
21
$ 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 - 連線
22
$ ifconfig wlan0
IP = 192.168.43.102
連線成功 查詢 IP
23
● 預設帳號 / 密碼: pi / raspberry
有了 IP, 用 SSH 連線
24
● 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( 今天不需設定 )
● $ 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
安裝今日所需軟體
Raspberry Pi Camera 簡介
從手機相機模組講起
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( 影像訊號處理器 )
● 問:樹葉為什麼看起來是綠色的?● 答:因為樹葉吸收了大部分可見光,只反射綠色光
基礎光學原理
https://www.raspberrypi.org/learning/infrared-bird-box/worksheet/
Type of Raspberry Pi Camera
http://elinux.org/Rpi_Camera_Module
Raspberry Pi Camera Module NoIR Camera Module
● 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
技術規格
Raspberry Pi Camera Module
https://www.modmypi.com
15-Pins, CSI 介面
綠色 PCB板
● No IR = No 'IR cut filter' installed● 因此CMOS 可吸收到不可見光 (Infrared)● No IR 相機 ≠ 夜視相機
● 除非有額外的紅外線發光源
No IR Camera
黑色PCB板
兩種相機效果比較
http://www.themagpi.com/issue/issue-18/
1. 非NoIR相機 2. NoIR 相機
3. NoIR 相機 4. NoIR 相機+藍色濾光片
Raspberry Pi Camera 應用簡介
移動偵測攝影
http://www.codeproject.com/Articles/665518/Raspberry-Pi-as-low-cost-HD-surveillance-camera
IP Camera以樂高做外殼
加上Camera 與按鍵
37
雲端相機
http://learn.adafruit.com/diy-wifi-raspberry-pi-touch-cam
可做影像辨識的相機
5
人臉辨識與追蹤
https://github.com/tasanakorn/rpi-mmal-demo/tree/develop
脈博辨識
https://github.com/thearn/webcam-pulse-detector
3D 建模計算深度 /2 Cameras
http://www.raspberrypi.org/real-time-depth-perception-with-the-compute-module/
360度照片
https://vimeo.com/77218985
效果
3D掃描 /50 Cameras
http://www.pi3dscan.com/
效果 + Autodesk Recap
http://www.pi3dscan.com/
Camera改裝套件
固定的機構
http://www.modmypi.com/
鏡頭改裝
http://www.modmypi.com/
惡改鏡頭
http://www.truetex.com/raspberrypi
外殼改裝
http://www.modmypi.com/http://blog.pi3g.com/2013/11/coming-soon-raspberry-with-case-mounted-camera/
Camera 安裝
安裝 Raspberry Pi Camera
http://goo.gl/7LqyMY
$ sudo raspi-config
啟用 Raspberry Pi Camera
進階選項
設定記憶體分配 >128M
實戰Camera 使用
使用 Camera 前先消除靜電吧
http://www.wikihow.com/Remove-Static-Electricity
58
實驗 1 :Hello Camera
目的:練習照相和攝影的指令
● 只預覽 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
常見Camera問題?
● 錯誤訊息: Camera is not enabled in this build
● 解法:進 raspi-config 重新 enable camera● $ sudo raspi-config
● 錯誤訊息: Camera is not detected
● 解法:重新安裝 camera, 或是更換排線
或是檢查 camera module 是否鬆脫
https://www.modmypi.com/blog/how-to-replace-the-raspberry-pi-camera-cable
● 錄 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
$ 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
65
DEMO./camera_effect.sh
66
$ git clone https://github.com/raspberrypi-tw/camera-python.git
$ cd camera-python
$ cd 01_hello_camera
$ ./camera_effect.sh
需要接上螢幕才能看到效果
執行方式
更多參數或用法請看文件
http://goo.gl/VhyBaL
https://www.raspberrypi.org/wp-content/uploads/2013/07/RaspiCam-Documentation.pdf
如何看照片和影片?
69
● 是一種圖形應用標準● Client/Server架構
● X Client : 應用程式● X Server : 管理硬體輸入 / 輸出
● 可透過網路傳輸● TCP/IP 或是 Unix Domain Socket
● X11 是通訊協定名稱
X Window System
http://keyj.emphy.de/files/linuxgraphics_en.pdf
70
● 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
● 看照片
● $ 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 連線成功後
● 第一步:編輯 /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
嫌慢的話直接用網路線對接
https://pihw.wordpress.com/guides/direct-network-connection/
● 在 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
網路設定
75
實驗 2 :縮時攝影
目的:簡單合成影片做特效
縮時攝影 (Time-Lapse Photography)
http://en.wikipedia.org/wiki/Time-lapse_photography
● 每間隔一段時間拍一張● 再將所有的照片接在一起● 調整播放速度 x = x倍速的視覺效果
概念
http://en.wikipedia.org/wiki/Time-lapse_photography
● 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/
79
DEMO./time_lapse.sh
vlc timelapse.avi
80
$ cd ../02_time_lapse
$ ./time_lapse.sh
執行完畢後會多一個 timelapse.avi 檔案 , 使用 VLC觀看
$ vlc timelapse.avi
執行方式
81
實驗 3 :用手機 App 控制
目的:沒有螢幕也可以玩 camera
RaspiCam Remote @ Android
連線 & 錄影
調整效果:亮度
85
實驗4:網路串流
目的:用播放器看結果
Streaming Media技術架構
http://www.consilient-tech.com/strmmeda.shtml
RTSP通訊協定
RTSP Client
RTSP Server
RTSP (TCP) : initiate
RTP (UDP) : content
RTCP (UDP) : control
● 在 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
Live Media Player @ iPhone
開啟 RTSP串流
91
DEMO./rtsp_stream.sh
要配合電腦或手機觀看
● 在 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=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,dst=:8080/video.mjpg}'}
● 開啟 Browser● http://raspberrypi 的 ip:8080/video.mjpg
HTTP + MJPEG
https://goo.gl/U9zhEO
v4l2:///dev/video0這是什麼東西?
- 非官方的 V4L2 Driver
回來看 camera
你有用過webcam嗎?
95
Webcam
http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals
● 預定義好的 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/video0Driver
Hardware
App1 (fd1) App2 (fd2)
ioctl() ioctl()
read()write()
Identifying App1and App2 bydifferent filedescriptors, thedriver can sendthem different data.
Camera ≠ Webcam
98
Modern Device Internal
http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals
99
Image Processing Pipeline
http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals
100
Image Processing Pipeline
http://www.slideshare.net/gxben/abs-2014-android-kit-kat-internals
ISP 在做的事 (HW)
color space/format 轉換 (SW)
101
http://elinux.org/Raspberry_Pi_VideoCore_APIs
102
● 開放多媒體加速層 (Open Media Acceleration)● 由Khronos Group 提出的標準● 統一的介面,加速大量多媒體資料的處理
OpenMAX
https://www.khronos.org/openmax/
103
Multimedia Stack Example
http://wiki.maemo.org/Documentation/Maemo_5_Developer_Guide/Architecture/Multimedia_Domain
104
● 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
105
● 安裝
● $ 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
106
● 參考這幾隻程式吧
● raspicam● https://github.com/raspberrypi/userland/tree/master/host_ap
plications/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
107
實驗5:寫程式控制 Camera
目的:自己的 Camera自己做
使用 picamera (Python library)
109
● 變數 , 物件 , 型別 , 註解● 模組● 縮排● 迴圈● 條件判斷● 函式● 例外處理● with as
Python 五分鐘速成
110
● 動態型別 (dynamic typing)
# 這是註解
i = 3 # 變數 i 指到數字物件 3
i = [1, 2, 3, 4, 5] # 變數 i 指到串列物件
print(i[2]) # 印出串列中第三個元素
i = “abcde” # 變數 i 指到字串物件
print(i[2]) # 印出字串中第三個元素
變數 , 物件 , 型別 , 註解
111
# 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
112
● 用縮排取代大括號● 程式碼的區塊是用縮排分隔● 不使用 tab, 使用空白鍵
● 常見縮排為 4 個空白鍵
縮排
113
● 自動迭代 (iterator)
for TARGET in LIST :
# aaa
● # bbb
# ccc
# nameS = ["paul", "mary", "tom", "rita"]
# for name in nameS :
# print name
迴圈
114
if CONDITION_1 :
PROCESS_1
elif CONDITION_2 :
PROCESS_2
else :
PROCESS_3
● # grade = 60
# if grade > 60 :
# print "great"
# else :
# print "too bad"
條件判斷
115
def FUNCTION() :
PROCESS
def FUNCTION( PARAM ) :
PROCESS
def FUNCTION( PARAM = 3) :
PROCESS
# def my_function(input = 5) :
# print (input)
函式
116
● 程式何時會結束 ?● 在正常情況下執行完畢結束● 遇到錯誤跳出
● 受到中斷停止 (收到終止訊號 , 例如 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
117
● 使用 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
#!/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
119
DEMOpython picamera_take_photo.py
執行方式$ cd ../05_picamera
$ python picamera_take_photo.py
120
● 使用 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/
#!/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
#!/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
123
DEMOpython picamera_record_video.pypython picamera_more.py
加上一個按鍵吧
125
● 開關:按鍵式 , 滑動式 , 傾斜式 ...● 常開 (normal open, N.O.)● 常閉 (normal close, N.C.)
按鍵 Button / 開關 Switch
http://nicegear.co.nz/
126
● 開關:按鍵式 , 滑動式 , 傾斜式 ...● 常開 (normal open, N.O.)● 常閉 (normal close, N.C.)
按鍵 Button / 開關 Switch
127
按鍵的內部結構
● 按下前● 長邊相連 (1&2, ¾3&4)● 短邊不相連
● 按下後● 四點都通
128
要接哪一個腳位?
129
● 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
130
Model B vs. B+
http://elinux.org/RPi_Low-level_peripheralshttp://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/
131
Raspberry Pi Model B 的 GPIO (P1)
http://elinux.org/RPi_Low-level_peripherals
SPI / I2C / UART / PWM
Pin1 Pin2
Pin25 Pin26
132
● 決定是輸入還是輸出● 寫值到某根腳位● 從某根腳位讀值● 決定是前緣觸發還是後緣觸發● 等待中斷 (interrupt) 的發生
GPIO 是硬體的事 , 那軟體做什麼 ?
133● 6 、 9 、 14 、 20等腳位為接地,可互相交換
GPIO腳位意義對照表
http://wiringpi.com/wp-content/uploads/2013/03/pins.pdf
134
簡單的按鍵接法
BUTTON RPi腳 1 Pin6 (Ground)腳 3 Pin11 (GPIO0)
135
● Input空接會讀到雜訊
問題在哪裡?
BUTTON RPi腳 1 Pin6 (Ground)腳 3 Pin11 (GPIO0)
136
麵包板的種類
https://goo.gl/JipVgH
137
麵包板的使用
http://bugworkshop.blogspot.tw/2012/12/diy-breadboard.html
1. 藍色和綠色兩塊不通2. 藍色垂直相通3. 紅色水平相通 麵包板的內部結構
138
更好的按鍵接法
http://geekgurldiaries.blogspot.tw/2012/12/part-2.html
139
上拉電阻 / 下拉電阻-兩種電路的接法
http://playground.arduino.cc/CommonTopics/PullUpDownResistor
140
上拉電阻 / 下拉電阻-還沒按下按鍵時
http://playground.arduino.cc/CommonTopics/PullUpDownResistor
141
上拉電阻 / 下拉電阻-按下按鍵以後
http://playground.arduino.cc/CommonTopics/PullUpDownResistor
142
線路圖 (上拉電阻 )BUTTON RPi腳 1 Pin6 (Ground)腳 3 Pin11 (GPIO0) Pin1 (3.3V)
1K電阻
2K電阻
143
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()
按下按鍵的判斷條件 (上拉電阻 )
144
DEMOsudo python push_button_poll.py
讀寫 GPIO 會存取 /dev/mem, 需 root 權限sudo 表示暫時切換身份到其他使用者 (root)
145
● 機械式開關在切換過程中會有訊號彈跳現象 (雜訊 )
開關訊號的彈跳問題 (bounce)
http://120.101.72.1/Onechip/PPT/實習單元三 .ppt
理想訊號輸出
實際輸出訊號
146
● 硬體方法:以 RC 電路或正回授的比較器電路解決
● 軟體方法:調整觸發的延遲時間● 不同的按鍵會有不同的延遲時間
解決彈跳問題 (de-bounce)
10ms - 20ms
147
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()
軟體方法:不反應在延遲時間內的觸發
148
DEMOsudo python push_button_debounces.py &
一樣的線路圖 , 不一樣的程式
149
但是這個程式的 CPU 用量挺大的$ top -c
跑個按鍵偵測程式 CPU 使用率達 91.9% ( 如果使用 Pi 2 使用率約 2x%)
150
● 輪詢 (polling)● SoC每隔一段時間檢查週邊硬體的資料
● 中斷 (interrupt)● 當週邊硬體的狀態改變時 , 通知 SoC
輪詢與中斷
151
● 建立回呼函數● def callback()
● 綁定事件和回呼函數● add_event_detect(gpio,
edge,
callback=None,
bouncetime=0)● 多個事件可以綁定同樣的回呼函數
中斷的程式寫法
source/py_gpio.c
152
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()
讀取按鍵
153
DEMOsudo python push_button_interrupt.py
一樣的線路圖 , 不一樣的程式
154
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()
按鍵控制拍照
155
DEMOsudo python push_button_take_photo.py
156
這 code好像怪怪的
是我手有問題嗎?
157
● R= 電阻 , C= 電容
● 利用電容放電維持準位
硬體方法:使用 RC 電路
http://www.eng.utah.edu/~cs5780/debouncing.pdf
按鍵還沒按下時 -充電 按鍵按下後 -放電
158
線路圖 (RC 電路 )BUTTON RPi腳 1 Pin6 (Ground)腳 3 Pin11 (GPIO0) Pin1 (3.3V) Pin14 (Ground)
1k 電阻:棕黑黑棕 (棕
1k 電阻:棕黑黑棕 (棕
0.1u電容: 104
159
DEMOsudo python push_button_take_photo.py
一樣的程式 , 不一樣的線路圖
160
實驗 6 :會認東西的 Camera
目的:串接網路服務
影像辨識
http://googleresearch.blogspot.tw/2014/09/building-deeper-understanding-of-images.html
更強大的看圖說故事
http://googleresearch.blogspot.tw/2014/11/a-picture-is-worth-thousand-coherent.html
CNN : Convolutional Neural Network(捲積式類神經網路 )RNN : Recurrent Neural Network(遞迴式類神經網路 )
影像分類服務
https://imagga.com/
看DEMO
http://imagga.com/auto-tagging-demo/?key=123#
Auto-Tagging
http://imagga.com/auto-tagging-demo/?key=123#
1. 註冊與認證
– https://imagga.com/auth/signup
2. 取得 API Key 和 API Secret
– https://imagga.com/profile/dashboard
3. 串接
– input: 命令列 / 程式
– output: JSON 字串
如何開始使用服務?
http://docs.imagga.com/
● 驗證方式: Base64 Encode(api_key:api_secret)
Base64 Encode - Online
https://www.base64encode.org/
冒號很重要 !
● 原型
● $ 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 \ YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1NTQ1MmYwNTgzMQ=='
命令列 (shell)串接
http://docs.imagga.com/
● JSON(JavaScript Object Notation) 是一種資料結構
● 物件 (object) 以 { } 表示
● 鍵 /值 (collection) 以 : 表示
● 陣列 (array) 以 [ ] 表示
回傳結果 (JSON)
http://docs.imagga.com/
● $ 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/
{
"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/
172
DEMO
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 YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1NTQ1MmYwNTgzMQ=="
}
response = requests.request("GET", url, headers=headers, params=querystring)
print(response.text)
Python 程式串接 (File URL)- 記得將紅色部份換成自己的 api_key 和 api_secret
http://docs.imagga.com/
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 YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1NTQ1MmYwNTgzMQ=="
}
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
175
DEMOpython imagga_tag_file_url.py
● 根據文件得知需要兩個步驟● 上傳檔案後取得檔案 uid● 將 uid 以參數方式送出查詢
Python 程式串接 (Upload File)
http://docs.imagga.com/
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 YWNjXzJkYzdkNzNjMmYwODliMToxYzQ3Yzg2ZDg0YjdmYjdjYjZjNzQ1NTQ1MmYwNTgzMQ=="
}
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
# … 接前頁
● 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 以參數方式送出查詢
179
DEMOpython imagga_tag_upload_file.py
● 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
181
DEMOpython imagga_tag_upload_and_speak.py
182
實驗 7:人臉偵測
目的:對Camera 影像做處理
● 跨平台的計算機函式庫 , 主要由C/C++撰寫
OpenCV- Open Source Computer Vision Library
http://www.embedded-vision.com/technology/computer-vision-algorithms
OpenCV 的架構
http://www.cse.iitk.ac.in/users/vision/dipakmj/papers/OReilly%20Learning%20OpenCV.pdf
import cv2
● import sys
●
imagePath = sys.argv[1]
image = cv2.imread(imagePath)
●
● cv2.imshow("preview", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
●
●
●
載入圖檔並顯示
186
DEMOpython image_load.py abba.png
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並顯示
188
DEMOpython camera_preview.py
使用前記得要先載入模組$ sudo modprobe bcm2835-v4l2
● 由 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/
● 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
● 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
● 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
● 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
● 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
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
196
DEMOpython image_face_detect.py abba.png haarcascade_frontalface_default.xml
● 搜索視窗 vs. 檢測視窗● 搜索視窗在整個影像中移動 , 檢測視窗在搜索視窗中移動並計算特徵值
● scaleFactor: 搜索視窗成長比率
● minNeighbors: 檢測區域鄰域內最少包含的檢測出的備選人臉區域 (次數 )
● minSize: 檢測視窗的最小尺寸
可調整的參數
scaleFactor- minNeighbors=5, minSize=(30, 30)
scaleFactor=1.1 1.2 1.3
1.4 1.5 1.6
minNeighbors- scaleFactor=1.1, minSize=(30, 30)
minNeighbors=1 2 3
5 10 20
minSize(x, y)- scaleFactor=1.1, minNeighbosr=5
minSize=(15, 15) (30, 30) (60, 60)
(90, 90) (120 ,120) (150, 150)
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並辨識
203
DEMOpython camera_face_detect.py
haarcascade_frontalface_default.xml
204
實驗 8 : HTTP Video Streaming
目的:瞭解Web Server 如何做 streaming
● 原理● 向 Web Server 請求一個很大的檔案● 該檔案是一個即時的資料
使用 HTTP做 Video Streaming
● 一個軟體● 回應從 80/8080 port 進來的 HTTP要求● 可透過CGI 或 module 方式擴充
● 如 Apache, Nginx, Boa
網頁伺服器 (Web Server)
http://www.resultantsys.com/index.php/general/what-is-a-web-application-server/
207
Flask- A Python Microframework
$ 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
$ 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 -
執行
210
DEMOsudo python app-hello.py
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
$ mkdir templates
$ vi templates/link.html
<h1>Hello Template</h1>
<a href="{{ url_for('foo') }}">foo</a>
$ vi templates/bar.html
<ul>
{% for ext in extns %}
<li>{{ ext }}</li>
{% endfor %}
</ul>
建立 template
$ sudo python app-route.py
執行
214
DEMOsudo python app-route.py
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圖片
$ 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類別
$ vi templates/stream.html
<h1>Hello Stream</h1>
<img id="bg" src="{{ url_for('video_feed') }}">
● 補個圖 1.jpg, 2.jpg, 3.jpg
修改 template
$ sudo python app-stream.py
執行
219
DEMOsudo python app-stream.py
● MJPEG = Motion JPEG● 一種視訊壓縮格式● 每一個 frame都使用 JPEG 編碼● 對運算能力與記憶體的需求較低
HTTP + MJPEG
$ 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 讀取影像
222
DEMOsudo python app-camera.py
223
加上OpenCV 功能做撒尿牛丸吧
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
225
DEMOsudo python app-opencv.py
Raspberry Pi Rocks the World
Thanks
227
請幫忙填問卷http://goo.gl/forms/4gzeuVdrWL
228
● WiFi 連不上怎麼辦 ?
● 接螢幕用 GUI 設定吧
● WiFi Config 的 Adapter 不見了怎麼辦 ?
● 將 /etc/network/interface和 /etc/wpa_supplicant/wpa_supplicant.conf回復成預設值
常見問與答
229
$ 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
兩個檔案的預設值