2021/01/19 - [졸업프로젝트/OpenCV] - [OpenCV] 답지 문제별로 자르기(1)
이 글에서 "매칭 기준으로 자르기" 부분은 많은 삽질을 통해 알아내었고,
최종적으로는 다음과 같다
def contour(page_rl):
#이미지 흑백화
imgray = cv2.cvtColor(page_rl, cv2.COLOR_BGR2GRAY)
#추출하려는 이미지
template = cv2.imread('/gdrive/MyDrive/ProjectStudy/answer_temp.png',0)
w, h = template.shape[::-1]
#템플릿 매칭
res = cv2.matchTemplate(imgray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.5
loc = np.where( res >= threshold)
#for문 내에서 사용할 변수 초기화
y_now = 0 #현재 자를 이미지의 y좌표
pt_now = 0 #현재 탐지한 "답"이미지의 y좌표
#탐지한 "답"이미지의 갯수만큼 반복
for pt in zip(*loc[::-1]):
#탐지한 "답"이미지의 y좌표
pt_past = pt_now # 이전값
pt_now = pt[1] #현재값
# 자를 y축 좌표 계산 (y_past : 시작좌표 / y_now : 끝좌표
y_past = y_now # 이전에 자른 부분(이전 단계의 끝좌표)으로 시작을 대치
y_now = pt_now + h + 25 #( "답"이미지의 left,top의 y좌표 + 이미지 height + 여백 )
#같은 "답"이미지가 여러번 탐지되는 부분을 자르는 것을 방지
if (pt_now >= pt_past+3):
img_trim = page_rl[y_past:y_now,:] # 원본 이미지를 계산한 좌표로 자르기
include(img_trim,qnum) # 잘린 이미지를 저장
# 맨 마지막 부분을 위해 1회 더 수행
img_trim = page_rl[y_now:,:]
include(img_trim,qnum)
이제 삽질과정을 나열해 보기로 한다
def contour(page_rl):
이 부분은 앞으로 생략하도록 하고 내용을 살펴보자
이미지 흑백화 및 템플릿 매칭
#이미지 흑백화
imgray = cv2.cvtColor(page_rl, cv2.COLOR_BGR2GRAY)
#추출하려는 이미지
template = cv2.imread('/gdrive/MyDrive/ProjectStudy/answer_temp.png',0)
w, h = template.shape[::-1]
#템플릿 매칭
res = cv2.matchTemplate(imgray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.5
loc = np.where( res >= threshold)
매칭을 기준으로 자르기
FIRST TRY
y_now = 0
for pt in zip(*loc[::-1]):
#이전 "답"이미지를 자른 부분 ( 시작부분 )
y_past = y_now
#현재 "답"이미지를 기준으로 자를부분 ( 끝 부분 )
y_now = pt[1] + h + 25
#이미지 자르기
img_trim = page_rl[y_past:y_now,:]
#출력
cv2_imshow(img_trim)
이렇게 시도했을 경우
다음과 같은 결과(오류)가 나온다
error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'
일단 순서상 맨 처음(2페이지 왼쪽의 맨 윗 문제)만 출력되었다.
이런 오류는 찾아 본 결과 경로가 잘못되어 해당 경로에 이미지가 없을 때 발생하는 오류이다.
하지만 해당 경로가 잘 못되었다면, 맨 첫번째 문제도 출력되지 않았을 것이다
결국 해당 경로에 이미지가 없는 것은 아니고, 두번째 이미지를 자르려고 시도한 부분에서 이미지가 존재하지 않는다는 의미일탠데
일단 잘 모르겠어서 문제가 생기는 function인 cvtColor를 contour함수 내에서 제거하고,
imtrim시 gray이미지로 변경한 후 contour함수로 넘겨주었다.
SECOND TRY : contour함수 내에서 cvtColor를 제거하고 다른 곳으로 이동시킴
다음 코드와 같이 cvtColor를 수행하는 장소를 imtrim으로 옮겨서 진행하였다
#수능완성 page trim
def imtrim(page,page_num):
#이미지 흑백화
page = cv2.cvtColor(page, cv2.COLOR_BGR2GRAY)
page_num = int(page_num)
#짝수
if (page_num%2 == 0):
left = page[150:-130, 100:855]
right = page[150:-130,880:-137]
#홀수
else:
left = page[150:-130, 145:900]
right = page[150:-130,905:-112]
return left,right
#반페이지를 입력받고 크롭하기
def contour(page_rl):
#cvtColor부분 제거
#imgray = cv2.cvtColor(page_rl, cv2.COLOR_BGR2GRAY)
#추출하려는 이미지
template = cv2.imread('/gdrive/MyDrive/ProjectStudy/answer_temp.png',0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(page_rl,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.5
y_now = 0
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
y_past = y_now
y_now = pt[1] + h + 25
img_trim = page_rl[y_past:y_now,:]
cv2_imshow(img_trim)
그랬더니 다음과 같은 결과를 얻었다
SystemError: tile cannot extend outside image
(중략)
다음과 같이 내가원하는 이미지는 전부 원하는 모양 대로 잘렸지만 (번호대로)
두가지 문제가 생겼다
- SystemError : tile cannot extend outside image
- 3페이지 맨 마지막 부분 (21번의 머릿부분)이 잘리지 않는다
2번째 문제는 해당 부분에는 "답"이라는 이미지가 없기 때문으로 여겨진다.
이는 나중에 해결하고 tile 뭐시기 에러를 고치지 않는 이상 imwrite를 사용할 수 없으므로 이를 고쳐야한다
tile cannot extend outside image라면, 아마 이미지를 자르려고 하는데, 가지고 있는 이미지 사이즈 보다 더 큰 범위를 자르려고 했을 것이다.
그렇게 예상했기 때문에 일단은 가설이 맞는지 확인하기 위해 각 이미지의 사이즈를 출력해보기로 했다.
THIRD TRY : image size 출력해보기
for pt in zip(*loc[::-1]):
y_past = y_now
y_now = pt[1] + h + 25
img_trim = page_rl[y_past:y_now,:]
print("==================start========================")
print(img_trim.size)
cv2_imshow(img_trim)
print("==================end========================")
결과는 다음과 같았다
올바르게 잘린 부분에 대해서는 다음과 같이 적당한 양수값의 size가 출력되는데 (357870)
오류가 난 부분은
size가 0이기 때문에 imshow(이미지 출력)이 불가능해 오류가 나며 end부분 또한 출력되지 못했다
즉, 나누려는 부분의 size가 0이라는 것은
y_past / y_now 둘의 좌표가 동일하게 나오는 부분이 존재하기 때문일 것이다.
y_past = y_now
y_now = pt[1] + h + 25
img_trim = page_rl[y_past:y_now,:]
y_past와 y_now가 나오는 부분은 다음과 같은데
y_past는 지난번의 y_now를 대입한 것이고,
y_now는 새로운 pt[1] (새로 찾은 "답"이미지의 y좌표) + h + 25 이다.
여기서 h와 25는 고정값이고, y_past는 지난번의 y_now일태니 오류가 날 일이 없으므로
지난번의 y_now 즉, 지난번의 pt[1] 과 이번에 새로 계산된 y_now 의 pt[1] 이 동일하거나 아주 비슷하거나 일 것
결론은 하나의 이미지 내에서 찾아낸 "답"이미지들의 y좌표에 겹치는 값이 존재한다는 것이다!
이는 실제로, 이 글을 돌이켜 보면 알 수있다.
2021/01/18 - [졸업프로젝트/OpenCV] - [OpenCV] 이미지에서 특정 이미지 찾아내기
다른 건 설명을 생략하고,
for pt in zip(*loc[::-1]):
을 통해 우리는
for문을 돌 때 마다 하나의 "답"이미지에 대하여
pt[0]에는 "답"이미지가 존재하는 좌표의 x값
pt[1]에는 "답"이미지가 존재하는 좌표의 y값을 저장한 것을 기억할 것이다.
그 당시 pt를 전부 출력한 내용을 확인해 보면,
검출 해낸 "답"이미지는 6개 인데 반해서, pt를 전부 출력한 결과는 11개인 것을 알 수 있다.
그리고 pt를 출력한 내용에서 y좌표 부분만 자세히 살펴보면,
279, 279, 625, 626, 754, 754, 1026, 1027, 1235, 1235, 1716 -> 이런식으로 6개가 11개로 불어난 것...
즉 엇비슷한 좌표내에서 "답"이미지가 2개로 검출되었다는 사실을 알 수 있다....
바로 이런거였다 빨강~파랑까지 하나의 "답"이미지 당 2개라고 검출된 것!
이들은 엇비슷한 위치에서 오차범위 +-1 정도를 가지므로
현재의 pt[1]의 값이 이전의 pt[1]의 값보다 +3 이상인 경우에만 cut을 진행하도록 고쳤다
FOURTH TRY : 현재의 pt[1]의 값(pt_now)이 이전의 pt[1]의 값(pt_past)보다 +3 이상인 경우에만 cut을 진행
for pt in zip(*loc[::-1]):
pt_past = pt_now
pt_now = pt[1]
y_past = y_now
y_now = pt_now + h + 25
#이전 y축값보다 3이상 더 클때만 진행
if (pt_now >= pt_past+3):
img_trim = page_rl[y_past:y_now,:]
cv2_imshow(img_trim)
결과는 성공적이었다. (혹시 몰라서 pt값도 같이 출력하게 했다)
13번에 쓰인 "답"을 4개의 이미지로나 찾아낸 모양...
여튼 오류는 깔끔하게 해결되었다!
이제 남은 문제는 페이지의 마지막 부분에 "답"이 없는 경우는 무시당하여 잘리지 않는 경우를 해결해야한다
그림과 같이 페이지 마지막 부분에 "답"이라는 이미지가 검출되지 않아
이를 해결하기위해서는 for문이 종료되어도 무조건 페이지의 끝 부분까지 한번더 cut을 진행해야한다
이렇게 되면 아무 의미도 없는 빈칸이 생겨날 수 있는 문제점이 발생할 수 있으나,
이는 후에 처리하거나 없앨 수 있으므로 정보가 손실되지 않는 것이 더 중요하다
FIFTH TRY : for문이 종료된 후에도 페이지의 맨 아래까지 cut을 수행
for pt in zip(*loc[::-1]):
pt_past = pt_now
pt_now = pt[1]
y_past = y_now
y_now = pt_now + h + 25
#이전 y축값보다 3이상 더 클때만 진행
if (pt_now >= pt_past+3):
img_trim = page_rl[y_past:y_now,:]
cv2_imshow(img_trim)
#for문이 종료되어도 1회 page의 맨 끝까지 컷을 진행
img_trim = page_rl[y_now:,:]
cv2_imshow(img_trim)
이렇게 하니 "답"이미지가 존재하지 않는 것에 대해서도 크롭을 할 수 있게 되었다!
그래서 결론적으로 정체불명의 오류였던
error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'
와
"답"이미지가 없는 경우에 대한 크롭 불가 issue
2가지를 해결할 수 있었다!
'졸업프로젝트 > OpenCV' 카테고리의 다른 글
[openCV]답지 문제별로 자르기(3) (0) | 2021.01.29 |
---|---|
[OpenCV] 답지 문제별로 자르기(1) (0) | 2021.01.19 |
[OpenCV] 이미지에서 특정 이미지 찾아내기 (2) | 2021.01.18 |
[OpenCV]문제지에서 문제 크롭(2) (0) | 2021.01.12 |
[OpenCV]Morphological Transformation (0) | 2021.01.12 |