引言:近幾年來,談起發展最火熱的幾個關鍵詞必然是人工智能、大數據以及物聯網的萬物互聯、邊緣計算等等了。而今天,咱們就將利用Python實現物聯網下的數據傳輸功能。主要的內容包括:本地視頻傳輸到服務器、視頻傳輸到手機實時顯示、以及文本傳輸等方式
物聯網是新一代信息技術的重要組成部分,也是"信息化"時代的重要發展階段。顧名思義,物聯網就是物物相連的互聯網。這有兩層意思:其一,物聯網的核心和基礎仍然是互聯網,是在互聯網基礎上的延伸和擴展的網絡;其二,其用戶端延伸和擴展到了任何物品與物品之間,進行信息交換和通訊,也就是物物相息。物聯網經過智能感知、識別技術與普適計算等通訊感知技術,普遍應用於網絡的融合中,也所以被稱爲繼計算機、互聯網以後世界信息產業發展的第三次浪潮。而物聯網最爲核心的功能即是數據傳輸功能,利用互聯網實現數據在任何能夠接受數據的設備平臺上達到傳輸效果,其中設備能夠包括:本地PC、服務器、樹莓派、手機、手環等等。html
首先咱們使用的Python版本是3.6.5所用到的模塊以下:python
1.Opencv模塊:在這裏咱們用來讀取視頻流數據,以及圖片或者是視頻的編碼解碼和數據視頻的顯示;flask
2.Numpy模塊:在這裏用來和圖片解碼結合使用進行數據運算;bash
3.Socket模塊:Socket又稱"套接字",應用程序一般經過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間能夠通信。服務器
4.Flask框架:Flask是一個Python編寫的Web 微框架,讓咱們能夠使用Python語言快速實現一個網站或Web服務。網絡
客戶端經過opencv讀取本地攝像頭數據,而後編碼成數據流格式,利用socket實現向服務端的發送,客戶端代碼以下:多線程
#客戶端代碼 import socket import threading import cv2 import 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接收數據流,而後解碼成爲圖片,並實時顯示:app
#服務器端 import socket import threading import numpy as np import 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'): break def 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()
能夠利用opencv讀取視頻或是攝像頭,進行編解碼後傳輸。代碼以下:框架
from flask import Flask, render_template, Response import cv2 import time class 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')
因爲手機端不方便運行Python程序,咱們能夠利用flask搭建視頻傳輸網頁,再利用opencv保存圖片更新圖片,以及flask更新圖片實現視頻傳輸效果。socket
#!/usr/bin/env python from importlib import import_module import os from flask import Flask, render_template, Response # import camera driver if os.environ.get('CAMERA'): Camera = import_module('camera_' + os.environ['CAMERA']).Camera else: from camera import Camera # Raspberry Pi camera module (requires picamera package) # from camera_pi import Camera app = 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)