파이썬의 TCP 소켓을 사용하여 웹캠에서 캡쳐한 이미지를 전송하는 서버와 클라이언트를 간단히 만들었습니다.
웹캠으로부터 이미지 캡쳐는 OpenCV를 사용하였습니다.
서버에는 두 종류의 쓰레드를 생성합니다.
웹캠으로부터 캡처한 이미지를 큐에 삽입하는 쓰레드와 클라이언트가 접속하면 큐에서 이미지를 꺼내어 클라이언트에 전송하는 쓰레드입니다.
서버에서 이미지를 전송하기 전에 넘파이 배열을 압축한 후, 최종적으로 String으로 변환해야 하고
클라이언트에서는 수신된 String 데이터를 넘파이 배열로 변환하여 화면에 보여줍니다.
서버 프로그램을 실행 후, 웹캠 영상이 화면에 보여지면
클라이언트 프로그램을 실행하세요.
여러 개 실행가능한데 몇 개 까지 가능한지 확인 안해봤습니다.
파이썬에서 소켓 사용하는 방법에 대해서는 다음 포스트를 참고하세요.
image-server.py
파이썬의 recv 함수는 수신될 데이터의 크기를 미리 알아야 하기 때문에 서버에서 전송할 이미지의 크기를 보내서 클라이언트에서 수신받을 준비를 하게 해놓고 이미지를 전송합니다.
import socket import cv2 import numpy from queue import Queue from _thread import *
enclosure_queue = Queue()
# 쓰레드 함수 def threaded(client_socket, addr, queue):
print('Connected by :', addr[0], ':', addr[1])
while True:
try: data = client_socket.recv(1024)
if not data: print('Disconnected by ' + addr[0],':',addr[1]) break
stringData = queue.get() client_socket.send(str(len(stringData)).ljust(16).encode()) client_socket.send(stringData)
except ConnectionResetError as e:
print('Disconnected by ' + addr[0],':',addr[1]) break client_socket.close()
def webcam(queue):
capture = cv2.VideoCapture(0)
while True: ret, frame = capture.read()
if ret == False: continue
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),90] result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = numpy.array(imgencode) stringData = data.tostring()
queue.put(stringData)
cv2.imshow('image', frame) key = cv2.waitKey(1) if key == 27: break
HOST = '127.0.0.1' PORT = 9999
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind((HOST, PORT)) server_socket.listen()
print('server start')
start_new_thread(webcam, (enclosure_queue,))
while True:
print('wait')
client_socket, addr = server_socket.accept() start_new_thread(threaded, (client_socket, addr, enclosure_queue,))
server_socket.close()
|
image-client.py
import socket import numpy as np import cv2
def recvall(sock, count): buf = b'' while count: newbuf = sock.recv(count) if not newbuf: return None buf += newbuf count -= len(newbuf) return buf
HOST = '127.0.0.1' PORT = 9999
client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))
while True:
message = '1' client_socket.send(message.encode()) length = recvall(client_socket,16) stringData = recvall(client_socket, int(length)) data = np.frombuffer(stringData, dtype='uint8')
decimg=cv2.imdecode(data,1) cv2.imshow('Image',decimg) key = cv2.waitKey(1) if key == 27: break
client_socket.close()
|
참고
https://stackoverflow.com/questions/20820602/image-send-via-tcp
https://pymotw.com/3/queue/index.html
안녕하세요, 혹시 소켓 통신으로 받은 frame을 저장하는 방법이 없을까요?
현재
fcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
out = cv2.VideoWriter("output.avi", fcc, 25.0, (640, 480))
을 미리 선언하고 받는 쪽의 imshow 다음에 out.write(decimg)을 한 상태인데,
영상이 파일 생성만 되고 frame이 저장이 되진 않습니다.
혹시 해결할 수 있는 방법이 있을까요?