Python/2.7 for fun.

시력 테스트 자동화 스크립트 1.

qkqhxla1 2015. 6. 26. 17:16

시력 테스트 자동화 스크립트 2 : http://qkqhxla1.tistory.com/556


심심해서 재미로 만들어봤다. 

http://wvw.igame.com/eye-test/?fbs=665%7C%7CKO

이 사이트를 들어가보면 색깔 구별 테스트가 나온다.



저기에 써있는데도 다른 색깔을 고르면 된다. 가면 갈수록 난이도가 높아지고, 사람의 경우에는 눈이 좋으면 35정도까지는 간다. 이걸 자동화해보기로 했다.


처음에는 크롬 콘솔에서 자바스크립트로 입력을 처리할까.. 생각하다가 쉽고 일반적인 방법이라는 생각이 들었다. 


그래서 일부러 더 어렵게 해보려고 직접 저 부분을 캡쳐해서, 각각의 도형들로 나눈 후, RGB값을 조사해서 나머지와 다른 부분의 위치를 계산해서 그 부분을 직접 클릭하는 스크립트를 만들었다.



대부분 13초에 클릭하며, 정확도가 높아서 끝까지 갈 기세이다. 그냥 저기서 종료시켰다.


# -*- encoding: cp949 -*-
import pyscreenshot as ImageGrab
import cv2
import numpy as np
import Image
import win32api, win32con
import time
 
while True:
    time.sleep(0.1)
    im = ImageGrab.grab(bbox=(755,280,1110,635)).save('cap.png') #그림이 있는 부분을 캡쳐해서 저장한다. 내 노트북 기준으로 절대좌표라 사람마다 다를수있음.
    im = Image.open('cap.png')
    flag = False
    for i in range(im.size[1]):
        for j in range(im.size[0]):
            colors = list(im.getpixel((j,i)))
            if colors != [255,255,255]: #그림을 최대한 어둡게 만든다. 이거 안하면 정확도가 떨어진다. (밝은 그림에 대해서는 opencv가 윤곽선을 못 잡기 때문)
                if colors[0] > 100:
                    if colors[0] - 100 > 50:
                        im.putpixel((j,i),(colors[0] - 150, colors[1], colors[2])); colors[0] -= 150
                    else:
                        im.putpixel((j,i),(colors[0] - 100, colors[1], colors[2])); colors[0] -= 100
                if colors[1] > 100:
                    if colors[1] - 100 > 50:
                        im.putpixel((j,i),(colors[0], colors[1] - 150, colors[2])); colors[1] -= 150
                    else:
                        im.putpixel((j,i),(colors[0], colors[1] - 100, colors[2])); colors[1] -= 100
                if colors[2] > 100:
                    if colors[2] -100 > 50:
                        im.putpixel((j,i),(colors[0], colors[1], colors[2] - 150)); colors[2] -= 150
                    else:
                        im.putpixel((j,i),(colors[0], colors[1], colors[2] - 100)); colors[2] -= 100
    im.save('cap1.png')
 
    im = cv2.imread('cap1.png') 
    imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 
    ret,thresh = cv2.threshold(imgray,127,255,0)
    contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    color = [[0,[],0] for i in range(2)]
    for cnt in contours: 
        if cv2.contourArea(cnt) < 100000 and cv2.contourArea(cnt) > 50: #윤곽선 크기 대충 이정도인거 가져와서
            rect = cv2.minAreaRect(cnt)
            box = cv2.cv.BoxPoints(rect)
            box = np.int0(box)
            x = [box[0][0],box[0][0]]; y = [box[0][1],box[0][1]]
            for i in range(len(box)): #사각형의 두 꼭지점을 구함.
                if x[0] > box[i][0]: x[0] = box[i][0]
                elif x[1] < box[i][0]: x[1] = box[i][0]
                if y[0] > box[i][1]: y[0] = box[i][1]
                elif y[1] < box[i][1]: y[1] = box[i][1]
 
            for i in range(2): #나머지 사각형과, 나머지와 다른 사각형 구별하기위한용.
                try:
                    if color[i][0] == 0:
                        color[i][0] = Image.open('cap1.png').getpixel((x[0] + 5,y[0] + 5)) #색깔
                        color[i][1].append((x,y))
                        color[i][2] += 1 #다수결
                        break
                    elif Image.open('cap1.png').getpixel((x[0] + 5,y[0] + 5)) == color[i][0]:
                        color[i][1].append((x,y))
                        color[i][2] += 1
                        break
                except: exit(1)
            #cv2.drawContours(im,[box],0,(255,0,0),2)
            #cv2.imshow('result',im)
            #cv2.waitKey(0)
 
    print color
    for i in range(2):
        if color[i][2] > 2: #나머지들이면 흰색으로 칠함
            im = Image.open('cap1.png')
            for j in range(len(color[i][1])):
                for k in range(color[i][1][j][1][0],color[i][1][j][1][1]):
                    for l in range(color[i][1][j][0][0],color[i][1][j][0][1]):
                        im.putpixel((l,k),(255,255,255))
            im.save('cap2.png')
 
    im = Image.open('cap2.png')
    for i in range(im.size[1]):
        for j in range(im.size[0]):
            if im.getpixel((j,i)) != (255,255,255): 
                im.putpixel((j,i),(0,0,0))
    im.save('cap3.png')
 
    im = cv2.imread('cap3.png') 
    imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 
    ret,thresh = cv2.threshold(imgray,127,255,0)
    contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
     
    for cnt in contours:
        if cv2.contourArea(cnt) < 100000 and cv2.contourArea(cnt) > 500: #윤곽선을 찾음.
            rect = cv2.minAreaRect(cnt)
            box = cv2.cv.BoxPoints(rect)
            box = np.int0(box)
            pos = [box[0][0],box[0][1]]
            for i in range(len(box)):
                if pos[0] > box[i][0]: pos[0] = box[i][0]
                if pos[1] > box[i][1]: pos[1] = box[i][1]
 
    win32api.SetCursorPos((755 + pos[0] + 5,280 + pos[1] + 5)) #마우스를 opencv가 찾은 도형의 위치로 옮김. 역시 좌표는 내 노트북 기준의 절대좌표.
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0) #클릭 이벤트 발생.
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)