作者 | 李秋鍵
責編 | 夕顏
出品 | AI科技大本營(ID:rgznai100)
引言:近幾年來,談起發展最火熱的幾個關鍵詞必然是人工智能、大數據以及物聯網的萬物互聯、邊緣計算等等了。而今天,我們就將利用Python實現物聯網下的數據傳輸功能。主要的內容包括:本地視頻傳輸到服務器、視頻傳輸到手機實時顯示、以及文本傳輸等方式。
物聯網是新一代信息技術的重要組成部分,也是"信息化"時代的重要發展階段。顧名思義,物聯網就是物物相連的互聯網。這有兩層意思:其一,物聯網的核心和基礎仍然是互聯網,是在互聯網基礎上的延伸和擴展的網絡;其二,其用戶端延伸和擴展到了任何物品與物品之間,進行信息交換和通信,也就是物物相息。物聯網通過智能感知、識別技術與普適計算等通信感知技術,廣泛應用於網絡的融合中,也因此被稱爲繼計算機、互聯網之後世界信息產業發展的第三次浪潮。而物聯網最爲核心的功能便是數據傳輸功能,利用互聯網實現數據在任何可以接受數據的設備平臺上達到傳輸效果,其中設備可以包括:本地PC、服務器、樹莓派、手機、手環等等。
其中實現的效果如下可見:
視頻傳輸到服務器效果圖
視頻傳輸到手機效果圖
實驗前的準備
首先我們使用的Python版本是3.6.5所用到的模塊如下:
Opencv模塊:在這裏我們用來讀取視頻流數據,以及圖片或者是視頻的編碼解碼和數據視頻的顯示;
Numpy模塊:在這裏用來和圖片解碼結合使用進行數據運算;
Socket模塊:Socket又稱"套接字",應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間可以通訊。
Flask框架:Flask是一個Python編寫的Web 微框架,讓我們可以使用Python語言快速實現一個網站或Web服務。
視頻傳輸
2.1 視頻傳輸服務器
客戶端通過opencv讀取本地攝像頭數據,然後編碼成數據流格式,利用socket實現向服務端的發送,客戶端代碼如下:
#客戶端代碼import socketimport threadingimport cv2import numpy as np#接受服務器返回的數據的函數def recvlink(client): while True: msg=client.recv(1024) print('Ubuntu say: '+msg.decode('utf-8'))def main(): #創建ipv4的socket對象,使用TCP協議(SOCK_STREAM) client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #設置服務器ip地址,注意應該是服務器的公網ip host='ip地址' #設置要發送到的服務器端口,需要在雲服務器管理界面打開對應端口的防火牆 port=端口 #建立TCP協議連接,這時候服務器就會監聽到到連接請求,並開始等待接受client發送的數據 client.connect((host,port)) #建立連接後,服務器端會返回連接成功消息 start_msg=client.recv(1024) print(start_msg.decode('utf-8')) #開啓一個線程用來接受服務器發來的消息 t=threading.Thread(target=recvlink,args=(client,)) t.start() cap = cv2.VideoCapture(0) quality = 25 # 圖像的質量 encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality] while (cap.isOpened()): ret, frame = cap.read() if ret == True: img_encode = cv2.imencode(".jpg", frame, encode_param)[1] data_encode = np.array(img_encode) str_encode = data_encode.tostring() print(str_encode) print(len(str_encode)) #輸入要發送的信息 sendmsg="kehu" #向服務器發送消息 client.send(str_encode) if sendmsg=='quit': break #結束時關閉客戶端 client.close()if __name__ == '__main__': main()
服務器端通過設置bufSize防止出現粘包,利用socket接收數據流,然後解碼成爲圖片,並實時顯示:
#服務器端import socketimport threadingimport numpy as npimport cv2#接受客戶端消息函數def recv_msg(clientsocket): global temp while True: # 接受客戶端消息,設置一次最多接受1024字節的數據 recv_msg = clientsocket.recv(10240) # 把接收到的東西解碼 msg = np.fromstring(recv_msg, np.uint8) img_decode = cv2.imdecode(msg, cv2.IMREAD_COLOR) try: s=img_decode.shape img_decode=img_decode temp=img_decode except: img_decode=temp pass cv2.imshow('SERVER', img_decode) if cv2.waitKey(1) & 0xFF == ord('q'): breakdef main(): #創建服務器端socket對象 ipv4 + TCP協議,和客戶端一樣 socket_server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 注意注意注意,我們要綁定監聽的地址和端口。服務器可能有多塊網卡,可以綁定到某一塊網卡的IP地址上,也可以用0.0.0.0綁定到所有的網絡地址 # 還可以用127.0.0.1綁定到本機地址。127.0.0.1是一個特殊的IP地址,表示本機地址,如果綁定到這個地址,客戶端必須同時在本機運行才能連接,也就是說,外部的計算機無法連接進來。 # 這個程序中host使用'0.0.0.0'或服務器內網ip地址都可以,我這裏就使用了內網ip地址 #host='0.0.0.0' host='' #設置被監聽的端口號,小於1024的端口號不能使用,因爲他們是Internet標準服務的端口號 port= #綁定地址 socket_server.bind((host,port)) #設置最大監聽數,也就是最多可以同時響應幾個客戶端請求,一般配合多線程使用 socket_server.listen(5) #等待客戶端連接,一旦有了連接就立刻向下執行,否則等待 #accept()函數會返回一個元組,第一個元素是客戶端socket對象,第二個元素是客戶端地址(ip地址+端口號) clientsocket,addr=socket_server.accept() # 有了客戶端連接後之後才能執行以下代碼,我們先向客戶端發送連接成功消息 clientsocket.send('你現在已經連接上了服務器啦,我們來聊天吧!'.encode('utf-8')) # 和客戶端一樣開啓一個線程接受客戶端的信息 t=threading.Thread(target=recv_msg,args=(clientsocket,)) t.start()''' # 發送消息 while True: reply="cer" clientsocket.send(reply.encode('utf-8')) clientsocket.close()'''if __name__=='__main__': main()
2.2 視頻傳輸到手機
可以利用opencv讀取視頻或是攝像頭,進行編解碼後傳輸。代碼如下:
from flask import Flask, render_template, Responseimport cv2import timeclass VideoCamera(object): def __init__(self): # 通過opencv獲取實時視頻流 self.video = cv2.VideoCapture(0) def __del__(self): self.video.release() def get_frame(self): try: image=cv2.imread("1.jpg") ceshi = image.shape global temp temp=image # 因爲opencv讀取的圖片並非jpeg格式,因此要用motion JPEG模式需要先將圖片轉碼成jpg格式圖片 ret, jpeg = cv2.imencode('.jpg', image) except: image = temp # 因爲opencv讀取的圖片並非jpeg格式,因此要用motion JPEG模式需要先將圖片轉碼成jpg格式圖片 ret, jpeg = cv2.imencode('.jpg', image) return jpeg.tobytes()app = Flask(__name__)@app.route('/') # 主頁def index(): # jinja2模板,具體格式保存在index.html文件中 return render_template('index.html')def gen(camera): while True: #time.sleep(0.5) frame = camera.get_frame() # 使用generator函數輸出視頻流, 每次請求輸出的content類型是image/jpeg 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(VideoCamera()), mimetype='multipart/x-mixed-replace; boundary=frame')
需要搭配的html代碼:
<html> <head> <title>Video Streaming Demonstration</title> </head> <body> <h1>Video Streaming Demonstration</h1> <img src="{
{ url_for('video_feed') }}"> </body></html>
圖片形成視頻流傳輸flask
由於手機端不方便運行Python程序,我們可以利用flask搭建視頻傳輸網頁,再利用opencv保存圖片更新圖片,以及flask更新圖片實現視頻傳輸效果。
#!/usr/bin/env pythonfrom importlib import import_moduleimport osfrom flask import Flask, render_template, Response# import camera driverif os.environ.get('CAMERA'): Camera = import_module('camera_' + os.environ['CAMERA']).Cameraelse: from camera import Camera# Raspberry Pi camera module (requires picamera package)# from camera_pi import Cameraapp = Flask(__name__)@app.route('/')def index(): """Video streaming home page.""" return render_template('index.html')def gen(camera): """Video streaming generator function.""" while True: frame = camera.get_frame() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')@app.route('/video_feed')def video_feed(): """Video streaming route. Put this in the src attribute of an img tag.""" return Response(gen(Camera()), mimetype='multipart/x-mixed-replace; boundary=frame')if __name__ == '__main__':app.run(host='0.0.0.0', threaded=True)
源碼地址:
鏈接:https://pan.baidu.com/s/1AMftWOZXnT-gNu-fuhMAaQ
提取碼:dx7z
更多精彩推薦
☞讀懂深度遷移學習,看這文就夠了 | 贈書
☞『帶你學AI』一文帶你搞懂OCR識別算法CRNN:解析+源碼
☞龍泉寺賢超法師:用 AI 爲古籍經書識別、斷句、翻譯
☞微信十週年,騰訊曬成績單了!
點分享點收藏點點贊點在看