machine learning, image

WeChall Crackcha 관련 삽질.

qkqhxla1 2015. 7. 11. 14:02

취미삼아 opencv를 공부하고 있지만 취미로 공부하게 만든 문제중에 하나가 이 Crackcha이다.

문제는 이렇다.

이러한 캡챠를 인식해서 30분안에 468개의 캡챠를 맞게 인증하면 된다. 틀려도 리셋되지 않지만 상당히 어렵다. 30분안에 468개이면 최소 3~4초내에 1개씩 인증해야 하는데.. 프로그래밍적으로 한다고 해도


다운로드 받고, 이미지 연산하고, 보내기까지 최소 2.x초는 걸린다. 즉 인식률을 최소 60%이상으로 끌어올려야 문제를 풀 수 있다는건데... 코딩의 마지막 문제인만큼 상당히 어렵다.


일단 현재까지 한 삽질을 올리겠다.

image denosing : http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_photo/py_non_local_means/py_non_local_means.html


ocr of hand-written data with knn : http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_ml/py_knn/py_knn_opencv/py_knn_opencv.html?highlight=hand


thresholding : http://opencvpython.blogspot.kr/2013/05/thresholding.html


1. 이미지에서 잡음을 없앤다.(denosing)

2. 쓰레스홀딩(thresholding)을 이용해서 이미지를 극단적으로 분류한다. 근데 말이 극단적이지 분류를 상당히 괜찮게 잘 하는것같다.


분류 결과.




나름 엄청나게 잘 분류된거같은데 좀 케바케다. 흐린 경우에는 중간의 글자가 아예 사라져 버리기도 한다. 

3. 글자들을 5글자로 나눠서 저장한다. 

4. 이렇게 분류된걸 내가 여태까지 모아온 알파벳 이미지를 이용해서 kNN알고리즘으로 분류한다.


여태까지 모아온 이미지. (kNN에 사용될 트레이닝용 이미지.)


하. 위 이미지를 모으느라 몇일 걸린것 같다.(일일히 수작업함.) 프로그래밍에 입문하고 나서 최악의 삽질이었던것 같다. 이렇게 삽질을 했는데 여튼 인식률은 30~40%정도 되는것같다. (한숨밖에 안나옴.)


인식률 40%도 글자가 잘 살아있을때의 이야기지, 한글자가 지워지기라도 하면 그냥 바로 실패이다. 결국 총 인식률을 계산해보면 10%정도밖에 안나오는듯.... 여기서 어떻게 더 인식률을 높여야될것 같긴 한데, 영상처리를 전문적으로 공부해보지 않아서 뭘 어떻게해야될지 모르겠다.


어제 학교 도서관에 책을 빌리러 가면서 패턴인식에 관한 책을 찾아봤었는데, 코딩은 없고 너무 수학적인 이론에만 치중되있었다. 이론적인게 중요하니 그런 원리를 써놓는게 맞긴 한데 일단 코딩으로 뭔가 구현해보고 원리를 보는 나에겐 맞지 않다. 시간을 많이 쏟아야 할것 같아서 책 빌려오는걸 그냥 포기했다. 책 빌려오는거 포기하면서 문제푸는것도 그냥 미뤄두기로 했다.


쓰다만 소스.

# -*- encoding: cp949 -*-
import numpy as np
import cv2
import Image
import urllib2
import time

session = 'WC=8536412-13590-HQZoQnmG1JUlJmYm'

def download_photo(filename):
    file_path = "%s%s" % ("C:\\Users\\Ko\\Documents\\Visual Studio 2012\\Projects\\PythonApplication37\\", filename)
    downloaded_image = file(file_path, "wb")
       
    req = urllib2.Request('http://www.wechall.net/challenge/crackcha/problem.php')
    req.add_header('Cookie',session)
    image_on_web = urllib2.urlopen(req)
    while True:
        buf = image_on_web.read()
        if len(buf) == 0:
            break
        downloaded_image.write(buf)
    downloaded_image.close()
    image_on_web.close()
    return file_path


img = cv2.imread('train.png',0)#img = cv2.imread('digits.png')
cells = [np.hsplit(row,50) for row in np.vsplit(img,26)]
x = np.array(cells)

train = x[:,:50].reshape(-1,1600).astype(np.float32) #train = x[:,:50].reshape(2500,400).astype(np.float32) # Size = (2500,400)
k = np.arange(26)#k = np.arange(10)
train_labels = np.repeat(k,50)[:,np.newaxis]

download_photo('problem.png')
my_size = 1
im = Image.open('problem.png')
im.resize((im.size[0] * my_size,im.size[1] * my_size)).save('problem1.png')
im = Image.open('problem1.png')
im.resize((200,40)).save('problem1.png')

img = cv2.imread('problem1.png',0)
dst = cv2.fastNlMeansDenoising(img,10,30,2,100)
kernel = np.ones((2,2),np.uint8)
o = cv2.morphologyEx(dst, cv2.MORPH_OPEN, kernel)
cv2.imwrite('problem2.png',o)

img = cv2.imread('problem2.png',0)
ret,thresh1 = cv2.threshold(img,120,255,cv2.THRESH_BINARY)
cv2.imwrite('problem3.png',thresh1)

im = Image.open('problem3.png')
x_index = 0
answer = ''
for i in range(5):
    im.crop((x_index, 0, x_index + 40, 40)).save('problem3%d.png' %i)
    x_index += 40
    prob = cv2.imread('problem3%d.png' %i,0)
    prob_x = np.array(prob)
    prob_test = prob_x.reshape(-1,1600).astype(np.float32)

    knn = cv2.KNearest()
    knn.train(train,train_labels)
    ret,result,neighbours,dist = knn.find_nearest(prob_test,k=3)

    answer += chr(int(ret)+65)
print answer
cv2.imshow('answer',cv2.imread('problem3.png',0))
cv2.waitKey(0)