### ch07 程式碼下載 ### $ cd ~/Lab $ wget https://max543.com/debugger/class/python02/PiCamera/Lab/code/ch07.zip $ unzip ch07.zip ### ex7-1 ### # 啟動 RTSP Server $ raspivid -o - -t 0 -hf --rotation 180 -w 320 -h 240 -fps 15 | cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554}' :demux=h264 # 找出佔用的 Port Number 的 PID  $ sudo netstat -lpn |grep 8554 # 刪除佔用的 PID $ sudo kill -9 PID ### ex7-2 ### # VLC media player https://get.videolan.org/vlc/3.0.14/win64/vlc-3.0.14-win64.exe ### ex7-3 ### # 安裝輕量級的 RTSP Server $ cd ~ $ git clone https://github.com/mpromonet/h264_v4l2_rtspserver.git $ sudo apt-get install liblivemedia-dev libv4l-dev cmake $ cd h264_v4l2_rtspserver $ cmake . $ make -j4 $ sudo ./v4l2rtspserver -F 15 --rotation 180 -W 800 -H 600 -P 8554 /dev/video0 # 沒有支援旋轉鏡頭參數的指令,也可以用以下的指令: $ v4l2-ctl --set-ctrl vertical_flip=1 ### ex7-4 (7-1-app-hello.py) ### from flask import Flask app = Flask(__name__) # flask 才會知道你的 root 在何處 @app.route("/") # 定義路由路徑,/ 指的是 web root (URL) def index(): # 一個接著要執行的 function。 return "Hello Flask" if __name__ == "__main__": # 是直接運行的才會執行 app.run() 這個方法 app.run(host = '0.0.0.0', port = 80, debug = True) ### ex7-5 ### # 查找哪一個 python 程序正在執行中 $ ps -fA | grep python # 刪除 root 占用的程序 $ sudo kill -9 PID ### ex7-6 (7-2-app-route.py) ### from flask import Flask, render_template, Response app = Flask(__name__) @app.route("/") def index(): return render_template('link.html') # View 可由自訂的樣板產生 @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) ### ex7-7 ### # 新增一個資料夾 templates,與一個網頁檔 link.html $ mkdir templates $ nano templates/link.html # link.html 的內容

Hello Template

foo # 新增一個 bar.html $ nano templates/bar.html # bar.html 的內容 ### ex7-8 (stream_pi.py) ### from time import time class Camera(object): def __init__(self): self.frames = [open("static/" + f + '.jpg', 'rb').read() for f in ['1', '2', '3']] def get_frame(self): return self.frames[int(time()) % 3] ### ex7-9 (7-3-app-stream.py) ### from flask import Flask, render_template, Response from stream_pi import Camera app = Flask(__name__) @app.route('/') def index(): return render_template('stream.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') if __name__ == "__main__": app.run(host = '0.0.0.0', port = 80, debug = True) ### ex7-10 ### # 新增一個 stream.html $ nano templates/stream.html # stream.html 的內容

Hello Stream

### ex7-11 (7-4-app-camera.py) ### from flask import Flask, render_template, Response from camera_pi import Camera app = Flask(__name__) @app.route('/') def index(): return render_template('stream.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') if __name__ == "__main__": app.run(host = '0.0.0.0', port = 80, debug = True) ### ex7-12 (camera_pi.py) ### import cv2 class Camera(object): def __init__(self): if cv2.__version__.startswith('2'): PROP_FRAME_WIDTH = cv2.cv.CV_CAP_PROP_FRAME_WIDTH PROP_FRAME_HEIGHT = cv2.cv.CV_CAP_PROP_FRAME_HEIGHT elif cv2.__version__.startswith('3'): PROP_FRAME_WIDTH = cv2.CAP_PROP_FRAME_WIDTH PROP_FRAME_HEIGHT = cv2.CAP_PROP_FRAME_HEIGHT else: PROP_FRAME_WIDTH = cv2.CAP_PROP_FRAME_WIDTH PROP_FRAME_HEIGHT = cv2.CAP_PROP_FRAME_HEIGHT self.video = cv2.VideoCapture(0) #self.video = cv2.VideoCapture(1) #self.video.set(PROP_FRAME_WIDTH, 640) #self.video.set(PROP_FRAME_HEIGHT, 480) self.video.set(PROP_FRAME_WIDTH, 320) self.video.set(PROP_FRAME_HEIGHT, 240) def __del__(self): self.video.release() def get_frame(self): success, image = self.video.read() ret, jpeg = cv2.imencode('.jpg', image) return jpeg.tostring()