ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TCP 소켓을 사용하여 웹캠의 이미지를 송수신하는 서버/클라이언트 예제(Python example - Send Webcam image to client over a TCP socket)
    Python/소켓(Socket) 프로그래밍 2019. 9. 30. 17:57





    파이썬의 TCP 소켓을 사용하여 웹캠에서 캡쳐한 이미지를 전송하는 서버와 클라이언트를 간단히 만들었습니다. 

    웹캠으로부터 이미지 캡쳐는 OpenCV를 사용하였습니다.


    서버에는 두 종류의 쓰레드를 생성합니다. 

    웹캠으로부터 캡처한 이미지를  큐에 삽입하는 쓰레드와 클라이언트가 접속하면 큐에서 이미지를 꺼내어 클라이언트에 전송하는 쓰레드입니다. 



    서버에서 이미지를 전송하기 전에 넘파이 배열을 압축한 후, 최종적으로   String으로 변환해야 하고

    클라이언트에서는 수신된 String 데이터를 넘파이 배열로  변환하여 화면에 보여줍니다. 



    서버 프로그램을 실행 후, 웹캠 영상이 화면에 보여지면

    클라이언트 프로그램을 실행하세요.

    여러 개 실행가능한데 몇 개 까지 가능한지 확인 안해봤습니다. 



    파이썬에서 소켓 사용하는 방법에 대해서는 다음 포스트를 참고하세요.


    파이썬 소켓 프로그래밍 - 클라이언트 / 서버 예제

    https://webnautes.tistory.com/1381 





    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




      

    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구독하기


    댓글 4

    • 이시영 2019.10.09 16:37


      안녕하세요, 혹시 소켓 통신으로 받은 frame을 저장하는 방법이 없을까요?
      현재
      fcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
      out = cv2.VideoWriter("output.avi", fcc, 25.0, (640, 480))
      을 미리 선언하고 받는 쪽의 imshow 다음에 out.write(decimg)을 한 상태인데,
      영상이 파일 생성만 되고 frame이 저장이 되진 않습니다.
      혹시 해결할 수 있는 방법이 있을까요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.09 17:19 신고


        소켓 통신으로 이미지를 전송하는 거라면 다음 포스팅을 참고해보세요.

        TCP 소켓을 사용하여 웹캠의 이미지를 송수신하는 서버/클라이언트 예제
        https://webnautes.tistory.com/1382

      • 이시영 2019.10.09 18:07


        네 해당 글을 보고 문의 드린 내용입니다! 라즈베리파이 상에서 우분투 서버로 프레임을 전송하는 것까지는 성공했지만, 프레임을 동영상으로 저장하는 걸 해보려고 합니다! 해당 글에는 저장 관련 내용은 없어서 저렇게 문의를 드렸습니다!

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.09 19:14 신고


        OpenCV에서 동영상 파일 저장하는 방법을 사용하면 됩니다.
        다음 포스트의 2번을 참고하세요

        OpenCV Python 예제 - 동영상 다루기
        https://webnautes.tistory.com/577

Designed by Tistory.