OCR 성능 끌어올리기 3rd step: Reducing noise-2

류창훈·약 17시간 전
0

CV (Computer Vision)

목록 보기
9/9

노이즈 제거 및 글자 복원 내용입니다.



이전 포스팅인 필터 적용 방식은 노이즈 감소에는 탁월하나,

OCR에 직접적으로 필요한 흐린 글씨 복원에 있어서 큰 효과는 없었습니다.



그래서 전에 공부했던 모폴로지 연산에 대해 생각하게 되었고,

효과는

노이즈 제거, 문자 연결 보정 및 경계 강화

와 같습니다.


모폴로지 연산에는 열림, 닫힘, 팽창, 침식 연산이 있습니다.

침식 연산은 필터가 존재한다고 하면, 그 필터안에 들어가지 않는 픽셀은 제거(0값 검은색으로 채우기)하는 방식,

팽창 연산은 그 필터 안에 픽셀이 하나라도 들어가 있다면, 주변 픽셀까지 채워넣는(255값 흰색 채우기) 방식 입니다.


두 연산을 다르게 말하면,

어두운 부분의 노이즈를 제거하는지, 밝은 부분의 노이즈를 제거하는지,
사실상 이 전의 필터 적용 노이즈 제거와 큰 차이가 없기 때문에
따로 다루지 않습니다.





- Morphology Opening(열림)


열림 연산은 침식 후에 팽창 방식 입니다.


과정을 정리하면,

  1. 작은 객체 제거(침식)
  2. 남은 주요 객체 복원(팽창)

으로,
노이즈 제거 및 객체 분리할 때 사용되는 연산 입니다.


kernel = np.ones((3,3), np.uint8)
opened = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)

적용 코드는 이와 같고,
위에 kernel 매개변수 값은 커널 사이즈를 지정하는건데,
글씨 크기가 작기 때문에 3값으로 두었습니다.



적용 이미지는 이와 같고,


열림 연산 적용 이미지(오른쪽)와 기존 흑백 이미지(왼쪽)를 비교해보면,

팽창 연산이 껴있기 때문에 배경이 좀 더 밝아진 것을 볼 수 있는데,

글씨 자체는 솔직히 별 차이 없는거 같습니다.


애초에 글씨가 작은데, 그 작은 객체에서 제거 과정이 일어난 후에, 복원을 거치다 보니 이렇게 되었다고 유추할 수 있습니다.





- Morphology Closing(닫힘)


닫힘 연산은 팽창 후 침식 과정을 거칩니다.


과정을 정리해보면,

  1. 경계 확장(팽창)
  2. 경계 보정(침식)

구멍을 메우고 분리된 객체 조각을 연결할 때 사용하는 연산 입니다.


어찌보면 글씨 복원에는 닫힘 연산이 더 적합해 보입니다.



closed = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)

적용 코드는 이와 같고, kernel 사이즈는 위와 동일합니다.




출력 결과를 보아하면,

열림 연산 적용 이미지(오른쪽) 보다 닫힘 연산 적용 이미지(가운데)가 더 흐릿해졌습니다.



위 이미지는
'닫힘 -> 열림' 연산,
'열림 -> 닫힘' 연산 섞어서 썼을 때의 결과물 입니다.

이미지를 보아도, 기대 효과에 미치지 못하는 것을 알 수 있습니다.



자동차 번호판, 혹은 어떤 잔뜩 확대되어 픽셀 다 깨진 이미지의 글씨에는 도움이 되나,

애초에 복원하고 싶은 객체(글자) 자체가 너무 작아서 큰 차이가 없는 것 같습니다.


그래서 노이즈는 쫌 낄 수 있어도,
글씨 자체를 복원할 수 있는 방법 몇가지를 적용해보겠습니다.





- CLAHE (Contrast Limited Adaptive Histogram Equalization)


히스토그램 평활화(HE)는 위 이미지 처럼, 한쪽으로 쏠려있는 분포(너무 어둡거나 밝은 이미지)를 평활화 하여 안 보였던 부분까지 선명하게 하는 것 입니다.

그에 반해 CLAHE는 이미지를 작은 블록으로 나누어 대비를 조정하는 방식입니다.


즉,
HE전역적으로 대비를 조정한다고 하면,
CLAHE지역적으로 대비를 조정해서 작은 글씨가 담겨있는 이미지에서 효과적으로 텍스트를 강화할 수 있습니다.


clahe = cv2.createCLAHE(clipLimit = 5.0, tileGridSize = (3, 3))
clahe_enhanced = clahe.apply(image)

적용 코드는 위와 같고,

tileGridSize는 블록 사이즈(위에 나와있는 지역)를 지정하는 것이고,
clipLimit은 대비(Contrast)를 얼마나 강하게 조정할지 설정하는 매개변수 입니다.

대비 설정값을 낮게하면 대비 조정을 적게 하여 부드러운 이미지 생성,
값이 높으면 대비를 강하게 하여 객체 자체를 선명하게 할 수 있으나, 노이즈 증가 가능성도 함께 존재합니다.


블록 사이즈는 작은 글씨를 잡아야 하기 때문에 이렇게 설정했고,
대비 강도는 어쨋든 흐릿한 글씨를 뚜렷하게 만들어야 하기 때문에 5.0 값으로 두었습니다.

대비 강도의 초기 설정값은 2.0 이다.
보통은 2.0 ~ 4.0 정도의 값을 둔다.

적용 이미지는 이와 같고,

확실히 원래 이미지 보다 글씨는 뚜렷해진게 보입니다.
배경의 노이즈 값도 함께 증가한게 보이기는 하나, 이건 이진화 과정으로 보완하면 될 것 같습니다.





- Unsharp Masking (샤프닝)


Unsharp Masking 기법은 전 포스팅처럼 필터 적용하는 방식입니다.


물체의 경계를 선명하게 하는 것.

이라고 나와있으나,


전 내용처럼 필터를 적용하는 것이기 때문에,
어느정도 노이즈 감소 효과도 있습니다.


다만, 필터 종류마다 용도는 제각각이며,
특정 필터는 노이즈 감소보다는 텍스트 강조에 더 효과적일 수 있습니다.


여기서는 작은 글씨를 강조해야 하기 때문에 Unsharp Masking 기법을 적용했습니다.


[010151010][111191111]\begin{aligned} \begin{bmatrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{bmatrix} \quad \begin{bmatrix} -1 & -1 & -1 \\ -1 & 9 & -1 \\ -1 & -1 & -1 \end{bmatrix} \end{aligned}

위에 처럼, 필터 값은 현재 픽셀을 얼만큼 강조하고 싶은지에 따라 변형할 수 있습니다.

왼쪽 이미지와 오른쪽 이미지는 각각 위 필터 순서와 동일하고,

확실히 값 차이가 그렇게 크지 않은 필터를 적용한 왼쪽 이미지는 좀 더 배경부터 부드럽게 나왔지만,

글씨 자체가 강조된 것을 보면, 노이즈를 감안하더라도 오른쪽 이미지가 더 적합해 보입니다.


sharpening_kernel = np.array([[-1, -1, -1], 
                              [-1,  9, -1], 
                              [-1, -1, -1]])
                              
sharpened = cv2.filter2D(image, -1, sharpening_kernel)

적용 코드는 이와 같습니다.





- CLAHE + Unsharp Masking


이제는 두개를 섞어서 보겠습니다.

왼쪽 이미지는 샤프닝 적용 후 CLAHE,
오른쪽 이미지는 CLAHE 후 샤프닝 적용 이미지 입니다.


샤프닝 후 CLAHE 적용 했을 때의 결과물이 좀 더 글씨가 도드라지나,
두 이미지 전부 노이즈가 너무 많이 껴 있는 상황입니다.


이렇게 되면 두개 다 그닥 좋지 못한 것 같습니다.





- 정리


모폴로지 연산, 그리고 샤프닝 기법 모두 필터를 적용하는 것 입니다.

자료를 보다 보면, 각각의 적용 방법, 작동 방식, 효과 이런 것을 알 수 있으나,
이것도 디테일한 상황을 고려해서 적용해야 합니다.


무수히 많은 풀이 방법 중, 어떻게 접근할 것이지는
자료를 통해 방법 축소 후 구체화 할 수는 있지만,


어떤 결과를 뱉는지, 그리고 원하는 결과를 가져올 수 있는지는

위에 이것저것 적용해 본것과 같이,

결국 직접 적용을 해봐야 아는 것 같습니다.


이 내용 결과를 보면, CLAHE 기법 적용했을 때의 결과물이
가장 적합한 것 같습니다.


이제 남은 것은
이 포스팅 내용에서 적용한 것에 대한 이진화,
그리고 기울기 보정, Edge 검출이 남았습니다.


음...
너무 많은 걸 한꺼번에 다뤄서 그런가...
머릿속으로 정리가 안된다 ㅋㅋ
내일 다시 보면 팍팍 정리 되겠죠? ㅎㅎ

쭉 적용하고, 정리해서 또 올리도록 하겠습니다.




감사합니당 ~ 🦾





참고자료
https://github.com/Ryuchanghoon/Improve-OCR-Quality/blob/main/sharpening_CLAHE.py
https://docs.opencv.org/4.x/d6/dc7/group__imgproc__hist.html#gad3b7f72da85b821fda2bc41687573974
profile
Linear AI Developer입니다.

0개의 댓글

관련 채용 정보