欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python實現(xiàn)udp傳輸圖片功能

 更新時間:2020年03月20日 16:10:12   作者:小白xbw  
這篇文章主要為大家詳細介紹了python實現(xiàn)udp傳輸圖片功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了python實現(xiàn)udp傳輸圖片的具體代碼,供大家參考,具體內(nèi)容如下

首先要了解UDP的工作模式

對于服務(wù)器,首先綁定IP和端口,本機測試的時候可以使用127.0.0.1是本機的專有IP,端口號 大于1024的是自定義的,所以用大于1024的端口號,然后接收客戶端數(shù)據(jù),處理,返回
對于客戶端,UDP不用建立連接,只管發(fā)送不管接收到?jīng)]有,所以可以直接對服務(wù)器的IP地址和端口號發(fā)送信息,然后等待應(yīng)答。

注意傳輸?shù)臄?shù)據(jù)是二進制流數(shù)據(jù),所以要找方法把需要傳輸?shù)臄?shù)據(jù)編碼成二進制碼流,傳過去之后再解碼即可,這里我用到了opencv讀取圖片成numpy的array格式,然后編碼,傳輸,最后接到之后再解碼。

先說一次性傳輸整個圖片,這個思路就是接受的參數(shù)設(shè)置很大,而且圖片比較小的情況,實現(xiàn)比較簡單

首先是服務(wù)器腳本,實現(xiàn)了接收、顯示、應(yīng)答

udp_sever.py

# -*- coding: utf-8 -*-

import socket
import cv2
import numpy as np

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 綁定端口:
s.bind(('127.0.0.1', 9999))

print('Bind UDP on 9999...')

while True:
 # 接收數(shù)據(jù):
 data, addr = s.recvfrom(400000)
 print('Received from %s:%s.' % addr)
 #解碼
 nparr = np.fromstring(data, np.uint8)
 #解碼成圖片numpy
 img_decode = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
 cv2.imshow('result',img_decode)
 cv2.waitKey()
 reply = "get message!!!"
 s.sendto(reply.encode('utf-8'), addr)
 cv2.destroyAllWindows()

客戶端腳本,實現(xiàn)了發(fā)送圖片,接收應(yīng)答

udp_client.py

# -*- coding: utf-8 -*-
import socket
import cv2
import numpy as np

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

img = cv2.imread('/home/xbw/jupyter_notebook/0.jpg')
img_encode = cv2.imencode('.jpg', img)[1]
data_encode = np.array(img_encode)
data = data_encode.tostring()

# 發(fā)送數(shù)據(jù):
s.sendto(data, ('127.0.0.1', 9999))
# 接收數(shù)據(jù):
print(s.recv(1024).decode('utf-8'))

s.close()

為了方便理解放一下圖片轉(zhuǎn)到二進制再轉(zhuǎn)回圖片的代碼

import numpy as np
import cv2
img = cv2.imread('0.jpg')
img_encode = cv2.imencode('.jpg', img)[1]
data_encode = np.array(img_encode)
str_encode = data_encode.tostring()
#print(str_encode)
nparr = np.fromstring(str_encode, np.uint8)
img_decode = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
cv2.imshow('result',img_decode)
cv2.waitKey()
cv2.destroyAllWindows()

分批傳輸圖片

搞了好久終于知道怎么分批傳輸圖片了,首先要知道需要傳的圖片需要多長的內(nèi)存,不然不知道什么時候停止接收,這樣就要考慮加一個文件頭,告訴服務(wù)器要接受多長的碼流。

實現(xiàn)思路是,首先客戶端要先發(fā)送一個文件頭,包含了碼流的長度,用一個long int型的數(shù),先用struct.pack打包,發(fā)過去,然后循環(huán)發(fā)送圖片的碼流即可

接著服務(wù)器先接到文件頭,確認(rèn)圖片碼流的長度,然后循環(huán)接收確定長度的碼流,最后再解碼成圖片即可

實現(xiàn)代碼如下:

首先是客戶端腳本

udp_client.py

# -*- coding: utf-8 -*-
import socket
import cv2
import numpy as np
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#讀取圖片,編碼成二進制 bytes格式
img = cv2.imread('/home/xbw/jupyter_notebook/0.jpg')
img_encode = cv2.imencode('.jpg', img)[1]
data_encode = np.array(img_encode)
data = data_encode.tostring()
#定義文件頭,打包成結(jié)構(gòu)體
fhead = struct.pack('l',len(data))
# 發(fā)送文件頭:
s.sendto(fhead,('127.0.0.1', 9999))
#循環(huán)發(fā)送圖片碼流
for i in range(len(data)//1024+1):
 if 1024*(i+1)>len(data):
 s.sendto(data[1024*i:], ('127.0.0.1', 9999))
 else:
 s.sendto(data[1024*i:1024*(i+1)], ('127.0.0.1', 9999))
# 接收應(yīng)答數(shù)據(jù):
print(s.recv(1024).decode('utf-8'))
#關(guān)閉
s.close()

然后是服務(wù)器接收

udp_sever.py

# -*- coding: utf-8 -*-

import socket
import cv2
import numpy as np
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 綁定端口:
s.bind(('127.0.0.1', 9999))

print('Bind UDP on 9999...')

while True:
 # 接收文件頭,文件頭的長度由calcsize函數(shù)確定,注意這里recvfrom是接收UDP消息,recv是接收TCP消息
 fhead_size = struct.calcsize('l')
 buf,addr = s.recvfrom(fhead_size)
 if buf:
 #這里結(jié)果是一個元組,所以把值取出來
 data_size = struct.unpack('l',buf)[0]
 #接收圖片碼流長度的碼流
 recvd_size = 0
 data_total = b''
 while not recvd_size == data_size:
 if data_size -recvd_size >1024:
  data,addr = s.recvfrom(1024)
  recvd_size += len(data)
 else:
  data,addr = s.recvfrom(1024)
  recvd_size = data_size 
 data_total += data
# data, addr = s.recvfrom(400000)
 print('Received')
# reply = 'Hello, %s!' % data.decode('utf-8')
# s.sendto(reply.encode('utf-8'), addr)
 #把接到的碼流解碼成numpy數(shù)組,顯示圖像
 nparr = np.fromstring(data_total, np.uint8)
 img_decode = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
 cv2.imshow('result',img_decode)
 cv2.waitKey()
 #應(yīng)答
 reply = "get message!!!"
 s.sendto(reply.encode('utf-8'), addr)
 cv2.destroyAllWindows()

-------------------分割線----------------

上面是基本的實現(xiàn),經(jīng)過一番學(xué)習(xí)我終于掌握了UDP傳輸?shù)木?/p>

首先是確定客戶端和服務(wù)器的運行機制

客戶端:先定義一個socket對象,不用綁定,然后指定IP地址和端口發(fā)送消息,然后如果用了recvfrom就會一直阻塞等待應(yīng)答(這個很有用,作用就是保證對方確實收到,再發(fā)新的消息,不用在考慮發(fā)送頻率的問題了),前面加一個while True就可以循環(huán)發(fā)送了,如果涉及到很大的消息,可以拆分發(fā)送,技巧是先發(fā)送一個文件頭高速服務(wù)器要發(fā)的內(nèi)容有多大(文件頭這里建議使用stuct庫,看前面例程),然后隨后發(fā)送文件內(nèi)容,保證要循環(huán)發(fā)送,因為每次發(fā)送,對面就當(dāng)發(fā)了一次,假如發(fā)了2048字節(jié)的內(nèi)容,對面設(shè)置的每次收1024,那么剩下的1024就被丟掉了,而不是等待下次繼續(xù)接收。還有就是發(fā)送的是二進制的碼流,目前我用到的轉(zhuǎn)換成碼流的方法有:圖片用opencv,先imencode 轉(zhuǎn)成二進制,然后再轉(zhuǎn)成numpy,然后再tostring。文件頭這種,需要確切知道占多大內(nèi)存,使得服務(wù)器好接收的,用了stuct庫,里面的pack,unpack,calcsize三個函數(shù)非常好用,發(fā)送的時候把數(shù)據(jù)pack一下就能發(fā)送了。列表、字典等等,作為文件內(nèi)容,用到了json,有點萬能,先json.dumps轉(zhuǎn)換成json類型,然后再encode編碼成二進制即可拿去發(fā)送了。

服務(wù)器:先定義一個socket對象,綁定IP地址和端口,讓客戶端可以找到,然后等待接收消息,收到消息之后處理消息,應(yīng)答,配合客戶端的recvfrom,保證接收頻率一致,服務(wù)器為了保證始終接收消息,一定會有一個while True,接收到的消息是二進制碼流,因此要進行解碼。針對上面講的編碼方式解碼,其實就是編碼方式的反向操作:圖片,用opencv解碼,先是np.fromstring,然后再cv2.imdecode(data, cv2.IMREAD_COLOR)。對于接收文件頭,這里有點技巧,用struct.calcsize確定文件頭長度,然后只接收這個長度的碼流,再unpack出來即可,這里unpack是個元組。對于json,解碼就是先decode,再json.loads即可,是上面編碼的反向操作。

然后再高端一點的操作,同一個腳本多進程工作,這就要用到了threading.Thread創(chuàng)建多個進程,思路就是新建多個服務(wù)器,然后分配給不同的進程,他們的IP地址可以一樣,端口號不一樣就行,然后就可以在同一個腳本里并行工作了,這里不同于TCP,因為UDP不需要建立連接

然后附上我實現(xiàn)的源碼,服務(wù)器腳本里有兩個進程,一個接收客戶端1的圖片,另一個接收客戶端2的列表

服務(wù)器

udp_server.py

# -*- coding: utf-8 -*-
import socket
import cv2
import numpy as np
import struct
import threading
import json
#設(shè)置IP地址、兩個服務(wù)器端口號
dest_ip = '127.0.0.1'
img_port = 9999
msg_port = 6666

#服務(wù)器1的處理、應(yīng)答函數(shù),接收圖片、顯示、應(yīng)答
def receive_img(rec_img):
 while True:
 # 接收數(shù)據(jù):
 fhead_size = struct.calcsize('l')
 buf,addr = rec_img.recvfrom(fhead_size)
 if buf:
  data_size = struct.unpack('l',buf)[0]
  print(data_size)
 recvd_size = 0
 data_total = b''
 while not recvd_size == data_size:
  if data_size -recvd_size >1024:
  data,addr = rec_img.recvfrom(1024)
  recvd_size += len(data)
  else:
  data,addr = rec_img.recvfrom(1024)
  recvd_size = data_size 
  data_total += data
# data, addr = rec_img.recvfrom(400000)
 print('Received')
# reply = 'Hello, %s!' % data.decode('utf-8')
# rec_img.sendto(reply.encode('utf-8'), addr)

 nparr = np.fromstring(data_total, np.uint8)
 img_decode = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
 cv2.imshow('result',img_decode)
 cv2.waitKey(100)
 reply = "get message!!!"
 rec_img.sendto(reply.encode('utf-8'), addr)
# cv2.destroyAllWindows()

#服務(wù)器2函數(shù),接收消息、輸出、應(yīng)答
def receive_msg(rec_msg):
 while True:
 msg_data ,msg_addr = rec_msg.recvfrom(1024)
 msg_str = msg_data.decode('utf-8')
 msg = json.loads(msg_str)
 print(msg)
 reply = 'get the msg'
 rec_msg.sendto(reply.encode('utf-8'),msg_addr)
 rec_msg.close()

#主函數(shù) 創(chuàng)建服務(wù)器、綁定端口、創(chuàng)建運行兩個進程、調(diào)用上面兩個函數(shù)
def main():
 #創(chuàng)建套接字
 rec_img = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 rec_msg = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 #綁定本地地址端口
 rec_img.bind((dest_ip, img_port))
 rec_msg.bind((dest_ip, msg_port))
 #創(chuàng)建進程
 t_recimg = threading.Thread(target=receive_img, args=(rec_img,))
 t_recmsg = threading.Thread(target=receive_msg, args=(rec_msg,))
 #開始進程
 t_recimg.start()
 t_recmsg.start()
 print('程序正常運行?。。?)
 


if __name__ == '__main__':
 main()

客戶端1

udp_client_1.py

# -*- coding: utf-8 -*-
import socket
import cv2
import numpy as np
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cap = cv2.VideoCapture(0)
#cap.set(3,320)
#cap.set(4,240)
while True:
 
 if cap.isOpened():
 flag, img = cap.read()
# img = cv2.imread('/home/xbw/jupyter_notebook/0.jpg')
 img_encode = cv2.imencode('.jpg', img)[1]
 data_encode = np.array(img_encode)
 data = data_encode.tostring()
 #定義文件頭
 fhead = struct.pack('l',len(data))
 # 發(fā)送文件頭、數(shù)據(jù):
 s.sendto(fhead,('127.0.0.1', 9999))
 for i in range(len(data)//1024+1):
  if 1024*(i+1)>len(data):
  s.sendto(data[1024*i:], ('127.0.0.1', 9999))
  else:
  s.sendto(data[1024*i:1024*(i+1)], ('127.0.0.1', 9999))
 # 接收應(yīng)答:
 cv2.waitKey(1)
 print(s.recv(1024).decode('utf-8'))

s.close()

客戶端2

udp_client_2.py

import socket
import cv2
import numpy as np
import struct
import json
import time
#定義套接字
send_msg = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#設(shè)置目標(biāo)IP地址、端口號
target_ip = '127.0.0.1'
target_port = 6666
#發(fā)送數(shù)據(jù),等待應(yīng)答
while True:
 data = [0,0,0,1]
 data_str = json.dumps(data)
 send_msg.sendto(data_str.encode(),(target_ip,target_port))
 time.sleep(0.01)
 print(send_msg.recv(1024).decode('utf-8'))

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • python使用PIL和matplotlib獲取圖片像素點并合并解析

    python使用PIL和matplotlib獲取圖片像素點并合并解析

    這篇文章主要介紹了python使用PIL和matplotlib獲取圖片像素點并合并解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • python 爬取微信文章

    python 爬取微信文章

    本文給大家分享的是使用python通過搜狗入口,爬取微信文章的小程序,非常的簡單實用,有需要的小伙伴可以參考下
    2016-01-01
  • Python通過tkinter實現(xiàn)百度搜索的示例代碼

    Python通過tkinter實現(xiàn)百度搜索的示例代碼

    這篇文章主要介紹了Python通過tkinter實現(xiàn)百度搜索的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Keras自定義IOU方式

    Keras自定義IOU方式

    這篇文章主要介紹了Keras自定義IOU方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • 基于Python創(chuàng)建語音識別控制系統(tǒng)

    基于Python創(chuàng)建語音識別控制系統(tǒng)

    這篇文章主要介紹了通過Python實現(xiàn)創(chuàng)建語音識別控制系統(tǒng),能利用語音識別識別說出來的文字,根據(jù)文字的內(nèi)容來控制圖形移動,感興趣的同學(xué)可以關(guān)注一下
    2021-12-12
  • Python基于SMTP發(fā)送郵件的方法

    Python基于SMTP發(fā)送郵件的方法

    這篇文章主要介紹了Python基于SMTP 發(fā)送郵件的方法,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • 下載python中Crypto庫報錯:ModuleNotFoundError: No module named ‘Crypto’的解決

    下載python中Crypto庫報錯:ModuleNotFoundError: No module named ‘Cry

    Crypto不是自帶的模塊,需要下載。下面這篇文章主要給大家介紹了關(guān)于下載python中Crypto庫報錯:ModuleNotFoundError: No module named 'Crypto'的解決方法,文中通過圖文介紹的非常詳細,需要的朋友可以參考下。
    2018-04-04
  • python使用fileinput模塊實現(xiàn)逐行讀取文件的方法

    python使用fileinput模塊實現(xiàn)逐行讀取文件的方法

    這篇文章主要介紹了python使用fileinput模塊實現(xiàn)逐行讀取文件的方法,涉及Python中fileinput模塊操作文件的相關(guān)技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • 如何利用python給圖片添加半透明水印

    如何利用python給圖片添加半透明水印

    這篇文章主要給大家介紹了關(guān)于如何利用python給圖片添加半透明水印的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • python中response.text 和response.content的區(qū)別詳解

    python中response.text 和response.content的區(qū)別詳解

    這篇文章主要介紹了python中response.text 和response.content的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-05-05

最新評論