파이썬 pillow crop 함수는 어떤 일을 할까요? 사진의 일부분을 직사각형으로 따는 역할을 합니다. thumbnail, resize 함수와 같이 제가 많이 사용하는 함수입니다.
오늘 소개할 함수가 어떻게 작동하는지 예제로 간단하게 알아보겠습니다.
pillow crop 함수
먼저, 실습 재료로 사용될 이미지는 아래와 같습니다.

이 그림을 보시면 160 by 160과 128 by 128 이렇게 2개의 사각형이 그림에 있음을 볼 수 있어요. 먼저, 가로 160, 세로 160의 사각형은 좌측 최상단에 붙어 있습니다. 다음, 노란색 사각형의 좌상단은 회색 사각형의 오른쪽 우하단과 붙어 있어요. 즉, 노란색 사각형은 (160, 160)부터 (288, 288)까지 있다는 말이 되겠군요.
그림에서, 맨 좌상단의 좌표는 (0, 0)이라는 것을 기억해 주세요.

pillow crop 함수는 box 인자를 받습니다. tuple로 받는데요. 각각 왼쪽 좌상단의 x 좌표와 y좌표, 그리고 오른쪽 우하단의 x 좌표와 y 좌표를 받습니다. 즉, 왼쪽 맨 위 꼭지점과 오른쪽 맨 아래 꼭지점 좌표를 받는다고 볼 수 있어요. 이 영역으로 box를 만들어서, box 부분만 취하겠다는 것입니다.
x 좌표는 가로, y 좌표는 이미지에서의 세로라고 생각하세요. 그러면, 예제 1번 프로그램을 보겠습니다.

예제 1의 4번째 줄을 봅시다. box에 (0, 0, 160, 160)을 넣었습니다. 무슨 의미인가요? 왼쪽 좌상단의 좌표를 (0, 0)으로 하고, 오른쪽 우하단의 좌표를 (160, 160)으로 하는 사각형 영역으로 자르겠다는 의미입니다. 회색 사각형만 나오겠네요.

결과를 보니 정말 그렇습니다. 이 회색 사각형은 왼쪽 좌상단이 (0, 0)이였고, 오른쪽 우하단이 (160, 160)이였지요. 고로, crop이 된 결과는 해당 사각형만 나오게 됩니다.

이제 예제 2번을 보겠습니다. box가 (160, 160, 160+128, 160+128)로 주어졌네요. 여기서 한 가지 팁. 어떤 좌표 w, h를 기준으로 가로 w’, 세로 h’의 크기를 가지는 사각형으로 자르고 싶다.
- 어떤 좌표 (w, h)가 기준으로 들어갔어요.
- 우하단의 가로 좌표는 w에서 w’만큼 증가한 게 됩니다.
- 비슷한 논리로 우하단의 세로 좌표는 h에서 h’만큼 증가한 게 되겠지요?
- 따라서 w+w’, h+h’를 tuple의 3번째, 4번째 요소에 적어주면 됩니다.
4번째 줄의 box 튜플에 3번째 원소에 160+128, 4번째 원소에 160+128이라고 적어뒀어요. 이는 기준 좌상단으로부터 가로로 128, 세로로 128만큼 영역을 생성한다는 의미입니다. + 연산자 하나 더 써서 명확하게 해 두는 편도 나쁘지 않겠지요. 좌상단이 (160, 160)이고 가로와 세로 크기가 128인 영역은 노란색 영역이였습니다.

결과를 보니 노란색 사각형만 뽑혔음을 알 수 있어요.
또 다른 예제
이제, 다른 이미지를 가지고 실습해 보겠습니다.

윗 단락에서 썼던 사진과 다르게 이 사진에는 빨간색 직사각형이 포함되어 있음을 볼 수 있어요. 저는 이 사진에서 빨간색 직사각형 영역만 뽑고 싶습니다. box에 어떻게 넣어주면 될까요? 일단, 빨간색은 사진의 좌상단에 걸려 있습니다. 고로, box tuple의 1번째와 2번째에는 0이 들어가겠네요.

예제 3번을 봅시다. box의 3번째 인자에 60, 4번째 인자에 85를 넣었어요. 빨간색 직사각형의 가로는 85이고, 세로는 60이라고 했어요. 빨간색 직사각형만 뽑히지 않을 거 같은데요. 결과를 먼저 봅시다.

하얀색 영역도 같이 뽑혔네요. 왜 그럴까요? 예제 3의 box는 (0, 0)으로부터 가로 60, 세로 85만큼의 영역을 box로 잡아서 자르게 됩니다. 그런데, 빨간색 직사각형의 가로는 85, 세로는 60 이였습니다. 크기가 맞지 않으니, 빨간색 영역이 아닌 부분도 잘라지게 됩니다. 또한, 빨간색 영역 중 일부는 box에 포함되지 않게 됩니다. 의도대로 수행되게 하려면 어떻게 해야 할까요?

box의 tuple의 3번째 인자에 85, 4번째 인자에 60을 넣습니다. 그러면 (0, 0)으로부터 가로 85, 세로 60 만큼의 영역을 box로 잡아서 잘라버립니다. 예제 4번의 결과를 보겠습니다.

아까와는 다르게 85 by 60 의 직사각형이 제대로 crop 되었음을 볼 수 있습니다.