본문 바로가기

DeepLearning/OCR_

[ENG_OCR] ImageWithTextBoxes 디버깅을 위한 코드

반응형

CRNN 학습 도중에 에러가 나는 이미지에 대해 시각적으로 보기 위해 만든 코드

그 외에도 데이터셋의 형태 파악에 사용 가능

 

 

1. Image와 함께 Annotation된 라벨 값 시각화 작업

 

1> 필요한 라이브러리 로딩

import matplotlib.pyplot as plt
import PIL
import pickle
import os
import cv2 
import numpy as np

 

 

2> 피클파일 불러오기

from data_cocotext import GTUtility

with open('gt_util_cocotext_val.pkl', 'rb') as f:
    gt_util_val = pickle.load(f)

 

 

3> 확인하고 싶은 특정이미지의 인덱스 확인.

idx = gt_util_val.image_names.index('COCO_train2014_000000234956.jpg')

 

 

4> 해당 인덱스의 boxes 값 확인.

boxes = gt_util_val.data[idx]

>> boxes값은 np.array 형태로 텍스트 박스의 갯수만큼 출력된다.

>> polygon 형태이므로 8개의 배열과, 마지막 1을 포함한 형태로 들어있다.

 

len(boxes) = 16 : 텍스트박스의 갯수 16개

 

5> 이미지이름과 이미지경로를 확인.

img_name = gt_util_val.image_names[idx]
img_path = os.path.join(gt_util_val.image_path, img_name)

 

 

6> 이미지를 넘파이 배열로.

img = cv2.imread(img_path) #3차원 배열의 형태로 온다.
img.shape #(426, 640, 3)

- cv2.imread(이미지 경로)를 이용하면 이미지를 3차원 넘파이 배열로 읽을 수 있다

 

 

7> 전처리를 한 뒤에 boxes와 text값을 가져온다.

boxes = np.copy(gt_util_val.data[idx][:,:-1])
texts = np.copy(gt_util_val.text[idx])

mask = np.array([not (np.any(b < 0.) or np.any(b > 1.)) for b in boxes])

boxes = boxes[mask]
texts = texts[mask]

- 해당 인덱스의 boxes의 값에서 각 배열에서 마지막 값 1개를 제외하고 np.copy하여 boxes에 담는다.

- texts 변수에 해당 텍스트박스의 레이블을 가져와 담아준다.

- boxes의 값들 중에서 이미지의 크기를 벗어난 값이 있다면 제외하고 가져온다.

 

 

8> 가져온 boxes의 값들을 원래 이미지 크기로 변경

bbox = boxes.reshape(-1,2)* [img.shape[1],img.shape[0]] #height, width

- 원래 가져왔을 때 boxes.shape = (텍스트 박스의 갯수, 8)

- reshape을 해서 열의 값을 2로 고정시킨다.

- 그리고 정규화된 값들을 원래 이미지 사이즈로 변경해주기 위해 x에는 height을 곱하고, y에는 width를 곱한다

- 여기서 img.shape[1] : height // img.shape[0] : width 값 이다

 

 

9> 다시 boxes를 원하는 형태로 변경

bbox2 = bbox.reshape(-1,8)
boxes = np.ndarray.tolist(bbox2) 

- 텍스트 박스 하나씩 리스트로 만들기 위해 다시 reshape

- 처리하기 쉽도록 nparray 형태를 list 형태로 변경해준다

 

 

10> XLIST & YLIST, XPOINT & YPOINT

xlist = [] 
ylist = []

for i in range(len(bbox3)):
    xpoint = bbox3[i][0::2]
    xpoint = xpoint + [xpoint[0]]
    
    ypoint = bbox3[i][1::2]
    ypoint = ypoint + [ypoint[0]]
    
    xlist.append(xpoint)
    ylist.append(ypoint)

- xpoint에는 하나의 텍스트 박스에 대한 xpoint 값

- ypoint에는 하나의 텍스트 박스에 대한 ypoint 값

- 텍스트 박스의 xpoint와 ypoint의 마지막에 각 포인트의 첫번째 값을 넣어준다

  ( plot을 그릴때 네모로 연결될 수 있게 한다 )

- 최종적으로 각 텍스트 박스의 포인트를 xlist와 ylist에 담아준다.

 

 

11> 이미지 위에 텍스트 박스 그리기

plt.figure(figsize=(20,20))

for i in range(len(xlist)):
    plt.plot(xlist[i], ylist[i], linewidth=3, color='r')

plt.imshow(img)
plt.axis('off')

- 처음에 figsize를 지정해준다.

- 각 xlist와 ylist에 담긴 값 들을 반복분을 이용해 텍스트 박스를 그린다.

- 마지막으로 이미지를 plt.imshow를 해서 겹쳐 보이게 한다

 

output image

 

 

CRNN_ImageWithTextboxes.py
import matplotlib.pyplot as plt
import PIL
import pickle
import os
import cv2 
import numpy as np

from data_cocotext import GTUtility

def getTextBoxes(img_name):
    with open('gt_util_cocotext_val.pkl', 'rb') as f:
        gt_util_val = pickle.load(f)
    
    idx = gt_util_val.image_names.index(img_name)
    
    img_name = gt_util_val.image_names[idx]
    img_path = os.path.join(gt_util_val.image_path, img_name)
    img = cv2.imread(img_path)
    print('이미지의 shape', img.shape)
    
    boxes = np.copy(gt_util_val.data[idx][:,:-1])
    texts = np.copy(gt_util_val.text[idx])

    mask = np.array([not (np.any(b < 0.) or np.any(b > 1.)) for b in boxes])
    boxes = boxes[mask]
    texts = texts[mask]
    
    bbox = boxes.reshape(-1,2)* [img.shape[1],img.shape[0]]
    
    bbox2 = bbox.reshape(-1,8)
    bbox3 = np.ndarray.tolist(bbox2) 
    
    xlist = []
    ylist = []
    for i in range(len(bbox3)):
        xpoint = bbox3[i][0::2]
        xpoint = xpoint + [xpoint[0]]

        ypoint = bbox3[i][1::2]
        ypoint = ypoint + [ypoint[0]]

        xlist.append(xpoint)
        ylist.append(ypoint)
    
    plt.figure(figsize=(20,20))
    for i in range(len(xlist)):
        plt.plot(xlist[i], ylist[i], linewidth=3, color='r')
    plt.imshow(img)
    plt.axis('off')

>> 위와 같이 함수 형태로 만들어 놓으면 재사용하기 편리하다.

 

>> 함수를 사용 할 떄는 아래와 같이 파라미터로 이미지 이름을 준다.

getTextBoxes('COCO_train2014_000000234956.jpg')

getTextBoxes 함수사용

 - 위에 보면 에러를 생성한 텍스트 박스를 확인할 수 있다.

 - 박스 보다는 막대 형태를 띄고 있는데, 이런 잘못 된 형태의 텍스트박스 를 처리 할 수 있는 코드를 추가해야한다.

   ( InputGenerator 와 crop_word에서 코드 수정이 필요하다)

반응형