5.21. 스케일, 뒤집기, 자르기¶
이전 하위 절들은 모두 픽셀이 처음 있던 동일한 위치에서 작업했습니다. 변환(transform) 계열은 그것을 바꿉니다. 스케일링은 모든 입력 픽셀을 다른 출력 위치로 보내며, 한 번에 여러 출력 위치로 보낼 수도 있고(업스케일링 시), 다른 여러 입력 픽셀과 공유되는 위치로 보낼 수도 있습니다(다운스케일링 시). 뒤집기와 회전은 다른 매핑을 통해 같은 일을 합니다. 자르기는 입력 픽셀의 직사각형 부분집합을 유지하고 나머지는 버립니다.
image 모듈은 인자와 동작 대부분을 공유하는 세 가지 메서드를 통해 이 계열을 노출합니다.
copy()– 이미지의 사본을 생성하며, 필요에 따라 스케일링, 자르기, 방향 재조정이 가능합니다.crop()–copy와 동일한 연산이지만, 애플리케이션이 원본에서 하위 직사각형을 골라낼 것이라는 전제를 가집니다.scale()– 다시 동일하되, 애플리케이션이 결과의 크기를 조정할 것이라는 전제를 가집니다.
셋은 동일한 인자와 동일한 변환 메커니즘을 공유합니다. 차이는 기본적으로 결과가 어디에 놓이는가입니다. copy() 는 새 이미지를 생성하는 반면, crop() 과 scale() 은 원본을 제자리에서 수정합니다.
5.21.2. 보간: AREA, BILINEAR, BICUBIC¶
스케일링이 각 출력 픽셀을 어떤 단일 입력 픽셀과도 정렬되지 않는 위치로 보낼 때, 메서드는 어떤 값을 쓸지 골라야 합니다. 세 가지 플래그가 방법을 제어합니다.
image.BILINEAR 은 출력 위치로부터의 거리에 따라 가중치를 둔 가장 가까운 네 개의 입력 픽셀 사이를 보간합니다. 결과는 최근접 이웃 방식보다 부드러우며 대각선에 눈에 띄는 계단 현상이 없지만, 추가 연산은 최근접 이웃 패스의 약 네 배 비용이 듭니다. 대부분의 업스케일링 작업과 정수가 아닌 스케일 계수에 적합한 선택입니다.
image.BICUBIC 은 3차 곡선을 사용하여 가장 가까운 열여섯 개의 입력 픽셀 사이를 보간하며, 다시 더 많은 연산 비용으로 한층 더 부드러운 결과를 만듭니다. 그것을 필요로 하는 비용 민감 애플리케이션에 최고의 품질을 제공합니다. IDE가 표시하기만 할 실시간 프레임에는 추가 연산이 거의 가치가 없습니다.
image.AREA 는 출력 픽셀의 영역 안에 들어오는 모든 입력 픽셀을 평균합니다 – 다운스케일링 에 적합한 알고리즘입니다. 쌍선형(bilinear)과 쌍삼차(bicubic)는 보간기입니다. 이들은 원본 픽셀 사이 의 값을 추정하는데, 이는 업스케일링에 필요한 것입니다. 하지만 다운스케일링 시 각 출력 픽셀은 많은 원본 픽셀을 덮고 보간기는 가장 가까운 몇 개만 읽기 때문에, 건너뛴 디테일이 앨리어싱으로 되돌아옵니다. image.AREA 는 대신 덮인 모든 픽셀을 평균에 포함합니다.
힌트가 없을 때의 기본 스케일링 알고리즘은 최근접 이웃 방식으로, 가장 저렴하며 원본이 이미 목적지의 픽셀 해상도에 있을 때 적합한 답입니다.
5.21.3. 방향: 뒤집기와 회전¶
방향 플래그는 서로 그리고 보간 플래그와 자유롭게 조합되는 소수의 불리언 변환 집합입니다.
image.VFLIP은 이미지를 세로로 뒤집습니다(위가 아래가 됩니다).image.HMIRROR은 이미지를 가로로 반전시킵니다(왼쪽이 오른쪽이 됩니다).image.TRANSPOSE는 x 축과 y 축을 맞바꿉니다(행이 열이 됩니다).
대부분의 회전은 이 세 가지를 조합하여 나옵니다. 모듈은 명명된 단축 표현도 제공합니다.
image.ROTATE_90(=VFLIP | TRANSPOSE)image.ROTATE_180(=HMIRROR | VFLIP)image.ROTATE_270(=HMIRROR | TRANSPOSE)
코드로 보면 다음과 같습니다.
img.copy(hint=image.ROTATE_90, copy_to_fb=True)
5.21.4. 종횡비 처리¶
원본의 종횡비가 그려질 직사각형과 일치하지 않을 때, 세 가지 플래그가 그 불일치를 어떻게 처리할지 결정합니다.
image.SCALE_ASPECT_KEEP 는 원본의 종횡비를 보존하고 결과를 레터박스 처리합니다 – 원본은 목적지 안에 맞을 때까지 스케일링되며, 목적지의 나머지는 빈(영) 픽셀로 채워집니다. 전체 출력을 채우는 것보다 원본을 왜곡 없이 유지하는 것이 더 중요할 때 적합한 선택입니다.
image.SCALE_ASPECT_EXPAND 는 원본의 종횡비를 보존하고 잘라냅니다 – 원본은 목적지를 채울 때까지 스케일링되며, 목적지를 벗어나는 부분은 잘립니다. 원본의 모든 부분을 보는 것보다 전체 출력을 채우는 것이 더 중요할 때 적합한 선택입니다.
image.SCALE_ASPECT_IGNORE 는 종횡비를 무시하고 원본을 늘려 목적지를 채우며, 그로 인해 생기는 왜곡을 그대로 받아들입니다. 애플리케이션이 이미 왜곡을 고려한 경우 – 예를 들어 목적지의 치수가 실제로는 동일한 장면의 직사각형이 아닌 경우 – 에 적합한 선택입니다.
기본값(종횡비 플래그 미설정)은 SCALE_ASPECT_IGNORE 와 동일합니다. 늘려서 채웁니다. 종횡비를 신경 쓰는 애플리케이션은 세 가지 중 하나를 명시적으로 지정합니다.
5.21.5. 어떤 것을 언제 사용할 것인가¶
대부분의 크기 조정은 x_scale / y_scale 쌍과 보간 힌트를 함께 사용하여 scale() 을 씁니다.
img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)
대부분의 회전은 hint=image.ROTATE_90 또는 유사한 값으로 동일한 호출을 사용합니다.
자르기는 기본값이 아닌 roi 와 함께 crop() 을 사용합니다.
img.crop(roi=(40, 30, 200, 150))
원본이 연산을 거치고도 남아 있어야 할 때 – 기준 프레임을 캡처하거나, 파괴적으로 처리될 프레임의 썸네일을 만들 때 – copy() 는 결과를 새 이미지로 생성하고 원본은 손대지 않은 채로 둡니다.
thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)
그 기본값이 세 이름 뒤에 숨은 실제 차이입니다. scale 과 crop 은 제자리에서 변환하고, copy 는 할당합니다. 결과 배치 키워드가 그 간극을 메웁니다. scale 또는 crop 에 copy=True 를 주면 원본을 덮어쓰는 대신 결과를 별도의 힙 버퍼로 할당하고, 셋 중 어느 것에든 copy_to_fb=True 를 주면 IDE 미리보기를 위해 결과를 프레임 버퍼에 둡니다.