아이디어)
전체 이미지에서 윗단과 아랫단을 제거 한 후 (문제영역만 남김)
페이지를 왼쪽부분과 오른쪽 부분으로 나눈 후
(1)글에서와 유사하게 진행하면서 kernel사이즈의 x size를 충분히 키우면 검출해 낼 수 있을 것
1. 이미지 tirm : imtrim함수
#수능완성 page trim
def imtrim(page):
x=300
w=1120
left = page[465:3450, x:x+w]
x=1480
right = page[465:3450,x:x+w]
return right,left
아랫단과 윗단을 제거한 후 페이지를 오른쪽 부분과 왼쪽 부분으로 나눔
그 후 right, left라는 변수에 저장한 후 return함
결과)
2. 이미지 전처리 + 외곽추출 + 일반화 : contour함수
#반페이지를 입력받고 크롭하기
def contour(page_rl):
#이미지 흑백화
imgray = cv2.cvtColor(page_rl, cv2.COLOR_BGR2GRAY)
#이미지 이진화 (스캔본 처럼)
blur = cv2.GaussianBlur(imgray, ksize=(3,3), sigmaX=0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# Morph operations
edge = cv2.Canny(imgray, 100, 200)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(1000,100))
closed = cv2.morphologyEx(edge, cv2.MORPH_CLOSE, kernel)
contours, hierarchy = cv2.findContours(closed.copy(),cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
이제 하나의 페이지에 대해서는 RECT에서 가로x가 아무리 커져도 옆과 혼선될 일이 없으므로
가로부분을 최대한으로 크게 잡는 것이 오히려 모든 정보를 빼지 않고 담을 수 있으므로
ksize의 x 축을 크게 준다
결과 - left / right page각각 적용 )
-> 문제가 존재하지 않으므로 필요없는 페이지임
-> 문제가 존재하므로 필요한 페이지 이며, 3가지 문제가 각각 적절하게 묶였음을 알 수 있음
3. 한 페이지에 존재하는 각각의 문제를 따로 자르기 : contour함수
contours_xy = np.array(contours)
contours_xy.shape
#한페이지 내의 모든 폐곡선 범위에 대해 실행
for c in contours:
#폐곡선 바운더리
x,y,w,h = cv2.boundingRect(c)
#바운더리를 이용해서 문제 크롭 후 보여주기
img_trim = page_rl[y:y+h , x:x+w]
cv2_imshow(img_trim)
for문을 이용해 각각의 contour에 대해 바운더리를 구한 후 그에 맞추어 잘라준다
저장하려면 imwrite를 사용해야 하지만 일단 미완이므로 imshow를 사용함
contours[] : 물체가 몇 개인지, 하나의 닫힌 선이 하나의 물체임
contours[][] : 각 좌표
contours [][][x][y] : x축과 y축
결과)
left page
right page
원하는 대로 잘라진 것을 볼 수 있다
4. Refactoring : problem_crop함수
하나의 페이지를 입력하면
right/left로 trim한 후 각각에 대해 crop을 하는 함수로 최종 만들면
#페이지 url을 입력하면
def problem_crop(image_url):
#이미지url을 open CV에 읽어들이기
imgfile = image_url
image = cv2.imread(imgfile)
#한 페이지를 반페이지로 나누기
right,left = imtrim(image)
#각 반페이지에 대해 크롭 진행
contour(right)
contour(left)
image_url을 인풋으로 주면 각각에 대한 문제 크롭을 출력하는 함수가 최종으로 만들어 졌다
5. 해결해야 할 것
1) left page처럼 문제가 아닌 부분에 대해서는 저장할 필요가 없다
-> text를 인식하여 첫글자가 숫자가 아닌 이미지에 대해서는 저장하지 않음( tesseract 이용
2) 이미지 저장할 때 이름을 DB에 넣기 쉽게 저장
-> "문제집명_페이지_문제번호.png " 로 저장되게 만들기
전체코드)
#OpenCV - 문제 크롭하기 (미완)
#라이브러리 임포트
import numpy as np
import cv2 #openCV package
from google.colab.patches import cv2_imshow
#구글 드라이브와 연동
from google.colab import drive
drive.mount('/gdrive')
#수능완성 page trim
#페이지에서 왼쪽,오른쪽 반페이지 분리
def imtrim(page):
x=300
w=1120
left = page[465:, x:x+w]
x=1480
right = page[465:,x:x+w]
return right,left
#반페이지를 입력받고 크롭하기
def contour(page_rl):
#이미지 흑백화
imgray = cv2.cvtColor(page_rl, cv2.COLOR_BGR2GRAY)
#이미지 이진화 (스캔본 처럼)
blur = cv2.GaussianBlur(imgray, ksize=(3,3), sigmaX=0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# Morph operations
edge = cv2.Canny(imgray, 100, 200)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(1000,100))
closed = cv2.morphologyEx(edge, cv2.MORPH_CLOSE, kernel)
contours, hierarchy = cv2.findContours(closed.copy(),cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours_xy = np.array(contours)
contours_xy.shape
#한페이지 내의 모든 폐곡선 범위에 대해 실행
for c in contours:
#폐곡선 바운더리
x,y,w,h = cv2.boundingRect(c)
#바운더리를 이용해서 문제 크롭 후 보여주기
img_trim = page_rl[y:y+h , x:x+w]
cv2_imshow(img_trim)
#페이지 url을 입력하면
def problem_crop(image_url):
#이미지url을 open CV에 읽어들이기
imgfile = image_url
image = cv2.imread(imgfile)
#한 페이지를 반페이지로 나누기
right,left = imtrim(image)
#각 반페이지에 대해 크롭 진행
contour(right)
contour(left)
#함수실행
if __name__ == "__main__":
problem_crop('/gdrive/MyDrive/cropStudy/suwan_ga/suwan_ga_030.png')
input )
수능특강 (가)형 _ 8pgae
output)
6개의 이미지
참고사이트
leembedded.tistory.com/16?category=698391
'졸업프로젝트 > OpenCV' 카테고리의 다른 글
[OpenCV] 답지 문제별로 자르기(1) (0) | 2021.01.19 |
---|---|
[OpenCV] 이미지에서 특정 이미지 찾아내기 (2) | 2021.01.18 |
[OpenCV]Morphological Transformation (0) | 2021.01.12 |
[OpenCV] 문제지에서 문제 크롭(1) (0) | 2021.01.12 |
[OpenCV] 이미지 이진화 (0) | 2021.01.11 |