專案介紹:
在本專案中,實作從本地攝像頭獲取資料幀,然后將其轉換成ip攝像頭資料流并在客戶端通過opencv代碼實時獲取該影像資料進行顯示:
當然也能在瀏覽器通過輸入地址進行視頻的訪問
專案所用庫版本:
Flask : 2.0.1
matplotlib : 3.4.2
numpy : 1.21.1
python : 3.7.3
PyAutoGUI : 0.9.53
opencv : 3.3.0
實驗平臺 :樹莓派
服務器端:
import pyautogui
from matplotlib import pyplot as plt
import cv2
import numpy as np
import os
from flask import Flask, render_template, Response
app = Flask(__name__)
def gen():
while(True):
img = pyautogui.screenshot()
img=np.array(img)
eye = img[0:200,0:200]
image = cv2.imencode('.jpg', eye)[1].tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + image + b'\r\n')
#out.write(eye)
#counter += 1
#cv2.imwrite('./test.png',eye)
#os.system('scp test.png ceremony@192.168.1.131:/home/ceremony/png')
#cv2.imshow('sad',eye)
#cv2.waitKey(10)
#os.system('rm test.png')
@app.route('/video_feed')
def video_feed():
return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
app.run(host='0.0.0.0',port=5000)
說明:因為這里我手里沒有攝像頭,因此使用了pyautogui庫實時截取桌面的某一區域,將其轉為numpy格式(因為在opencv中,使用read讀取的fram格式就是numpy的,因此這里將其轉換為numpy格式)
客戶端:
使用opencv讀取該ip攝像頭的資料流,并實時顯示:
import cv2
url = 'http://192.168.1.220:5000/video_feed'
cap = cv2.VideoCapture(url)
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow('frame',frame)
cv2.waitKey(10)
效果:

注意:
上述是通過截屏的方式進行的,在使用真實的攝像頭時,不對服務器端進行設定在瀏覽器中是完全可以訪問的,但是如果通過上面的opencv的代碼進行獲取就會出問題:會報如下錯誤:
Assertion failed (size.width>0 && size.height>0) in imshow, file /home/pi/opencv-3.3.0/modules/highgui/src/window.cpp, line 325
Traceback (most recent call last):
File "read_flask.py", line 7, in <module>
cv2.imshow('frame',frame)
cv2.error: /home/pi/opencv-3.3.0/modules/highgui/src/window.cpp:325: error: (-215) size.width>0 && size.height>0 in fun
出現上面錯誤并不是因為我們的代碼有問題,而是應為樹莓派羸弱的性能,導致客戶端一次不能讀取完一幀圖片資料,因此該圖片幀就是損壞的,當然不能顯示了
解決方式
在服務器端對攝像頭的幀資料進行截取,植上傳一部分,這里為了還原圖片最大真實情況,我截取了200*200的圖片中間區域進行試驗,
當然最有效的方法還是對影像進行上采樣和下采樣,在服務器端,我們對影像進行下采樣,使影像大小變為原來一般,在客戶端對影像進行上采樣,使影像擴大為原來的2倍
通過截取圖片大小進行解決
服務器端代碼:
import pyautogui
from matplotlib import pyplot as plt
import cv2
import numpy as np
import os
from flask import Flask, render_template, Response
app = Flask(__name__)
cap = cv2.VideoCapture(0)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
def gen():
while(True):
#img = pyautogui.screenshot()
#img=np.array(img)
ret, frame = cap.read()
eye = frame[220:420,140:340]
#ret, jpeg = cv2.imencode('.jpg', eye)
#re_img = jpeg.tobytes()
image = cv2.imencode('.jpg', eye)[1].tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + image + b'\r\n')
cv2.waitKey(20)
#out.write(eye)
#counter += 1
#cv2.imwrite('./test.png',eye)
#os.system('scp test.png ceremony@192.168.1.131:/home/ceremony/png')
#cv2.imshow('sad',eye)
#cv2.waitKey(10)
#os.system('rm test.png')
@app.route('/video_feed')
def video_feed():
return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
app.run(host='0.0.0.0',port=5000)
客戶端代碼:
import cv2
url = 'http://192.168.1.220:5000/video_feed'
cap = cv2.VideoCapture(url)
while(True):
ret, frame = cap.read()
cv2.imshow('frame',frame)
cv2.waitKey(50)
效果如下:

通過上下采樣進行解決
服務器端代碼:
import pyautogui
from matplotlib import pyplot as plt
import cv2
import numpy as np
import os
from flask import Flask, render_template, Response
app = Flask(__name__)
cap = cv2.VideoCapture(0)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
def gen():
while(True):
#img = pyautogui.screenshot()
#img=np.array(img)
ret, frame = cap.read()
eye=cv2.pyrDown(frame)
#eye = frame[220:420,140:340]
#ret, jpeg = cv2.imencode('.jpg', eye)
#re_img = jpeg.tobytes()
image = cv2.imencode('.jpg', eye)[1].tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + image + b'\r\n')
cv2.waitKey(20)
#out.write(eye)
#counter += 1
#cv2.imwrite('./test.png',eye)
#os.system('scp test.png ceremony@192.168.1.131:/home/ceremony/png')
#cv2.imshow('sad',eye)
#cv2.waitKey(10)
#os.system('rm test.png')
@app.route('/video_feed')
def video_feed():
return Response(gen(), mimetype='multipart/x-mixed-replace; boundary=frame')
app.run(host='0.0.0.0',port=5000)
客戶端代碼:
import cv2
url = 'http://192.168.1.220:5000/video_feed'
cap = cv2.VideoCapture(url)
while(True):
ret, frame = cap.read()
dst = cv2.pyrUp(frame)
cv2.imshow('frame',dst)
cv2.waitKey(1)
效果:

Expected boundary '--' not found, instead found a line of 127 bytes
該問題參考文章:
鏈接1
鏈接2
鏈接3
鏈接4
鏈接5
flask參考文章:鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291134.html
標籤:其他
下一篇:爬蟲學習筆記(第四章)驗證碼識別
