본문 바로가기

졸업프로젝트/OpenCV

[OpenCV]문제지에서 문제 크롭(2)

728x90

 

아이디어)

raw image

전체 이미지에서 윗단과 아랫단을 제거 한 후 (문제영역만 남김) 

trimed image

페이지를 왼쪽부분과 오른쪽 부분으로 나눈 후 

8page_left 

 

8page_right

 

(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함 

 

결과)

left

 

right 

 

 

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각각 적용  )

left

-> 문제가 존재하지 않으므로 필요없는 페이지임 

 

right 

-> 문제가 존재하므로 필요한 페이지 이며, 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번 이미지 
5번 이미지 
6번 이미지 

 

원하는 대로 잘라진 것을 볼 수 있다

 

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개의 이미지 

left_1

 

left_2
left_3
right_1
right_2

 

right_3

 

 

 

참고사이트

youbidan.tistory.com/19

 

[파이썬] Python과 OpenCV로 이미지 외곽 찾기, 이미지 자르기, 원하는 부분만 자동으로 잘라내기 +

이미지 분류를 위한 딥러닝 모델을 만들던 중 학습 데이터가 필요해서 이미지를 크롤링 해왔으나 문제점이 있었다. 모델을 만들 때 잘 정제된 학습 데이터를 쓰는 것과 그렇지 않은 것으로 학습

youbidan.tistory.com

leembedded.tistory.com/16?category=698391

 

OpenCV - 도형 외곽 추출하기 (1)

이미지로 부터 외곽을 추출하기 위해서는 이미지로 부터 모든 Edge를 검출한 뒤에 그 Edge에서 특정한 부분을 외곽으로 검출하게 된다. 그 과정에서 어떤 부분을 외곽으로 볼 것인지, 검출된 외곽

leembedded.tistory.com

 

728x90