본문 바로가기

Theory/DeepLearning

Python에서 OpenCV를 통해 내가 손으로 쓴 숫자 영역 확인하기

어떻게 사는게 좋을까? 어떤 선택을 하는 것이 최선일까?를 난데없이 문득 고민하는 하루입니다. 별로 고민없이 물 흐르는데로 사는 것이 인생이라 생각하고, 오직 즐거움(^^)만을 따라다녔는데... 뭔가 요즘 선택을 계속 고민하게 되네요.ㅠㅠ. 이럴때는 일하다말고, 잠시 블로깅하는 것이 정신건강에 좋죠^^. 얼마전에 이때까지 10년 블로그 생활중에 처음으로 OpenCV라는 아이를 이용해서, Python으로 OpenCV를 이용해서 사람의 얼굴이나 몸을 인식하는 것을 haarcascade를 이용해서 연습했는데요. 이번에는 내가 직접 쓴 숫자에서 숫자 하나하나가 위치하는 영역을 인식하고 싶네요^^. 어떻게하면 좋을까요^^. 정답은?? 구글이죠^^ 아무튼.. 그 연습을 시작해볼께요...

아... 이겁니다. 이 손글씨에서 숫자가 위치한 영역을 찾고 싶은거죠. 잠깐.. 인식은 안해요.. 왜냐구요? 다음 글에서 할 거거든요^^ 위 그림파일 이름이 300.jpg입니다. 그래서 위 그림을

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

img = cv2.imread("./300.jpg")

plt.figure(figsize=(15,12))
plt.imshow(img);

로 읽어들이는 거구요...

이렇죠... 문제는 제가 연습장에 쓰고, 폰으로 찍었는데... 저의 노예계약이 무려 1년반이나 남은 On7 폰이 물속으로 낙하하신 후에... 카메라 성능이 저렇게 되었습니다. 테두리에 이상한 음영이ㅠㅠ. 저거 좀 있다 좀 골치아프겠어요ㅠㅠ.

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.figure(figsize=(15,12))
plt.imshow(img_gray);

아무튼... cvtColor명령으로 GRAY로 바꾸면...

흠... 아바타 분위기라고 지적(^^) 당했지만.. 전 그냥 저 상태로 감상하는게 좋습니다. 아직은 OpenCV 초심자이니까요 ㅎㅎㅎ^^ OpenCV 학습 속도가 잘 붙는 아이인것 같습니다.^^

img_blur = cv2.GaussianBlur(img_gray, (5, 5), 0)
plt.figure(figsize=(15,12))
plt.imshow(img_blur);

그리고, 가우시안블러~~~를 살짝 씌워서....

위에 필기도구나 저의 거지같은(^^) 카메라때문에 끊어진 듯 보이는 이어진 선이 부드럽게 연결된듯 보입니다.

ret, img_th = cv2.threshold(img_blur, 100, 230, cv2.THRESH_BINARY_INV)

image, contours, hierachy= cv2.findContours(img_th.copy(), 
                                 cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

rects = [cv2.boundingRect(each) for each in contours]
rects

이제... 적당한 threshold 값을 찾아서 - 정말 찾아야하더군요.ㅠㅠ. 코드를 몇번 돌려봤는지ㅠㅠ. 아무튼... 그렇게 찾아서.. 이쁘게 사각영역을 얻어~~~

얻었는줄 알았는데...12개 숫자인데... 이상하게.. 너무 많은 영역이 나옵니다. 이 다음 코드를 생략하고, 끝까지 진행하면, 몹쓸 카메라로 인해 만들어진 가운데 원의 경계선에 작은 상자들이 만들어집니다.ㅠㅠ. 그래서 잔꽤를....

tmp = [w*h for (x,y,w,h) in rects]
tmp.sort()
tmp

구한 height와 weight를 이용해서 넓이를 보는거죠. 그래서 결과를 보면

제일 큰 아이 두개를 빼고, 나머지의 넓이를 찾을 수 있습니다. 그래서 넓이값으로 다시 한 번 더 걸러주는거죠...

rects = [(x,y,w,h) for (x,y,w,h) in rects if ((w*h>15000)and(w*h<500000))]
rects

뭐 이번 경우만 사용할 수 있지만... 일단 전 연습생(^^)이니까요... 그리고 이딴 블로그에 설마.. 죽자고 위 방식의 문제를 걸고 넘어지실 분은 없으리라 보고... (더 좋은 방법을 알려주시는건 정말 감사합니다.^^)

이제 상자 12개가 나왔네요^^

for rect in rects:
    # Draw the rectangles
    cv2.rectangle(img, (rect[0], rect[1]), 
                  (rect[0] + rect[2], rect[1] + rect[3]), (0, 255, 0), 5) 

plt.figure(figsize=(15,12))
plt.imshow(img);

ㅋㅋ 저렇게 기존의 img에 상자를 넣어줍니다. 끝끝끝~~

짠.... 다음엔 뭐할까요???? ㅎㅎ 아마 제가 최근 MNIST데이터 셋으로 CNN을 케라스로 돌렸다는 둥 , 그때 학습한 모델을 저장했다가, 자기 손글씨를 확인하는데 사용했는데.. 그때 이미지의 크기 28*28에 맞추느라 약간 삽질했다는 둥의 이야기를 기억하신다면, 그 와중에 난데없이 갑자기 OpenCV로 가서는 사람 얼굴 영역 찾기 놀이를 했다는 것도 기억하신다면~^^ 넵.. 짐작하신데로 입니다. 다음 과정은 저렇게 찾은 각각의 이미지를 28*28로 크기를 바꾸고, 그걸 이미 학습해둔 CNN 모델에 돌려주고, 그 결과를 다시 저 이미지에 마킹하겠다는거죠.. ㅋㅋㅋ 요즘 조금씩 블로그할 시간이 안나서 그걸 또 언제할지 모른다는것이 함정~~~^^입니다.

반응형