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'를 디폴트 값으로 사용하겠다는 것이다.
개인적으로는 두번째 방법이 마음에 든다.

2016년 5월 13일 금요일

[Database/SQL] MariaDB 설치 및 접속


[Database/SQL] MariaDB 설치 및 접속




Maria DB 설치 및 접속

Step 1 ) MariaDB 설치파일 다운로드

아래 링크에서 최신버전의 설치파일을 다운로드 받는다.
https://downloads.mariadb.org/
나는 MariaDB 10.1.14 Stable을 받았다.(mariadb-10.1.14-winx64.msi)

Step 2 ) MariaDB 설치

다운받은 msi 형태의 설치파일을 실행하여 설치를 진행한다.
별다른 점 없이 Next를 천천히 눌러나간다.
그러다가 중간에 root 계정의 비밀번호를 설정하라고 한다.

비밀번호를 입력해주고, 'Enable access ~'랑 'Use UTF8 ~'의 체크박스에 체크해준다. 위의 것은 원격컴퓨터에서 root계정으로 접속할 수 있게 허용하는 것이고, 아래 것은 기본 character set을 utf8로 설정하는 것이다.
다음으로 윈도우 Service의 설정으로 이름을 수정할 수 있는데 기본적으로 MySQL이라고 되어있다.
모처럼 MariaDB를 사용하니깐 수정했다. 수정 안 해도 상관없다.
TCP port 번호도 수정해도 상관없으나 나는 그대로 사용했다.


이후로 Next 누르다가 맨 마지막에 Install 누르면 설치가 진행된다.
설치 끝.

Step 3 ) HeidiSQL로 MariaDB 접속하기

아래 링크에서 HeidiSQL을 다운로드 받는다.
http://www.heidisql.com/download.php
최신버전을 다운 받는다. 나는 ‘HeidiSQL 9.3 Installer’를 다운 받았다.
설치는 그냥 Next 버튼만 누르면 된다.
설치가 완료되고 HeidiSQL을 실행하면 세션관리자 창이 뜬다.
새로 설치해서 DB에 접근하기 위한 세션이 아무것도 없으므로 세션을 새로 만든다.
왼쪽 아래에 ‘신규’ 버튼을 누른다.


unnamed라고 된 이름을 원하는 것으로 바꿔주고, 사용자 계정(사용자/암호), 포트 번호를 아까 MariaDB 설치할 때 설정한 값으로 입력한다.
열기를 누르면 MariaDB와 연결된다.