Send Frame Detected from Webcam with Python Sockets

61 views Asked by At

I'll send the frame detected from webcam to another device. This device will check the objects with YOLOv5 and it will send how many objects are there to device with camera. I started with send image to another device but I have some problems with Python sockets.

Server Code :

import socket
import cv2
import io
import numpy as np
from PIL import Image

HOST = "127.0.0.1" 
PORT = 65432

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
print(f"Connected by {addr}")

camera = cv2.VideoCapture(0)

while True:
    ret, frame = camera.read()
    frame = cv2.resize(frame, (640, 480))
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    frame = Image.fromarray(frame)
    frame_bytes = io.BytesIO()
    frame.save(frame_bytes, format="JPEG")
    frame_bytes = frame_bytes.getvalue()
    conn.sendall(frame_bytes)
    data = conn.recv(4096)
    print(data)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

Client Code :

import socket
import time
import cv2
import io
import numpy as np
from PIL import Image
import random

HOST = "127.0.0.1" 
PORT = 65432 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

while True:
    data = s.recv(8192)
    frame = Image.open(io.BytesIO(data))
    frame = np.array(frame)
    frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
    cv2.imshow("frame", frame)
    cv2.waitKey(1)
    s.sendall(b"OK")

When I ran this codes, client.py returns a error :

Traceback (most recent call last):
  File "C:\Users\ASUS\Desktop\test\client.py", line 18, in <module>
    frame = np.array(frame)
            ^^^^^^^^^^^^^^^
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\Image.py", line 696, in __array_interface__
    new["data"] = self.tobytes()
                  ^^^^^^^^^^^^^^
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\Image.py", line 754, in tobytes
    self.load()
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\ImageFile.py", line 266, in load
    raise OSError(msg)
OSError: image file is truncated (31 bytes not processed)
PS C:\Users\ASUS\Desktop\test> python client.py
Traceback (most recent call last):
  File "C:\Users\ASUS\Desktop\test\client.py", line 18, in <module>
    frame = np.array(frame)
            ^^^^^^^^^^^^^^^
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\Image.py", line 696, in __array_interface__
    new["data"] = self.tobytes()
                  ^^^^^^^^^^^^^^
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\Image.py", line 754, in tobytes
    self.load()
  File "C:\Users\ASUS\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\ImageFile.py", line 266, in load
    raise OSError(msg)
OSError: image file is truncated (35 bytes not processed)

I tried change recv buffer size, but I can't solve my problem.

1

There are 1 answers

0
Emir Ünalan On

I solved the problem with TLV scheme.

Client code :

import io
import cv2
import socket
import struct
import time
import numpy as np
from PIL import Image

cl_socket = socket.socket()
cl_socket.connect(('127.0.0.1', 8000))
connection = cl_socket.makefile('wb')

try:
    camera = cv2.VideoCapture(0)
    stream = io.BytesIO()
    
    while True:
        ret, frame = camera.read()
        frame = cv2.resize(frame, (640, 480))
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        frame = Image.fromarray(frame)
        frame.save(stream, format="JPEG")
        stream.seek(0)
        image_bytes = stream.read()
        connection.write(struct.pack('<L', len(image_bytes))) 
        connection.flush()
        stream.seek(0)
        connection.write(stream.read())
        stream.seek(0)
        stream.truncate()   
    connection.write(struct.pack('<L', 0))
        
finally:
    connection.close()
    cl_socket.close()

Server Code:

import cv2
import io
import socket
import struct
from PIL import Image
import numpy as np

server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen(0)

connection = server_socket.accept()[0].makefile('rb')

try:
    img = None
    while True:
        image_len = struct.unpack('<L', connection.read(struct.calcsize('<L')))[0]
        if not image_len:
            break
        image_stream = io.BytesIO()
        image_stream.write(connection.read(image_len))
        image_stream.seek(0)
        image = Image.open(image_stream).convert('RGB')
        image = np.array(image)
        cv2.imshow('Image', cv2.cvtColor(image, cv2.COLOR_RGB2BGR))
        cv2.waitKey(1)  

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
finally:
    connection.close()
    server_socket.close()