0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

AI模型部署邊緣設(shè)備的奇妙之旅:邊緣端設(shè)備的局域網(wǎng)視頻流傳輸方案

福州市凌睿智捷電子有限公司 ? 2025-01-04 12:00 ? 次閱讀

1、簡介

隨著物聯(lián)網(wǎng)(IoT)和智能設(shè)備的快速發(fā)展,邊緣計算技術(shù)已成為高效數(shù)據(jù)處理和服務(wù)交付的重要組成部分。當(dāng)我們考慮利用邊緣端設(shè)備進(jìn)行實(shí)時監(jiān)控時,一個常見的需求是通過攝像頭捕捉視頻,并在局域網(wǎng)內(nèi)實(shí)現(xiàn)視頻流的傳輸。這種設(shè)置不僅適用于家庭和小型企業(yè)的安全監(jiān)控,也能滿足遠(yuǎn)程教育、醫(yī)療監(jiān)護(hù)等多個領(lǐng)域的需要。

面對局域網(wǎng)內(nèi)的視頻流傳輸挑戰(zhàn),有多種方法可以實(shí)現(xiàn)從攝像頭到顯示終端的數(shù)據(jù)傳遞,每種方法都有其特點(diǎn)和適用場景。本文將介紹一種基于TCP/IP協(xié)議棧和Socket編程的方法,這種方法因其穩(wěn)定性和易用性而被廣泛采用。

選擇TCP/IP與Socket編程的理由:

穩(wěn)定性:TCP(傳輸控制協(xié)議)作為面向連接的協(xié)議,確保了數(shù)據(jù)包在網(wǎng)絡(luò)中的有序傳遞,并提供了錯誤檢測與糾正機(jī)制,這對于視頻流這類對丟包敏感的數(shù)據(jù)尤為重要。

靈活性:使用Socket API可以在應(yīng)用層直接操作網(wǎng)絡(luò)通信,給予開發(fā)者更大的自由度來定制視頻流的傳輸邏輯,比如調(diào)整幀率、分辨率或?qū)嵤┳远x的安全措施。

跨平臺支持:無論是Windows、Linux還是macOS,大多數(shù)操作系統(tǒng)都內(nèi)置了對TCP/IP和Socket的支持,這意味著開發(fā)的應(yīng)用程序具有良好的兼容性和移植性。

資源效率:對于邊緣端設(shè)備而言,優(yōu)化后的TCP/IP服務(wù)和Socket編程可以幫助節(jié)省寶貴的計算資源和帶寬,保證即使在網(wǎng)絡(luò)條件有限的情況下也能維持視頻流的流暢性。

接下來,我們將探討如何利用這些技術(shù)構(gòu)建一個簡易的局域網(wǎng)視頻流傳輸系統(tǒng),包括具體的實(shí)現(xiàn)步驟和技術(shù)細(xì)節(jié)。您將看到,通過合理的設(shè)計和配置,即使是普通用戶也能夠在自己的環(huán)境中輕松搭建起一套實(shí)用的實(shí)時監(jiān)控解決方案。如果您對視頻流傳輸有著更高的要求,如低延遲、高清晰度或更復(fù)雜的安全特性,后續(xù)部分還會提及一些進(jìn)階技術(shù)和最佳實(shí)踐建議。

2、相關(guān)知識

2.1 TCP/IP協(xié)議簡介

TCP/IP(Transmission Control Protocol/Internet Protocol,傳輸控制協(xié)議/網(wǎng)際協(xié)議)是指能夠在多個不同網(wǎng)絡(luò)間實(shí)現(xiàn)信息傳輸?shù)膮f(xié)議簇。TCP/IP協(xié)議不僅僅指的是TCP 和IP兩個協(xié)議,而是指一個由FTP、SMTP、TCP、UDP、IP等協(xié)議構(gòu)成的協(xié)議簇, 只是因為在TCP/IP協(xié)議中TCP協(xié)議和IP協(xié)議最具代表性,所以被稱為TCP/IP協(xié)議。

TCP/IP傳輸協(xié)議是嚴(yán)格來說是一個四層的體系結(jié)構(gòu),應(yīng)用層、傳輸層、網(wǎng)絡(luò)層和數(shù)據(jù)鏈路層都包含其中。

層級名稱主要協(xié)議功能描述
應(yīng)用層Telnet, FTP, SMTP, HTTP, HTTPS, DNS 等接收來自傳輸層的數(shù)據(jù)或按不同應(yīng)用要求與方式將數(shù)據(jù)傳輸至傳輸層;提供用戶接口和應(yīng)用服務(wù)。
傳輸層TCP (傳輸控制協(xié)議), UDP (用戶數(shù)據(jù)報協(xié)議)提供端到端的通信服務(wù),確保數(shù)據(jù)可靠地從一臺機(jī)器傳輸?shù)搅硪慌_機(jī)器(TCP)或不保證順序和可靠性但更快速的數(shù)據(jù)傳輸(UDP)。
網(wǎng)絡(luò)層IP (網(wǎng)際協(xié)議), ICMP, IGMP負(fù)責(zé)網(wǎng)絡(luò)中數(shù)據(jù)包的傳送,包括路由選擇、數(shù)據(jù)包轉(zhuǎn)發(fā)等;ICMP用于報告錯誤并交換有限的控制消息;IGMP用于管理組播成員關(guān)系。
網(wǎng)絡(luò)訪問層/鏈路層ARP (地址解析協(xié)議), RARP, Ethernet, Wi-Fi提供鏈路管理和錯誤檢測;處理對不同通信媒介有關(guān)的信息細(xì)節(jié)問題,如物理地址的解析(ARP),以及在局域網(wǎng)中直接傳遞數(shù)據(jù)幀。

2.2 TCP

TCP(傳輸控制協(xié)議)是TCP/IP模型傳輸層中最重要的協(xié)議之一,它提供了一種面向連接、可靠的字節(jié)流服務(wù)。這意味著在兩個應(yīng)用程序之間建立通信之前,必須先通過三次握手過程來建立一個連接;而當(dāng)數(shù)據(jù)傳輸完成后,則需要通過四次揮手過程來斷開這個連接。TCP確保了數(shù)據(jù)包按序到達(dá),并且能夠檢測并重傳丟失或損壞的數(shù)據(jù)包,從而保證了數(shù)據(jù)傳輸?shù)目煽啃浴?/p>

TCP的主要特點(diǎn):

面向連接:在發(fā)送數(shù)據(jù)前,雙方必須建立一個連接。這種連接類似于電話呼叫,在通話開始前需要撥號建立連接。

可靠性:TCP使用確認(rèn)機(jī)制和超時重傳來確保所有發(fā)送的數(shù)據(jù)都被接收方正確接收。如果接收方?jīng)]有收到某個數(shù)據(jù)包或者接收到的是損壞的數(shù)據(jù)包,它會請求發(fā)送方重新發(fā)送該數(shù)據(jù)包。

流量控制:為了防止快速的發(fā)送方淹沒慢速的接收方,TCP實(shí)現(xiàn)了滑動窗口機(jī)制來進(jìn)行流量控制,根據(jù)接收方的能力調(diào)整發(fā)送速率。

擁塞控制:TCP還包含了一系列算法來避免網(wǎng)絡(luò)擁堵,例如慢啟動、擁塞避免、快重傳和快恢復(fù)等。

全雙工通信:TCP支持同時雙向的數(shù)據(jù)傳輸,即可以同時作為客戶端和服務(wù)端進(jìn)行數(shù)據(jù)交換。

錯誤檢查與糾正:利用校驗和機(jī)制對每個數(shù)據(jù)段進(jìn)行完整性驗證,以確保數(shù)據(jù)的準(zhǔn)確性。

TCP適用場景:

文件傳輸(如FTP)

電子郵件(如SMTP, POP3, IMAP)

Web瀏覽(如HTTP, HTTPS)

遠(yuǎn)程登錄(如SSH)

TCP工作流程概述

三次握手:用于建立連接??蛻舳税l(fā)送SYN(同步序列編號),服務(wù)器回應(yīng)ACK(確認(rèn)信息)和自己的SYN,然后客戶端再次回應(yīng)ACK確認(rèn)。

數(shù)據(jù)傳輸:一旦連接建立,雙方就可以開始傳輸數(shù)據(jù)。TCP負(fù)責(zé)將數(shù)據(jù)分割成合適大小的數(shù)據(jù)段,并為每個數(shù)據(jù)段添加頭部信息,包括序列號以便接收方重組數(shù)據(jù)。

四次揮手:當(dāng)一方完成數(shù)據(jù)發(fā)送后,它會發(fā)送FIN(結(jié)束標(biāo)志)給另一方表示希望關(guān)閉連接。接收方會回應(yīng)ACK確認(rèn)收到FIN,并在準(zhǔn)備好關(guān)閉連接時也發(fā)送自己的FIN。發(fā)送方再回應(yīng)ACK,最終完成連接的終止。

綜上所述,TCP因其高可靠性和安全性,廣泛應(yīng)用于那些對數(shù)據(jù)完整性和順序有嚴(yán)格要求的應(yīng)用程序中。

2.3 UDP

UDP(用戶數(shù)據(jù)報協(xié)議)是TCP/IP模型傳輸層的一個重要成員,它提供了一種無需建立連接即可發(fā)送和接收數(shù)據(jù)包的通信方式。與TCP不同的是,UDP不保證數(shù)據(jù)的順序性和可靠性,也不進(jìn)行流量控制或擁塞控制。這意味著使用UDP時,數(shù)據(jù)可能會丟失、重復(fù)或者亂序到達(dá)。

UDP的主要特點(diǎn):

無連接:在發(fā)送數(shù)據(jù)之前不需要建立連接,因此減少了建立連接所需的時間。

盡力而為的服務(wù):UDP不會對數(shù)據(jù)包的傳輸做任何保證,也不會重傳丟失的數(shù)據(jù)包。

低開銷:由于缺少確認(rèn)機(jī)制和其他復(fù)雜的功能,UDP具有較低的頭部開銷,這使得它非常適合實(shí)時應(yīng)用。

高效性:因為沒有復(fù)雜的握手過程,所以UDP可以更快地發(fā)送數(shù)據(jù)。

適用于廣播或多播:UDP支持向多個目的地同時發(fā)送數(shù)據(jù)的能力,這對于視頻會議等應(yīng)用場景非常有用。

UDP適用場景:

實(shí)時音頻/視頻流媒體服務(wù)

在線游戲

DNS查詢

SNMP(簡單網(wǎng)絡(luò)管理協(xié)議)

其他對延遲敏感的應(yīng)用程序

2.4 TCP vs UDP

特性TCP (Transmission Control Protocol)UDP (User Datagram Protocol)
連接類型面向連接,需要三次握手建立連接無連接,即發(fā)即用
可靠性可靠的數(shù)據(jù)傳輸,確保數(shù)據(jù)按序完整到達(dá)不可靠,不保證數(shù)據(jù)包會到達(dá),可能丟失或亂序
速度較慢,因為有握手過程和錯誤檢查更快,因為它沒有這些額外的過程
流量控制支持,通過滑動窗口機(jī)制不支持
擁塞控制支持不支持
頭部開銷較大,因為包含更多的控制信息較小,只有必要的控制信息
用途適合需要高可靠性的應(yīng)用程序,如文件傳輸、電子郵件適合對時間敏感但可容忍一定數(shù)據(jù)損失的應(yīng)用,如視頻流

2.5 Socket

Socket(套接字)是網(wǎng)絡(luò)編程中的一個重要概念,它提供了一種跨進(jìn)程通信的方式,使得不同計算機(jī)上的應(yīng)用程序能夠通過網(wǎng)絡(luò)交換數(shù)據(jù)。在實(shí)現(xiàn)TCP/IP服務(wù)時,Socket扮演著至關(guān)重要的角色,它是程序員用來編寫客戶端和服務(wù)器端程序的接口。

Socket的基本特性:

地址家族:定義了通信協(xié)議類型,例如IPv4(AF_INET)或IPv6(AF_INET6)。

類型:指定了傳輸層使用的協(xié)議,如TCP(SOCK_STREAM,流式套接字)或UDP(SOCK_DGRAM,數(shù)據(jù)報套接字)。

協(xié)議:通常設(shè)置為0,表示使用默認(rèn)協(xié)議;對于某些特殊情況可以指定特定協(xié)議編號。

使用Socket實(shí)現(xiàn)TCP/IP服務(wù)的步驟:

創(chuàng)建Socket:在服務(wù)器端和客戶端都需要調(diào)用socket()函數(shù)來創(chuàng)建一個套接字對象,該對象將用于發(fā)送和接收數(shù)據(jù)。

綁定(僅限服務(wù)器端):服務(wù)器需要調(diào)用bind()函數(shù)將其套接字與特定的IP地址和端口號關(guān)聯(lián)起來,以便其他客戶端可以通過這些信息找到并連接到服務(wù)器。

監(jiān)聽(僅限服務(wù)器端):服務(wù)器調(diào)用listen()函數(shù)開始監(jiān)聽來自客戶端的連接請求。這一步驟會將套接字轉(zhuǎn)換為被動模式,準(zhǔn)備接受連接。

接受連接(僅限服務(wù)器端):當(dāng)有客戶端嘗試連接時,服務(wù)器調(diào)用accept()函數(shù)來接受這個連接,并返回一個新的套接字,專門用于與那個特定客戶端之間的通信。

連接服務(wù)器(客戶端操作):客戶端調(diào)用connect()函數(shù)發(fā)起對服務(wù)器的連接請求,指定要連接的服務(wù)器IP地址和端口號。

發(fā)送/接收數(shù)據(jù):一旦建立了連接,雙方都可以使用send()和recv()函數(shù)來進(jìn)行數(shù)據(jù)的發(fā)送和接收。對于TCP來說,這意味著可以進(jìn)行可靠的數(shù)據(jù)流傳輸。

關(guān)閉連接:數(shù)據(jù)交換完成后,雙方應(yīng)該調(diào)用close()函數(shù)來關(guān)閉各自的套接字,釋放資源。

以上代碼展示了如何使用Python內(nèi)置的socket庫來實(shí)現(xiàn)一個簡單的TCP回顯服務(wù)器和客戶端。

3 邊緣端設(shè)備實(shí)現(xiàn)

我此次使用的設(shè)備是凌智視覺模塊,但是該設(shè)備是沒有帶WiFi的,如果需要使用WiFi,需要外界一塊WiFi模塊。

7fdf0530-ca50-11ef-9434-92fbcf53809c.jpg

3.1 服務(wù)端

下面我將搭建一個簡易的服務(wù)器,用于通過TCP連接向客戶端發(fā)送視頻幀。它使用OpenCV庫捕獲圖像,并將圖像編碼為JPEG格式后通過網(wǎng)絡(luò)傳輸給客戶端。此外,它還支持命令控制和視頻流模式,允許客戶端發(fā)送命令來控制視頻幀的傳輸。

以下是代碼的主要功能模塊和邏輯:

導(dǎo)入必要的庫:

cv2:來自lockzhiner_vision_module的OpenCV庫,用于視頻捕獲和圖像處理。

Thread, Event:來自threading模塊,用于創(chuàng)建線程和事件對象以同步線程間的操作。

socket:用于網(wǎng)絡(luò)通信。

os, time:分別用于操作系統(tǒng)相關(guān)的功能和時間測量。

定義輔助函數(shù):

send_image(conn, frame):負(fù)責(zé)將一幀圖像編碼成JPEG格式并通過TCP連接發(fā)送出去。

定義線程處理函數(shù):

handle_client_send(conn, start_event, shutdown_event, confirm_event, streaming_event, cap):此函數(shù)在一個獨(dú)立線程中運(yùn)行,負(fù)責(zé)讀取攝像頭圖像并根據(jù)事件狀態(tài)決定是否發(fā)送圖像。它還會計算和打印幀率。

handle_client_receive(conn, addr, cap, start_event, shutdown_event, confirm_event, streaming_event):此函數(shù)也在一個獨(dú)立線程中運(yùn)行,負(fù)責(zé)接收來自客戶端的命令并對這些命令作出響應(yīng),比如開始發(fā)送單個圖像、確認(rèn)接收到圖像、關(guān)閉連接或切換視頻流模式等。

主程序邏輯:

設(shè)置了服務(wù)器的IP地址(HOST)和端口(PORT),并初始化了OpenCV的視頻捕獲對象(cap)。

創(chuàng)建了一個TCP/IP套接字,綁定了指定的主機(jī)和端口,并開始監(jiān)聽傳入的連接請求。

當(dāng)有新的客戶端連接時,會啟動兩個新線程:一個用于處理發(fā)送到客戶端的數(shù)據(jù),另一個用于接收來自客戶端的命令。

主循環(huán)等待客戶端連接,并在接收到中斷信號(如KeyboardInterrupt)時優(yōu)雅地關(guān)閉所有資源。

事件機(jī)制:

使用了多個Event對象來協(xié)調(diào)不同線程之間的交互,確保了正確的順序和狀態(tài)管理。

視頻流模式:

支持一種持續(xù)發(fā)送視頻幀的“視頻流模式”,這可以通過發(fā)送特定命令開啟或關(guān)閉。

import lockzhiner_vision_module.cv2as cv2fromthreading import Thread, Eventimport socketimport osimporttimedef send_image(conn, frame): try:

# 使用imencode將圖像編碼為JPEG格式

ret, img_encode = cv2.imencode('.jpg', frame)

if not ret:

print("Failed to encode image")

return # 假設(shè)img_encode已經(jīng)是bytes類型,直接使用

data = img_encode # 發(fā)送圖像大小和圖像數(shù)據(jù)

conn.sendall(len(data).to_bytes(4, byteorder='big'))

conn.sendall(data) print("Image sent.") except (ConnectionResetError, OSError) as e:

print(f"Error sending image: {e}")defhandle_client_send(conn, start_event, shutdown_event, confirm_event, streaming_event, cap): frame_counter =0 start_time = time.time() while not shutdown_event.is_set():

if start_event.is_set() or streaming_event.is_set(): # 檢查開始或流式事件是否被設(shè)置 ret, frame = cap.read()

if ret: send_image(conn, frame) frame_counter +=1 if not streaming_event.is_set(): # 如果不是流式傳輸,則等待客戶端確認(rèn)

confirm_event.wait() # 等待客戶端確認(rèn)

confirm_event.clear() # 清除確認(rèn)事件

start_event.clear() # 圖像發(fā)送完成并且已確認(rèn)后清除事件

# 計算幀率 elapsed_time = time.time() - start_time if elapsed_time >=1: # 每一秒打印一次幀率 fps = frame_counter / elapsed_time

print(f"FPS: {fps}") # 重置計數(shù)器和時間戳

frame_counter =0

start_time = time.time()# 接收線程處理函數(shù),接收命令并根據(jù)命令執(zhí)行操作defhandle_client_receive(conn, addr, cap, start_event, shutdown_event, confirm_event, streaming_event): print(f"Connected by {addr}") try: while not shutdown_event.is_set(): try:

data = conn.recv(1024) except ConnectionResetError: print("Connection reset by peer.")

break if not data or shutdown_event.is_set(): print("Connection closed.") break command = data.decode().strip() print(f"Received command: {command}") if command =='0': ret, frame = cap.read()

if ret:

if streaming_event.is_set(): # 如果處于流式傳輸模式,則不需要設(shè)置start_event

pass else: start_event.set() # 設(shè)置開始事件以通知發(fā)送線程 elif command =='1': confirm_event.set() # 設(shè)置確認(rèn)事件 elif command =='2': shutdown_event.set()

break elif command =='3': # 開始視頻流模式 streaming_event.set() print("Video stream mode started.") elif command =='q': # 停止視頻流模式 streaming_event.clear() print("Video stream mode stopped.") else: conn.sendall("Unknown command".encode()) finally: conn.close()if __name__ =="__main__": HOST ='172.32.0.144' PORT =6810 cap = cv2.VideoCapture() # if not cap.isOpened(): if cap.open(0) is False: print("Failed to open capture")

exit(1) print("video is all ready") start_event =Event() shutdown_event =Event() confirm_event =Event() streaming_event =Event() # 新增流式傳輸事件 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((HOST, PORT)) server_socket.listen() print("Server started, waiting for connections...") try:

while not shutdown_event.is_set():

conn, addr = server_socket.accept()

client_send_thread =Thread(target=handle_client_send,

args=(conn, start_event, shutdown_event, confirm_event, streaming_event, cap))

client_receive_thread =Thread(target=handle_client_receive,

args=(conn, addr, cap, start_event, shutdown_event, confirm_event, streaming_event))

client_send_thread.start() client_receive_thread.start() except KeyboardInterrupt: print("Server interrupted.") finally:

cap.release() server_socket.close()

print("Server stopped and resources released.")

3.2 客戶端

客戶端通過TCP連接接收圖像幀,并根據(jù)命令執(zhí)行不同操作的功能。以下是代碼的詳細(xì)解釋:

客戶端功能概述

接收圖像:

receive_image(conn, timeout=5)函數(shù)用于從服務(wù)器接收圖像數(shù)據(jù)。

它首先接收表示圖像大小的4個字節(jié),然后循環(huán)接收直到收到完整的圖像數(shù)據(jù)。

接收到的數(shù)據(jù)被轉(zhuǎn)換為NumPy數(shù)組并使用OpenCV解碼成圖像格式返回。

主程序邏輯 (main函數(shù)):

'0'請求單張圖像。

'1'不做任何操作(假設(shè)用作確認(rèn)信號)。

'2'發(fā)送退出命令給服務(wù)器并終止程序。

'3'啟動視頻流模式,允許連續(xù)接收圖像幀,并將這些幀顯示出來,同時保存為本地視頻文件。

設(shè)置了服務(wù)器的IP地址(HOST)和端口(PORT),與服務(wù)端保持一致。

創(chuàng)建了一個TCP/IP套接字并嘗試連接到服務(wù)器。

根據(jù)用戶輸入的不同命令來控制視頻幀的請求和處理:

視頻流模式:

當(dāng)用戶選擇啟動視頻流模式時,客戶端會創(chuàng)建一個以當(dāng)前時間戳命名的視頻文件。

它會持續(xù)請求圖像幀并將接收到的每一幀添加到視頻文件中,同時在窗口中顯示。

用戶可以按q鍵停止視頻流模式,并保存錄制的視頻文件。

異常處理:

在關(guān)鍵位置添加了異常處理邏輯,以確保在發(fā)生錯誤時能夠適當(dāng)響應(yīng),例如網(wǎng)絡(luò)連接超時或失敗時。

資源管理:

使用with語句確保即使出現(xiàn)異常,套接字也會被正確關(guān)閉。

確保視頻寫入器在異常情況下也能夠釋放資源。

注意事項

命令同步:客戶端發(fā)送命令后,通常需要等待服務(wù)器的響應(yīng)。這里的實(shí)現(xiàn)假設(shè)服務(wù)器會在接收到命令后立即采取行動,因此客戶端緊接著就會嘗試接收圖像數(shù)據(jù)。

超時設(shè)置:對于圖像接收設(shè)置了超時參數(shù),以防止程序在無響應(yīng)的情況下卡住。

視頻編碼格式:選擇了XVID作為視頻編碼格式,這是一個常見的選擇,但并不是唯一可用的選項??梢愿鶕?jù)需要更改。

視頻保存:視頻流模式下,視頻會被保存到本地磁盤。每次開始新的視頻流都會創(chuàng)建一個新的文件名,以避免覆蓋舊文件。

代碼

importsocketimportcv2importnumpyasnpimporttimedef receive_image(conn, timeout=5): conn.settimeout(timeout) # 設(shè)置接收超時 try: data_length = int.from_bytes(conn.recv(4), byteorder='big') image_data = b'' received =0 whilereceived < data_length:? ? ? ? ? ? packet = conn.recv(min(1024, data_length - received))? ? ? ? ? ??

ifnot packet:

break image_data += packet received += len(packet) # 將接收到的數(shù)據(jù)轉(zhuǎn)換為NumPy數(shù)組,并使用OpenCV解碼為圖像

image_np = np.frombuffer(image_data, dtype=np.uint8) frame = cv2.imdecode(image_np, cv2.IMREAD_COLOR) returnframe except socket.timeout: print("Timeout waiting for image from server.") returnNone except Exceptionase: print(f"Error receiving image: {e}") returnNonedef main(): HOST ='172.32.0.144' PORT =6810# 應(yīng)與服務(wù)端使用的端口號相同 with socket.socket(socket.AF_INET, socket.SOCK_STREAM)ass: try:

s.connect((HOST, PORT)) video_writer = None # 初始化視頻寫入器為None whileTrue:

command = input("Enter command (0 to request image, 1 to do nothing, 2 to exit, 3 for video stream): ") s.sendall(command.encode()) ifcommand =='2':

s.sendall(b'2') # 發(fā)送退出命令給服務(wù)器

break elif command =='3':

print("Starting video stream mode. Press 'q' to stop.")

timestamp = int(time.time() *1000) # 毫秒級時間戳

video_filename = f"video_stream_{timestamp}.avi"

fourcc = cv2.VideoWriter_fourcc(*'XVID') # 視頻編碼格式

video_writer = None # 重置視頻寫入器

# 請求第一幀以獲取尺寸信息

s.sendall(b'0') # 請求圖像幀

frame = receive_image(s, timeout=5) # 增加超時參數(shù) ifframeisNone:

print("Failed to receive first image frame.")

continue

height, width, _ = frame.shape

video_writer = cv2.VideoWriter(video_filename, fourcc,20.0, (width, height)) # 創(chuàng)建視頻寫入器 whileTrue:

ifvideo_writerisNone:

break # 如果視頻寫入器未初始化,則跳出循環(huán)

frame = receive_image(s, timeout=1) # 對每一幀都設(shè)置較短的超時時間 ifframeisNone: print("No new frame received. Waiting...")

time.sleep(1) # 等待一段時間再嘗試重新請求

continue

cv2.imshow('Video Stream', frame)

video_writer.write(frame) # 將幀寫入視頻文件

key = cv2.waitKey(1) &0xFF

ifkey == ord('q'):

print("Stopping video stream and saving video.")

s.sendall(b'q') # 發(fā)送停止信號給服務(wù)器 break ifvideo_writerisnot None:

video_writer.release() # 關(guān)閉視頻寫入器

print(f"Video saved as {video_filename}")

cv2.destroyAllWindows() elif command =='0':

frame = receive_image(s, timeout=5) # 增加超時參數(shù)

ifframeisnot None: cv2.imshow('Received Frame', frame)

cv2.waitKey(3000) # 顯示圖像3秒后自動關(guān)閉窗口

cv2.destroyAllWindows() else:

print("No image received.") s.sendall(b'1') # 假設(shè)'1'是確認(rèn)信號 except Exceptionase: print(f"Socket error occurred: {e}") ifvideo_writerisnot None: video_writer.release() # 確保異常情況下也釋放視頻寫入器資源if__name__ =="__main__": main()

3.3 執(zhí)行結(jié)果

7fff45c0-ca50-11ef-9434-92fbcf53809c.png


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 物聯(lián)網(wǎng)
    +關(guān)注

    關(guān)注

    2909

    文章

    44726

    瀏覽量

    374374
  • 局域網(wǎng)
    +關(guān)注

    關(guān)注

    5

    文章

    757

    瀏覽量

    46308
  • AI
    AI
    +關(guān)注

    關(guān)注

    87

    文章

    31054

    瀏覽量

    269406
收藏 人收藏

    評論

    相關(guān)推薦

    邊緣AI應(yīng)用越來越普遍,AI模型邊緣如何部署?

    模型側(cè)的部署也成了業(yè)界關(guān)注的焦點(diǎn)。 ? 如何把AI 模型邊緣
    的頭像 發(fā)表于 07-04 00:11 ?2692次閱讀
    <b class='flag-5'>邊緣</b><b class='flag-5'>AI</b>應(yīng)用越來越普遍,<b class='flag-5'>AI</b><b class='flag-5'>模型</b>在<b class='flag-5'>邊緣</b><b class='flag-5'>端</b>如何<b class='flag-5'>部署</b>?

    邊緣側(cè)部署模型優(yōu)勢多!模型量化解決邊緣設(shè)備資源限制問題

    設(shè)備上,可以減少數(shù)據(jù)傳輸的延遲和帶寬需求,提高模型的實(shí)時性和響應(yīng)速度。 ? 邊緣部署
    的頭像 發(fā)表于 01-05 00:06 ?3651次閱讀

    部署邊緣設(shè)備上的輕量級模型

    電子發(fā)燒友網(wǎng)報道(文/李彎彎)邊緣AI算法是一種將人工智能(AI)算法和計算能力放置在接近數(shù)據(jù)源的終端設(shè)備中的策略。這種算法通常被部署
    的頭像 發(fā)表于 05-11 00:17 ?2623次閱讀

    AI模型部署邊緣設(shè)備奇妙之旅:如何實(shí)現(xiàn)手寫數(shù)字識別

    處理,而不必傳輸到外部服務(wù)器,這有助于更好地保護(hù)用戶隱私和數(shù)據(jù)安全。 然而,邊緣計算也帶來了獨(dú)特的挑戰(zhàn),特別是在資源受限的嵌入式系統(tǒng)中部署復(fù)雜的AI
    發(fā)表于 12-06 17:20

    AI模型部署邊緣設(shè)備奇妙之旅:如何在邊緣部署OpenCV

    的能力。 本文章主要講述如何在邊緣設(shè)備上使用OpenCV。本次使用的邊緣設(shè)備是凌智電子開發(fā)的
    發(fā)表于 12-14 09:31

    AI模型部署邊緣設(shè)備奇妙之旅:目標(biāo)檢測模型

    以及邊緣計算能力的增強(qiáng),越來越多的目標(biāo)檢測應(yīng)用開始直接在靠近數(shù)據(jù)源的邊緣設(shè)備上運(yùn)行。這不僅減少了數(shù)據(jù)傳輸延遲,保護(hù)了用戶隱私,同時也減輕了云端服務(wù)器的壓力。然而,在
    發(fā)表于 12-19 14:33

    AI模型部署邊緣設(shè)備奇妙之旅邊緣設(shè)備局域網(wǎng)視頻流傳輸方案

    1、簡介 隨著物聯(lián)網(wǎng)(IoT)和智能設(shè)備的快速發(fā)展,邊緣計算技術(shù)已成為高效數(shù)據(jù)處理和服務(wù)交付的重要組成部分。當(dāng)我們考慮利用邊緣設(shè)備進(jìn)行實(shí)時
    發(fā)表于 01-04 14:32

    EdgeBoard FZ5 邊緣AI計算盒及計算卡

    ` 隨著應(yīng)用場景的多樣化,利用人工智能技術(shù)在邊緣側(cè)部署一系列創(chuàng)新應(yīng)用解決方案,對企業(yè)傳統(tǒng)的業(yè)務(wù)形態(tài)進(jìn)行升級,加速業(yè)務(wù)增長,增強(qiáng)競爭優(yōu)勢,起著至關(guān)重要的作用。 在市場需求和產(chǎn)業(yè)趨勢的推動下,米爾
    發(fā)表于 08-31 14:12

    邊緣計算網(wǎng)關(guān)是什么 邊緣計算網(wǎng)關(guān)功能優(yōu)勢

    路由器功能,實(shí)現(xiàn)2路局域網(wǎng)接入和視頻數(shù)據(jù)的采集和上傳。支持WAN/LAN、ADSL、GPRS、4G、WIFI等滿足不同環(huán)境下對遠(yuǎn)程通信的需求?!   ?b class='flag-5'>設(shè)備遠(yuǎn)程管理、維護(hù),降低運(yùn)維成本    集GPRS
    發(fā)表于 09-10 17:24

    【HarmonyOS HiSpark AI Camera】邊緣計算安全監(jiān)控系統(tǒng)

    打火機(jī))就報警的模型,實(shí)現(xiàn)邊緣測的相關(guān)檢測和報警的業(yè)務(wù)邏輯。中期,完成傳感器數(shù)據(jù)和視頻推流到云端,實(shí)現(xiàn)遠(yuǎn)程監(jiān)控。后期,各個環(huán)節(jié)的豐富和優(yōu)化,比如多傳感器、設(shè)備接入等,組成一套較完善系統(tǒng)
    發(fā)表于 09-25 10:11

    MLU220-M.2邊緣智能加速卡支持相關(guān)資料介紹

    ??梢暂p松實(shí)現(xiàn)終端設(shè)備邊緣設(shè)備AI賦能方案。MLU220-M.2加速卡用于離線模型
    發(fā)表于 08-08 17:37

    邊緣智能市場要素:海量需求,物聯(lián)網(wǎng)切分

    設(shè)備本身,另一個則是邊云協(xié)同。 邊緣智能要求在邊緣完成數(shù)據(jù)的訓(xùn)練和推理,計算、存儲等資源的配置是一個挑戰(zhàn)。電子哨兵在邊緣的學(xué)習(xí)能力
    發(fā)表于 08-23 15:42

    嵌入式邊緣AI應(yīng)用開發(fā)指南

    保駕護(hù)航。下面讓我們來了解如何不借助手動工具或手動編程來選擇模型、隨時隨地訓(xùn)練模型并將其無縫部署到TI處理器上,從而實(shí)現(xiàn)硬件加速推理。圖1: 邊緣A
    發(fā)表于 11-03 06:53

    邊緣計算設(shè)備部署方案

    邊緣計算設(shè)備,是相對于云計算而言的。不同于云計算的中心式服務(wù),邊緣服務(wù)是指在靠近物或數(shù)據(jù)源頭的一側(cè),采用網(wǎng) 絡(luò)、計算、存儲、應(yīng)用核心能力為一體的開放平臺,就近提供最近服務(wù)。其應(yīng)用程
    發(fā)表于 05-18 15:39 ?2次下載
    <b class='flag-5'>邊緣</b>計算<b class='flag-5'>設(shè)備</b>與<b class='flag-5'>部署</b><b class='flag-5'>方案</b>

    AI邊緣計算是什么意思?邊緣ai是什么?AI邊緣計算應(yīng)用

    算法部署邊緣設(shè)備上實(shí)現(xiàn)智能化的計算方式。 什么是邊緣計算? 邊緣計算是一種通過把計算能力盡可能靠近數(shù)據(jù)來源或消費(fèi)者的計算模式,提高應(yīng)用程序
    的頭像 發(fā)表于 08-24 15:18 ?2075次閱讀