국비지원교육/Python
opencv - 2 그리고 사진에서 텍스트 추출
HanJW96
2024. 5. 10. 13:03
오늘은 사진 읽어서 색상 톤 변경, 동영상 경계만 뽑아서 파일로 저장.
간판에서 글자 뽑아서 db에 넣기, 프로젝트 .exe파일로 변환하기를 했다.
이렇게 쓰고보니 엄청 많은듯
별 다른건 없었고 오류났던거 몇 개
1.
왜인지는 모르겠지만 인식을 못한다
스택오버플로우에서 python-opencv 를 낮은버전으로 재설치를하면 된다고해서 그렇게도 해봤는데 확실히 오류가 사라지긴한다. 근데 버전을 안낮추고 오류난채로 구동해도 문제없이 구동이 되기때문에 신경안써도 될듯
2.
환경변수 설정 다했는데도 tesseract를 인식을 못해서, 스택오버플로우에서 알려준 코드를 메인에서 가장 먼저 실행하니 해결. 아마 강제로 위치를 알려주는 코드인듯
사진에서 텍스트 뽑는 코드는 대충 사진을 흑백으로 바꾸고 명암비교해서 글자로 바꾸는듯 하다 .
어떤 원리인지는 취직하고 만약 AI쪽 배울일이 생기면 그때 자세히 고민해보는걸로
# camera_save.py
# 카메라를 통해 들어오는 영상 프레임을 저장 처리
import cv2
import sys
# 시스템 기본 카메라를 cv2.VideoCapture 객체로 생성
cap = cv2.VideoCapture(0) # 카메라 열기함
if not cap.isOpened(): # 카메라 열기가 실패했다면
print('Camera is not opened')
sys.exit()
# 프레임 해상도, 초당 프레임수(fps)
print('Frame width : ', round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)))
print('Frame height : ', round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
print('FPS : ', round(cap.get(cv2.CAP_PROP_FPS)))
# 동영상 저장을 위한 cv2.VideoWriter 객체 생성
fw = round(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
fh = round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = round(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc(*'DIVX') # * 'DIVX' == 'D', 'I', 'V', 'X'
out = cv2.VideoWriter('./multi/output.avi', fourcc, fps, (fw, fh))
# 매 프레임 처리 및 화면 출력, 동영상 저장 처리
while True:
ret, frame = cap.read() # 카메라는 한곳에만 작동 ! 다른앱에서 카메라 실행중이지 않도록 주의
# ret : 읽기 성공 여부, frame : 프레임정보
if not ret:
break
edgeOrigin = cv2.Canny(frame, 50, 150) # 경계선 검출 함수
edge = cv2.cvtColor(edgeOrigin, cv2.COLOR_GRAY2BGR)
# out.write(edge) # 파일로 저장
out.write(frame)
cv2.imshow('frame', frame)
cv2.imshow('edge', edge)
if cv2.waitKey(1) == 27: # esc 키
break
# while end -------------------------------------------------
cap.release()
out.release()
cv2.destroyAllWindows()
2. tesseract
# sign.py
import numpy as np
import cv2
import sys
import pytesseract
import common.dbConnectTemplate as dbtemp
def reorderPts(pts):
idx = np.lexsort((pts[:, 1], pts[:, 0])) # 컬럼 0 -> 컬럼 1 순으로 정렬한 인덱스를 반환
pts = pts[idx] # x좌표로 정렬
if pts[0, 1] > pts[1, 1]:
pts[[0, 1]] = pts[[1, 0]]
if pts[2, 1] < pts[3, 1]:
pts[[2, 3]] = pts[[3, 2]]
return pts
def camerain():
filenames = ['./images/sample01.jpg', './images/sample02.jpg', './images/sample03.jpg']
data_list = []
for filename in filenames:
print(f'파일이름 : {filename}')
src = cv2.imread(filename)
if src is None:
print('image load failed')
sys.exit()
# 출력 영상 설정
dh, dw = src.shape[:2]
srcQuad = np.array([[0, 0], [0, 0], [0, 0], [0, 0]], np.float32)
dstQuad = np.array([[0, 0], [0, dh], [dw, dh], [dw, 0]], np.float32)
dst = np.zeros((dh, dw), np.uint8)
# 입력 영상 전처리
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
th, src_bin = cv2.threshold(src_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# 외곽선 검출 및 명함 검출
contours, _ = cv2.findContours(src_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for pts in contours:
# 너무 작은 객체는 제외
if cv2.contourArea(pts) < 10:
continue
# 외곽선 근사화 : 0.02의 오차범위 지정
approx = cv2.approxPolyDP(pts, cv2.arcLength(pts, True) * 0.02, True)
print('approx : ', len(approx))
# 컨벡스(닫혀진 다각형)가 아니고, 사각형이 아니면 제외
if not cv2.isContourConvex(approx) or len(approx) != 4:
continue
# 골라낸 컨벡스에 테두리 그리기(다각형 도형 그리기)
cv2.polylines(src, [approx], True, (0, 255, 0), 2, cv2.LINE_AA)
srcQuad = reorderPts(approx.reshape(4, 2).astype(np.float32))
# 명함 이미지 사각형 이미지 만들기
pers = cv2.getPerspectiveTransform(srcQuad, dstQuad)
dst = cv2.warpPerspective(src, pers, (dw, dh), flags=cv2.INTER_CUBIC)
dst_rgb = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)
result = pytesseract.image_to_string(dst_rgb, lang='Hangul+eng')
print('result : ', result)
cv2.waitKey()
cv2.destroyAllWindows()
list = [item for item in result.split('\n') if item != ""]
print('list : ', list)
data = {}
for i in range(len(list)):
if i == len(list) - 1:
data['phone'] = list[i]
elif 'name' not in data:
data['name'] = list[i]
else:
data['name'] = data['name'] + list[i]
print(f'data : {data}')
data_list.append(data)
print(f'data_list : {data_list}')
outputDB(data_list)
def outputDB(data_list):
# 결과 DB에 저장
# vision 테이블 비우기
delete_query = 'delete from vision'
conn = dbtemp.connect()
cursor = conn.cursor()
try:
cursor.execute(delete_query)
dbtemp.commit(conn)
print(f'vision 테이블 데이터 삭제 성공')
except:
dbtemp.rollback(conn)
print(f'vision 테이블 데이터 삭제 실패')
finally:
cursor.close()
dbtemp.close(conn)
# DB 삽입 쿼리
insert_query = 'insert into vision values (:1, :2)'
for data in data_list:
conn = dbtemp.connect()
cursor = conn.cursor()
tp_data = (data.get('name'), data.get('phone'))
print(f'{ data.get("name") } 데이터 삽입 중')
try:
cursor.execute(insert_query, tp_data)
dbtemp.commit(conn)
print(f'{ data.get("name") } 데이터 삽입 성공')
except:
dbtemp.rollback(conn)
print(f'{data.get("name")} 데이터 삽입 실패')
finally:
cursor.close()
dbtemp.close(conn)
if __name__ == '__main__':
dbtemp.oracle_init() # 딱 한번만 실행
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
camerain()