MAC 사용
brew install tesseract
pip install pytesseract
Step1. 이미지 읽어와서 가장자리 탐색
1. 일반적인 경우
from tkinter import Image
import cv2
from cv2 import imshow
import numpy as np
def Imgcontour():
img = cv2.imread('img.jpg', cv2.IMREAD_COLOR)
GRAY = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edge = cv2.Canny(GRAY, 100,200)
contours , hierarchy = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
### 이진화된 이미지만 넘겨줘야 함
cv2.imshow("Edge", edge)
cv2.drawContours(img, contours, -1, (0,255,0), 1)
cv2.imshow("Contours", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
Imgcontour()
2. 찍고자하는 명함 또는 문서가 구겨진 경우 도형을 근사화 하는 방법
from tkinter import Image
import cv2
from cv2 import imshow
import numpy as np
def Imgcontour():
img = cv2.imread('img.jpeg', cv2.IMREAD_COLOR)
copy_img = img.copy()
copy_img_1 = img.copy()
GRAY = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edge = cv2.Canny(GRAY, 100,200)
contours , hierarchy = cv2.findContours(edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Cnt = contours[0]
cv2.drawContours(img, [Cnt],0 , (0,255,0), 2)
cv2.drawContours(copy_img_1, contours[1],0 ,(0,255,0), 2)
epsilon = 0.1 * cv2.arcLength(Cnt, True)
### contour의 둘레의 길이를 확인하고 , 폐곡선 여부 확인 후 근사정확도(10퍼센트) 작을 수록 원본과 비슷함
approx = cv2.approxPolyDP(Cnt, epsilon, True)
cv2.drawContours(copy_img, [approx],0 , (0,255,0), 2)
cv2.imshow("edge", edge)
cv2.imshow("img", img)
cv2.imshow("copy_img", copy_img)
cv2.imshow("copy_img_1", copy_img_1)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
Imgcontour()
Step2. 탐색한 가장자리를 이용하여 투영변환
자동으로 좌표 구하는 방법을 찾아야 한다..
import cv2
from cv2 import warpPerspective
import numpy as np
def wrapPerspective():
img = cv2.imread('ocr.jpeg')
TL = [100,200]
TR = [200,300]
BL = [300,400]
BR = [200,400]
pts1 = np.float32( [TL, TR, BL, BR])
w1 = abs(BL[0] - BR[0])
w2 = abs(TR[0] - TL[0])
h1 = abs(TR[0] - BR[0])
h2 = abs(TL[0] - BL[0])
min_w = min([w1,w2]) ## 최소 너비
min_h = min([h1,h2]) ## 최소 높이
pts2 = np.float32([[0,0], [min_w-1,0],
[min_w-1, min_h-1], [0,min_h-1]])
M = cv2.getPerspectiveTransform(pts1, pts2)
result = warpPerspective(img, M, (int(min_w), int(min_h)))
cv2.imshow("OG img", img)
cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
wrapPerspective()
Step3. 이진화를 이용하여 조명값 제거
import cv2
def adaptive_threshold():
img = cv2.imread('img.jpeg', cv2.IMREAD_GRAYSCALE)
blur = cv2.GaussianBlur(img, (7,7), 0)
result_without_blur = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 21,10)
result_with_blur = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 21,10)
cv2.imshow('Without Blur', result_without_blur)
cv2.imshow('With Blur', result_with_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
adaptive_threshold()
Step4. 합치기
1. 가장자리 검출
import cv2
img = cv2.imread('img.jpeg')
og_img = img.copy()
GRAY = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
GRAY = cv2.GaussianBlur(GRAY, (3,3), 0)
edged = cv2.Canny(GRAY, 75,200)
cv2.imshow("IMG", img)
cv2.imshow("EDGED", edged)
cv2.waitKey(0)
cv2.destroyAllWindows()
2. 검출된 가장자리를 이용하여 외곽 찾기
from pickle import TRUE
import cv2
img = cv2.imread('img.jpeg')
ratio = 800.0/img.shape[0]
dim = (int(img.shape[1] * ratio), 800)
img = cv2.resize(img, dim, interpolation= cv2.INTER_AREA)
og_img = img.copy()
GRAY = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
GRAY = cv2.GaussianBlur(GRAY, (5,5), 0)
edged = cv2.Canny(GRAY, 50,200)
cnts, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key =cv2.contourArea, reverse= True)[:5]
## 반환받은 cnt중 면적인 큰 순서대로 5번까지 반환
for c in cnts:
## 순차적으로 탐색
peri = cv2.arcLength(c, True)
## 컨투어의 길이를 반환
approx = cv2.approxPolyDP(c, 0.03 * peri, True)
## 길이의 오차 2퍼센트로 도형을 근사화
if len(approx) == 4:
## 근사화한 도형의 꼭지점이 4개라면 그것이 문서의 외곽
screenCnt = approx
break
cv2.drawContours(img, [screenCnt], -1, (0,255,0), 2)
cv2.imshow("IMG", img)
cv2.imshow("edged", edged)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 네 개의 꼭지점을 이용하여 투영변환
import numpy as np
import cv2
def order_points(pts):
rect = np.zeros((4, 2), dtype="float32")
s = pts.sum(axis=1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
diff = np.diff(pts, axis=1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect
def four_point_transform(image, pts):
rect = order_points(pts)
(tl, tr, br, bl) = rect
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
maxWidth = max(int(widthA), int(widthB))
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxHeight = max(int(heightA), int(heightB))
dst = np.array([
[0, 0],
[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],
[0, maxHeight - 1]], dtype="float32")
M = cv2.getPerspectiveTransform(rect, dst)
warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
return warped
img = cv2.imread('ocr.jpeg')
ratio = 800.0/img.shape[0]
dim = (int(img.shape[1] * ratio), 800)
img = cv2.resize(img, dim, interpolation= cv2.INTER_AREA)
og_img = img.copy()
GRAY = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
GRAY = cv2.GaussianBlur(GRAY, (3,3), 0)
edged = cv2.Canny(GRAY, 70,200)
cnts, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key =cv2.contourArea, reverse= True)[:5]
## 반환받은 cnt중 면적인 큰 순서대로 5번까지 반환
check = False
for c in cnts:
## 순차적으로 탐색
peri = cv2.arcLength(c, True)
## 컨투어의 길이를 반환
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
## 길이의 오차 2퍼센트로 도형을 근사화
if len(approx) == 4:
## 근사화한 도형의 꼭지점이 4개라면 그것이 문서의 외곽
screenCnt = approx
check = True
break
if check == False:
cv2.imshow("IMG", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.drawContours(img, [screenCnt], -1, (0,255,0), 2)
warped = four_point_transform(og_img, screenCnt.reshape(4, 2))
cv2.imshow("IMG", img)
cv2.imshow("warped", warped)
cv2.waitKey(0)
cv2.destroyAllWindows()