레이블이 [010. Python]인 게시물을 표시합니다. 모든 게시물 표시
레이블이 [010. Python]인 게시물을 표시합니다. 모든 게시물 표시

2016년 5월 19일 목요일

[Python] Python을 이용한 OpenCV에서 TCP socket을 통해서 Image 전송하기.

Python을 이용한 OpenCV에서 TCP socket을 통해서 Image 전송하기.

TCP통신만 보면 일반적인 Python의 TCP통신 기법을 이용한다.
python의 tcp socket에서는 문자열을 보내고 받을 수 있는데, 이를 따르기 위해서 OpenCV에서는 Image를 문자열(string)으로 변환할 수 있다.
즉, 이미지 송신단에서는 OpenCV를 이용해서 캡처한 Image를 문자열로 변환한 뒤 TCP Socket으로 전송(send)한다.
이미지 수신단에서는 TCP Socket으로 수신한 문자열을 OpenCV를 이용해서 Image로 변환한다.

(출처 : http://stackoverflow.com/questions/20820602/image-send-via-tcp)

client.py (송신단)

#!/usr/bin/python
import socket
import cv2
import numpy

#연결할 서버(수신단)의 ip주소와 port번호
TCP_IP = 'localhost'
TCP_PORT = 5001

#송신을 위한 socket 준비
sock = socket.socket()
sock.connect((TCP_IP, TCP_PORT))

#OpenCV를 이용해서 webcam으로 부터 이미지 추출
capture = cv2.VideoCapture(0)
ret, frame = capture.read()

#추출한 이미지를 String 형태로 변환(인코딩)시키는 과정
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),90]
result, imgencode = cv2.imencode('.jpg', frame, encode_param)
data = numpy.array(imgencode)
stringData = data.tostring()

#String 형태로 변환한 이미지를 socket을 통해서 전송
sock.send( str(len(stringData)).ljust(16));
sock.send( stringData );
sock.close()

#다시 이미지로 디코딩해서 화면에 출력. 그리고 종료
decimg=cv2.imdecode(data,1)
cv2.imshow('CLIENT',decimg)
cv2.waitKey(0)
cv2.destroyAllWindows() 

server.py (수신단)

#!/usr/bin/python
import socket
import cv2
import numpy

#socket 수신 버퍼를 읽어서 반환하는 함수
def recvall(sock, count):
    buf = b''
    while count:
        newbuf = sock.recv(count)
        if not newbuf: return None
        buf += newbuf
        count -= len(newbuf)
    return buf

#수신에 사용될 내 ip와 내 port번호
TCP_IP = 'localhost'
TCP_PORT = 5001

#TCP소켓 열고 수신 대기
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(True)
conn, addr = s.accept()

#String형의 이미지를 수신받아서 이미지로 변환 하고 화면에 출력
length = recvall(conn,16) #길이 16의 데이터를 먼저 수신하는 것은 여기에 이미지의 길이를 먼저 받아서 이미지를 받을 때 편리하려고 하는 것이다.
stringData = recvall(conn, int(length))
data = numpy.fromstring(stringData, dtype='uint8')
s.close()
decimg=cv2.imdecode(data,1)
cv2.imshow('SERVER',decimg)
cv2.waitKey(0)
cv2.destroyAllWindows() 

2016년 5월 18일 수요일

[Python] socket.close()한 port를 즉시 재사용하기.


[Python] socket.close()한 port를 즉시 재사용하기.



Python에서 socket의 setsockopt 옵션 설정하기.

기본적으로 socket을 사용하고 나면 사용한 port는 close로 닫아주는게 맞다.
그래야 해당 port를 다른데서도 사용할 수 있으니깐.
근데 port를 닫았다고해도 일정시간 동안은 TIME_WAIT 상태로 대기한다고 한다.
그리고 이 상태에서는 즉각적으로 다시 바로 사용할 수 없다.
그래서 socket을 쓰고 close를 했는데도 already in use 에러가 발생하게된다.
이런 에러를 막기위해서 setsockopt을 사용한다. 사용법은 아래와 같다.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
저렇게 가운데줄에 setsockopt함수에서 socket.SO_REUSEADDR 옵션을 설정해주면 방금 사용하고 close한 port를 즉시 다시 사용할 수 있다.

[Python]Python의 getopt 함수


[Python]Python의 getopt 함수




Python의 getopt 함수

Python에서는 getopt함수를 이용해서 command 명령에 작성하는 파라미터를 입력받을 수 있다.

사용법

간편하면서 장점인 것이, 한 줄안에서 command 명령에 사용될 옵션을 정의함과 동시에 변수에 할당하는 것이다.
예는 아래와 같다.
opts, args = getopt.getopt(argv[1:],"hi:o:",["ifile=","ofile="])
예에 따르면, 우선 변수는 opts와 args를 받는다.
opts는 옵션 이름을 선언하고 값을 적는 파라미터에 대한 값을 저장하고,
args는 옵션 이름 없이 바로 값만 적는 파라미터에 대한 값을 저장한다.
즉, --ifile 'sample.txt' 와 같이 command 명령에 적는 것은 opts에 sample.txt 문자열이 들어가고,
그냥 'test.txt' 와 같이 command 명령에 적는 것은 args에 test.txt 문자열이 들어간다는 것이다.
다음으로 getopt함수의 인자들을 보면,
첫번째 인자는 command 명령에서 입력받는 파라미터들이고,
두번째 인자는 단문자 옵션 이름이다. hi:o:라고 되어 있느면 command 명령에서는 -h -i -o 라고 쓸수 있는 것인데, i와 o에는 : 가 붙어 있다. 이는 옵션 이름만 쓰겠다는 것이 아니라 해당 옵션에 대해서 값을 입력 받겠다는 것이다.
세번째 인자는 장문자 옵션 이름이다. command 명령에서는 --ifile, --ofile 과 같이 쓰인다. 뒤에 = 가 붙어 있는 것도 옵션만 쓴다는게 아니고 값을 받겠다는 것이다.
입력받은 opts와 args를 사용하는 방법은 다음과 같다.
우선 opts는 2가지 방법이 있는데 첫번째는 아래와 같이 for문과 if문을 사용하는 방법이다.
for opt, arg in opts:
      if opt == '-h':
         print 'test.py -i <inputfile> -o <outputfile>'
         sys.exit()
      elif opt in ("-i", "--ifile"):
         inputfile = arg
      elif opt in ("-o", "--ofile"):
         outputfile = arg
opts는 (key, value)쌍으로 이루어진다. 그래서 for opt, arg in opts:는 옵션쌍을 순서대로 하나씩 확인하겠다는 것이다.
두번째 방법은 python의 dict함수를 이용하는 방법이다.
opts=dict(opts)라고 하면 opts가 dictionary구조로 바뀐다.
이렇게 하면, opts.get('-i', 'sample.txt')와 같이 사용할 수 있다. 의미는 '-i'키와 매핑되는 값을 get하겠다는 것인데, 만약 값이 없다면 'sample.txt'를 디폴트 값으로 사용하겠다는 것이다.
개인적으로는 두번째 방법이 마음에 든다.