5.6. 도형과 텍스트 그리기

이미지에 대해 무언가를 결정하는 알고리즘은 종종 그 결정을 시각화해야 합니다. 블롭 검출기는 애플리케이션이 관심 있어 하는 영역을 찾고, 애플리케이션은 운영자 – 또는 스크립트를 실행하는 개발자 – 가 무엇이 발견되었는지 볼 수 있도록 그 영역이 프레임에 그려지기를 원합니다. 좌표 변환은 입력 위치를 출력 위치로 매핑하는데, 이를 디버깅하려면 보통 같은 이미지 위에 두 위치를 표시해야 합니다. IDE 미리보기는 폴링하는 순간 프레임 버퍼에 들어 있는 것을 무엇이든 읽으므로, 알고리즘 출력을 시각화하는 가장 간단한 방법은 프레임 버퍼 자체에 주석을 쓰는 것입니다. Image 클래스의 그리기 계열은 바로 그 작업을 위한 도구 모음입니다.

5.6.1. 프리미티브

각 그리기 메서드는 이미지에 특정 종류의 표시 하나를 배치합니다. 카탈로그는 작으며, 주석이 실제로 필요로 하는 기하학적 프리미티브에 가깝게 머뭅니다:

  • draw_line() – 두 끝점 사이의 직선 선분.

  • draw_rectangle() – 축에 정렬된 사각형으로, 비어 있거나 채워짐.

  • draw_circle() – 중심을 둘러싼 원으로, 비어 있거나 채워짐.

  • draw_ellipse() – 임의의 회전을 가진 타원.

  • draw_cross() – 한 점에 있는 더하기 기호로, 무게중심이나 클릭 대상을 나타내는 일반적인 표시.

  • draw_arrow() – 시작점에서 끝점까지의 화살표.

  • draw_edges() – 네 모서리 점이 주어진 임의의 사각형의 네 변으로, 검출된 태그나 원근 왜곡된 영역을 윤곽으로 표시하는 자연스러운 방법.

  • draw_string() – 내장 비트맵 폰트의 텍스트.

이들 각각은 소스 이미지를 제자리에서 수정하고 체이닝을 위해 같은 이미지를 반환하며, 앞서 확립된 연산 메서드 관례를 따릅니다.

여덟 가지 그리기 프리미티브를 각각 한 번씩 적용해 보여주는 작은 패널들의 그리드. 각 패널에는 선, 사각형, 원, 타원, 십자, 화살표, 사각형, 또는 짧은 텍스트 문자열이 들어 있으며, 그것을 만든 메서드의 이름이 아래에 레이블로 붙어 있습니다.

여덟 가지 그리기 프리미티브, 패널당 하나씩. 각 메서드는 한 종류의 표시를 만듭니다.

5.6.2. 색상

모든 그리기 메서드는 칠해지는 각 픽셀에 어떤 값을 쓸지 결정하는 color 인자를 받습니다. 이 인자가 취하는 형태는 이미지의 형식에 따라 달라집니다. RGB565 이미지의 경우 자연스러운 형태는 각 채널이 0255 범위인 (r, g, b) 튜플이며, 모듈은 이를 쓰기 전에 16비트 RGB565 워드로 패킹합니다. 그레이스케일 이미지의 경우 자연스러운 형태는 0 (검정)부터 255 (흰색)까지의 단일 정수 밝기 값입니다. 메서드들은 해당 형식의 원시 저장 값(RGB565의 경우 16비트로 패킹된 워드, 그레이스케일의 경우 8비트 정수)도 받아들이는데, 이는 색상이 다른 곳에서 계산되어 이미 저장 형태로 되어 있을 때 효율적인 형태입니다.

color 인자를 생략하면 흰색으로 칠합니다. 그 기본값은 흰색이 최댓값이고 대부분의 배경에 대비하여 명확하게 읽히는 그레이스케일 작업에 편리합니다. RGB565 디버그 오버레이의 경우 거의 항상 틀린 선택입니다. 초록이나 빨강이 보통 카메라가 실제로 보는 종류의 장면에 대비하여 더 잘 읽히며, 명시적인 색상은 의도를 전달합니다.

5.6.3. 두께와 채우기

대부분의 기하학 메서드는 표시가 어떻게 그려질지 결정하는 두 개의 플래그를 받습니다:

  • thickness=N은 선의 너비를 픽셀 단위로 설정합니다. 기본값은 1이며, 이는 대부분의 오버레이에 적합합니다. 더 큰 값은 주석이 복잡한 장면에 대비하여, 또는 파이프라인의 후속 단계가 이미지를 더 수정한 후에도 보이도록 유지되어야 할 때 유용합니다.

  • fill=True는 표시를 윤곽선에서 단색으로 전환하여, 모든 내부 픽셀을 선택한 색상으로 칠합니다. 기본값은 False입니다.

이 플래그들은 채울 내부가 없는 프리미티브 – 선, 십자, 화살표, 사각형 – 에는 적용되지 않으며, 거기서는 thickness만 의미가 있습니다.

5.6.4. 텍스트 그리기

draw_string()는 내장된 8x10 픽셀 비트맵 폰트로 문자를 씁니다. xy는 첫 문자 셀의 좌상단 모서리이고, text는 그릴 문자열이며, color는 기하학 메서드와 동일한 관례를 따릅니다. 폰트는 인쇄 가능한 전체 ASCII 범위를 담고 있으며 커닝이 없어 – 각 문자가 동일한 8픽셀 너비 셀을 차지합니다 – 출력을 배치하기 쉽게 만듭니다.

img.draw_string(10, 10, "blobs: 3", color=(0, 255, 0))

문자열에는 줄바꿈(\n)을 포함할 수 있습니다. 각 줄바꿈은 다음 문자를 이전 줄보다 10픽셀 아래의 새 줄 시작 위치로 옮깁니다. scale 인자는 부동소수점 배율로 모든 문자를 더 큰 크기로 그리며, x_spacingy_spacing은 각 문자 주위에 여백을 추가합니다. 작은 회전 / 미러 / 뒤집기 플래그 모음이 문자열 전체에 또는 각 문자 개별에 적용됩니다 – 레이아웃이 요구할 때 텍스트를 각도를 따라 또는 수평이 아닌 가장자리에 대비하여 배치하기에 충분한 제어입니다.

5.6.5. 캔버스 지우기

이 계열의 한 메서드는 특정 표시를 그리지 않습니다. 그것은 단지 이미지의 모든 픽셀을 0으로 리셋합니다:

  • clear() – 모든 픽셀을 0으로 만들며, 선택적으로 ROI로 제한하거나 마스크를 통해 범위를 지정합니다.

clear()는 애플리케이션이 캡처된 프레임 위에 오버레이하는 대신 매 프레임마다 주석을 처음부터 합성할 때 – 검은 캔버스로 시작해 새 주석을 그리고 결과를 디스플레이에 넘김 – 올바른 답입니다. 또한 스크래치 이미지를 마스크 버퍼로 사용하기 위해 준비하는 가장 저렴한 방법이기도 합니다.

갓 할당된 이미지는 생성자에서 이미 0이므로, clear()는 특히 프레임 사이에 재사용되는 버퍼에 대해 의미가 있습니다.