OCR 태스크는 논리적으로 두 개의 단계로 구성된다. Deep Learning based OCR 은 (첫 번째 단계) 문자영역을 찾아내는 detection 모델과 (두 번째 단계) 문자를 식별하는 recognition 모델로 이루어져 있다.
해야 하는 일은 End2End F1 Score 을 산출하는 것이다. 코그넷나인 김경태 파트장님으로부터 이 과제를 부여받은 것은 2022/09/15쯤이었지만, 2022/10/26쯤 뒤늦게 알게 된 사실은 MMOCR 등의 OCR 프레임워크들조차 Detection F1 Score 이나 Recognition Word Accuracy, Recognition Character F1 Score 등을 계산해 주는데 비해 Detection + Recognition = End2End F1 Score 을 계산해주지는 않는다. 따라서 MMOCR 등 프레임워크를 사용하더라도 모델 출력값을 받아서 이 기능을 직접 구현해야만 한다. 따라서 이 에셋은 AiHub OCR 국가지원사업은 물론 다른 OCR 태스크에도 유용하게 사용될 수 있다.
End2End F1 Score 의 정의는 아래 과제문서를 참고하라.
이때 최적화가 굉장히 중요하게 작용한다. 보통 시간복잡도가 $O(n^2)$ 이기 때문이다. 컴파일 언어 사용을 권장한다. Distribution or Multiprocess 를 사용하라.
모든 Object detection task 가 그러하듯, prediction 과 ground truth 는 1:1 대응이 되지 않는다. prediction 순서와 ground truth 의 순서 및 개수는 보장되지 않는다. 보통 prediction bbox 이 ground truth 보다 훨씬 많을 것이다.
대표적인 OCR 대회는 ICDAR 이고, ICDAR 만의 Label 포맷이 있다.
{x1},{y1},{x2},{y2},{x3},{y3},{x4},{y4},{label}
{x1},{y1},{x2},{y2},{x3},{y3},{x4},{y4},{label}
{x1},{y1},{x2},{y2},{x3},{y3},{x4},{y4},{label}
일반적인 object detection task bounding box label 과 다르게, 그 형식이 left_top, right_bottom 형태가 아님을 알 수 있다. OCR 문제에서는 문자가 존재하는 영역 사각형이 이미지의 변에 평행하거나 수직인 직사각형 형태일 것이라는 점을 보장할 수 없기 때문이다. 텍스트에 주어진 text detection 형식은 polygon 이다.
만약 주어진 네 좌표에서, 임의의 세 개의 좌표로 만드는 삼각형이 나머지 한 개의 좌표를 포함한다면, 네 개의 좌표로 만들 수 있는 사각형은 유일하지 않다.

따라서 반드시 주어지는 $(x_1, y_1), (x_2, y_2), (x_3, y_3), (x_4, y_4)$ 는 ‘linear ring’ 을 만들 수 있는 형태로 공급된다.
레이블러의 실수에 대해 강인하게 설계되어야 한다. 가령 GT 데이터의 labels key 가 비어 있는 레코드들을 don’t care 이라고 보는 것이 합리적이지만, iscrowd == False 인데도 labels key 가 비어있는 레코드가 발견될 수 있다. 혹은 주어지는 $(x_1, y_1), (x_2, y_2), (x_3, y_3), (x_4, y_4)$ 가 ‘linear ring’ 형태로 들어오지 않는 경우가 존재할 수 있으므로 처리를 거부하는 예외처리 로직이 있으면 좋을 것이라고 한다. 코그넷나인 김경태 파트장님에 따르면, 이러한 상황들은 그냥 레이블러의 실수이기 때문에 전처리 과정에서 그냥 버리면 된다고 하셨다.
텍스트 영역에 가림(occlusion)이 있는 경우 하나의 검출 대상에 대해서도 여러 polygon 으로 구성되어 있을지 모른다.
Note that a single object (iscrowd=0) may require multiple polygons, for example if occluded.
$\mathrm{transcription}(t’)$ 을 계산할 때, 문장 내 단어가 1개로 구성되어 있다면, 해당 단어를 구성하는 문자 n 개 중 1 개라도 틀리면 그냥 score 을 0 으로 계산하는 것이 맞다.
Single instruction 실행 시간을 단축하는 미시적인 최적화보다 알고리즘 시간복잡도 단축과 같이 거시적인 최적화가 선행되어야 할 뿐 아니라 훨씬 중요하다.
Given an overall design, a good choice of efficient algorithms and data structures, and efficient implementation of these algorithms and data structures comes next. After design, the choice of algorithms and data structures affects efficiency more than any other aspect of the program. (Program optimization - Wikipedia)
무엇이 더 시간을 많이 잡아먹는지 알기 위해서는 요소별 소요시간을 정확히 측정하고, 자주 일어나는 연산을 빠르게 한다 (Common Case Fast).
Making the common case fast will tend to enhance performance better than optimizing the rare case. Ironically, the common case is often simpler than the rare case and hence is oft en easier to enhance. This common sense advice implies that you know what the common case is, which is only possible with careful experimentation and measurement.(Computer Organization and Design MIPS Edition)
병렬적으로 처리하라 (Performance via parallelism).
python prototyping
<aside> 💡 (1) 일단 최대한 완성된 라이브러리들을 사용하여 전체 파이프라인을 완성시킨 다음에 하나씩 자체적으로 구현하며 디버깅하는 것이 훨씬 개발 생산성이 높을 것이라는 생각, (2) 최적화 원칙 중 알고리즘 단축에 더욱 집중할 수 있는 언어를 사용하기 위해 python 프로토타이핑을 우선적으로 진행한다.
</aside>
C/C++ porting
<aside> 💡 C/C++ 포팅은 진행 중, 더 급한 일들이 생겨서 더이상 진행하지 않았다.
</aside>