참조해서 요청을 보내주면 된다. 위의 초록그림같은경우 ;) :|~~ 등으로 보내면 되겠다. 난 이미지인식을 할 때 그림을 영어소문자로 인식했다.(해쉬값 저장하듯이) 위에 적어놨는데 :D는 a로, :)는 b로.. 이런식으로 l까지 인식했다. 나중에 우리가 알아서 다시 원래 이모티콘으로 변형해 주면 된다.
인식을 위해서 이미지를 여러번 새로고침후 12개의 이미지를 하나하나 수작업으로 복붙해서 가져왔다. 가져온 이미지.
인식을 위해 사용된 코드이다. 변경된 부분은 주석을 달았다.
확실한 판별을 위해 배경은 흰색으로, 이모티콘이나 하트가 있는 부분은 검은색으로 변경시켰다.
import Image
im = Image.open('captcha3.png')
for i in range(0,im.size[1]):
for j in range(0,im.size[0]):
if im.getpixel((j,i))[0] > 15:
im.putpixel((j,i),(255,255,255))
else:
im.putpixel((j,i),(0,0,0))
im.save('captcha3.png')
이 코드를 사용해서 이미지를 반전(?)시키고, 하나하나 순서에 맞게 수작업으로 가져왔다.
실행시키니 이런식으로 변경되어 나왔다. 이 이미지를 대상으로 트레이닝을 실시했다. (captcha3.png) 이제 아래 코드를 실행시키고 위쪽에 세로로 길게 적어놓은 표? 를 참조해서 각 얼굴에 맞는 영어를 입력한다.
#-*- coding: cp949 -*-
import sys
import numpy as np
import cv2
im = cv2.imread('captcha3.png') #트레이닝에 사용될 이미지 이름.
im3 = im.copy()
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)
thresh = cv2.adaptiveThreshold(blur,255,1,1,11,2)
################# Now finding Contours ###################
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
samples = np.empty((0,100))
responses = []
keys = [i for i in range(97,123)] #여기. 영어 소문자이기때문에 아스키코드 97~123범위로 잡았다.
for cnt in contours:
if cv2.contourArea(cnt)>10:
[x,y,w,h] = cv2.boundingRect(cnt)
#print x,y,w,h x,y는 인식한 물체의 좌표, w,h는 가로,세로의 길이를 뜻한다.
if (w==19 and h==20) or (w==17 and h==15): #인식해야할 문자는 이모티콘+하트인데, 이모티콘의 크기는
#w=19,h=20으로 고정이고, 하트는 w=17,h=15로 고정이다. 그래서 이렇게 잡았다.
cv2.rectangle(im,(x,y),(x+w,y+h),(0,0,255),2)
roi = thresh[y:y+h,x:x+w]
roismall = cv2.resize(roi,(10,10))
cv2.imshow('norm',im)
key = cv2.waitKey(0)
if key == 27: # (escape to quit)
sys.exit()
elif key in keys:
responses.append(int(key-97)) #a는 0을저장, b=1을저장... 이런식으로 변경해서 저장했다.
sample = roismall.reshape((1,100))
samples = np.append(samples,sample,0)
responses = np.array(responses,np.float32) #여기서 두번째 인자가 np.float32이기때문에 위에서 정수로 변경해서 저장해야한다. 아님 에러뜸.
responses = responses.reshape((responses.size,1))
print "training complete"
np.savetxt('generalsamples.data',samples)
np.savetxt('generalresponses.data',responses)
트레이닝이 다 끝났다. 동일한 이미지로 테스트를 해보자.
#-*- coding: cp949 -*-
import cv2
import numpy as np
####### training part ###############
samples = np.loadtxt('generalsamples.data',np.float32)
responses = np.loadtxt('generalresponses.data',np.float32)
responses = responses.reshape((responses.size,1))
model = cv2.KNearest()
model.train(samples,responses)
############################# testing part #########################
im = cv2.imread('captcha3.png') #인식 테스트를 할 사진
out = np.zeros(im.shape,np.uint8)
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)
thresh = cv2.adaptiveThreshold(blur,255,1,1,11,2)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
answer = ''
for cnt in contours:
if cv2.contourArea(cnt)>10:
[x,y,w,h] = cv2.boundingRect(cnt)
if (w==19 and h==20) or (w==17 and h==15): #h==20은 이모티콘용, h==15는 하트용
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
roi = thresh[y:y+h,x:x+w]
roismall = cv2.resize(roi,(10,10))
roismall = roismall.reshape((1,100))
roismall = np.float32(roismall)
retval, results, neigh_resp, dists = model.find_nearest(roismall, k = 1)
string = str(chr(int((results[0][0]))+97)) #다시 복호화하는부분 내가 알아서 바꿈.
answer += string #답에 더함.
cv2.putText(out,string,(x,y+h),0,1,(0,255,0))
cv2.imshow('im',im)
cv2.imshow('out',out)
cv2.waitKey(0)
print answer
이걸 실행하면
abcdefghijkl로 잘 인식을 한다!! 그런데 문제가 있었다. 저 abcd답이 나오면 바로 그냥 문자열 변수 answer에 넣게 해놨는데, 하트의 크기가 조금 달라서 그런지 순서대로 인식하지 않는 경우가 있다.
위에 보이는건 abcdefghijkl이지만 answer에 넣을때는 cdefgab~이렇게 순서가 뒤죽박죽할수도 있다는
소리이다. 이걸 대비해서 난 리스트를 만들어서 x좌표와 저 문자를 같이 넣은 후, x좌표대로 정렬해서 문자를 뽑아오는 알고리즘으로 문제를 해결했다. 테스트까지 완료했으니 다음에는 문제를 풀어보겠다.