Python / Pillow / Colab

3주차 1교시: 디지털 이미지의 픽셀과 좌표

사진을 픽셀의 격자로 읽고, 코드가 이미지 안의 위치를 지정하는 좌표 규칙을 배웁니다.

정사각 픽셀 격자에서 원점과 좌표 관계를 보여 주는 3주차 1교시 이미지
왼쪽 위 원점과 픽셀 격자로 이미지를 읽는 출발점

디지털 이미지의 데이터 구조

핵심 개념
픽셀, 좌표, 튜플
이전 학습
변수, int, 실행 순서
확인 방법
크기와 유효 좌표
다음 학습
RGB와 Pillow 도형

학습 목표

  1. 래스터 이미지를 색상 값을 가진 픽셀의 격자로 설명
  2. 가로·세로 크기와 전체 픽셀 수 구분
  3. 왼쪽 위 원점과 x는 오른쪽, y는 아래쪽으로 증가하는 좌표 규칙 설명
  4. 이미지 크기와 마지막 픽셀 좌표 구분
  5. 위치 (x, y)와 색상 (R, G, B) 튜플의 구조 해석
  6. 2주차 정수 자료형과 이미지 크기·위치의 연결
  7. Colab에서 좌표 계산과 Image.new() 실행

학습 내용

값에서 이미지로의 확장

이 수업이 마지막에 만드는 것은 생성예술, 데이터 아트, 데이터 시각화처럼 눈에 보이는 콘텐츠입니다. 앞으로 배우는 반복, 조건, 함수는 모두 이미지 위에서 그 효과를 확인하고, 9주차부터 다루는 데이터도 그래프와 지도라는 이미지로 정리합니다. 2주차의 생활 데이터에서 픽셀로 급하게 옮겨 온 것처럼 보일 수 있지만, 이미지는 이 수업의 모든 결과물이 놓이는 바탕이므로 값과 변수 다음에 가장 먼저 익힐 대상입니다. 오늘은 그 첫걸음으로 이미지 안의 모든 위치에는 (x, y)라는 주소가 있다는 규칙을 익힙니다.

2주차에는 score = 10처럼 변수 하나에 값 하나를 담았습니다. 이미지도 같은 종류의 값으로 이루어져 있지만, 값의 개수가 훨씬 많습니다. 래스터 이미지는 픽셀의 격자이며, 격자의 칸마다 색상 값이 하나씩 저장됩니다. 가로 4칸, 세로 3칸 이미지라면 색상 값이 12개입니다.

사람은 사진에서 얼굴이나 풍경을 알아보지만, 파일에 얼굴이나 풍경이 저장되어 있지는 않습니다. 저장된 것은 가로·세로 픽셀 수각 위치의 색상 값뿐입니다. 코드가 다루는 대상도 이 숫자들입니다. 이미지를 밝게 만드는 코드도 사진을 통째로 다루지 않고, 모든 위치의 색상 값을 하나씩 바꿉니다.

숫자로 적힌 위치와 크기는 계산할 수 있습니다. “제목을 가운데에 둔다”는 결정은 눈대중이 아니라 가로 크기에서 제목의 폭을 뺀 나머지를 반으로 나누는 계산으로 적을 수 있고, 이미지 크기가 바뀌어도 같은 계산으로 다시 구할 수 있습니다. 프로그래밍으로 이미지를 만든다는 것은 이렇게 시각적 결정을 계산 가능한 규칙으로 적어 두는 일입니다.

이미지의 구조

픽셀, 래스터 이미지, 해상도

디지털 이미지의 기본 용어
용어이번 수업의 예
픽셀래스터 이미지 안에서 하나의 위치와 색상 값을 가지는 가장 작은 주소 단위(2, 1) 위치의 파란색 칸
래스터 이미지픽셀이 가로와 세로의 격자로 배열된 이미지사진, PNG, JPEG처럼 픽셀로 저장되는 이미지
해상도이미지를 구성하는 가로 픽셀 수 × 세로 픽셀 수800 × 600 픽셀
색상 값각 픽셀이 어떤 색으로 보일지 나타내는 데이터2교시에서 배울 (R, G, B)

픽셀은 래스터 이미지에서 좌표로 식별되는 색상 데이터 단위입니다. 격자의 각 위치에 색상 값이 저장되며, 확대 방식에 따라 개별 픽셀이 사각형 영역으로 표시될 수 있습니다. 픽셀을 이해할 때에는 표시되는 모양보다 위치와 데이터의 관계가 중요합니다.

풍경을 이루는 모자이크 전체에서 일부 격자를 확대하고, 그 안의 파란 타일 한 칸을 따로 살펴보는 모습
전체 이미지와 개별 픽셀

모자이크를 가까이 보면 색이 다른 타일의 배열이 드러납니다. 래스터 이미지도 전체 장면을 격자로 나누어 읽으며, 각 위치에 색상 값이 저장됩니다. 타일은 이 관계를 설명하는 비유이고, 실제 픽셀은 물리적인 조각이 아닌 데이터 단위입니다.

이미지의 일부를 수정하는 것은 특정 좌표의 색상 값을 갱신하는 작업입니다. 선과 원을 그리는 명령은 해당 형태에 포함되는 픽셀을 계산한 뒤 그 위치에 새로운 색상 값을 기록합니다.

800 × 600 이미지는 가로 800개, 세로 600개의 픽셀로 구성됩니다. 전체 픽셀 수는 800 * 600, 즉 480,000개입니다. 해상도는 기록할 수 있는 세부 정보의 양과 관련되지만, 그 자체가 작품의 완성도를 결정하지는 않습니다.

이번 실습은 픽셀 값을 기록하는 래스터 이미지를 대상으로 합니다. 벡터 그래픽과의 상세 비교, 표시 크기와 파일 용량의 차이는 본문 뒤 보충 설명에서 확인할 수 있습니다.

이미지 좌표

원점과 축 방향

래스터 이미지를 다루는 도구 대부분은 왼쪽 위 픽셀을 원점 (0, 0)으로 사용합니다. 첫 번째 숫자 x는 오른쪽으로 갈수록 커지고, 두 번째 숫자 y는 아래로 갈수록 커집니다.

왼쪽 아래 원점과의 혼동 주의

수학에서 양의 x·y 영역만 표시한 그래프에 익숙하면 왼쪽 아래를 (0, 0)으로 생각하기 쉽습니다. 그러나 이번 수업에서 다루는 이미지 좌표의 원점은 왼쪽 아래가 아니라 왼쪽 위입니다. 수학 좌표평면의 축 방향을 그대로 적용하지 않도록 주의합니다.

일반적인 수학 좌표평면에서는 y값이 위쪽으로 증가하지만, 이 수업의 이미지 좌표에서는 y값이 커질수록 아래쪽으로 이동합니다. 원점에서 아래로 한 칸 이동한 좌표는 (0, 1)입니다. 좌표를 해석하기 전에 원점의 위치와 각 축의 증가 방향을 먼저 확인합니다.

왼쪽 위 칸의 원점에서 오른쪽으로 향하는 코랄 화살표와 아래쪽으로 향하는 청록 화살표, 두 방향의 점선이 만나는 칸의 노란 말
원점과 두 방향의 위치 지정

왼쪽 위 칸을 기준으로 오른쪽 위치는 x, 아래쪽 위치는 y로 지정합니다. 노란 말의 위치는 두 방향을 함께 확인해야 정해집니다. 실제 코드에서는 이 두 값을 (x, y) 순서로 작성합니다.

수학 좌표평면과 디지털 이미지 좌표의 비교
항목 Mathematics Digital image
원점 x축과 y축의 교점 이미지의 왼쪽 위 픽셀
x 증가 오른쪽으로 이동 오른쪽으로 이동
y 증가 위쪽으로 이동 아래쪽으로 이동
주요 목적 위치와 관계를 수학적으로 표현 행과 열로 배열된 픽셀 위치를 지정

두 체계는 원점의 위치와 y의 증가 방향만 다릅니다. x는 양쪽 모두 오른쪽으로 증가합니다.

좌표의 표기 순서

(120, 80)은 “120번째 행, 80번째 열”이 아닙니다. 첫 값 120은 가로 방향인 x, 둘째 값 80은 세로 방향인 y입니다. 표나 배열을 설명할 때는 행을 먼저 말하기도 하지만, 이미지의 점 좌표는 (x, y) 순서로 읽습니다.

가로 4픽셀 × 세로 3픽셀 이미지의 모든 좌표
y \ x0123
0(0, 0)
왼쪽 위
(1, 0)(2, 0)(3, 0)
1(0, 1)(1, 1)(2, 1)(3, 1)
2(0, 2)(1, 2)(2, 2)(3, 2)
오른쪽 아래

표의 첫 행에는 y가 모두 0인 픽셀이 놓입니다. 같은 행에서 오른쪽으로 이동하면 x만 바뀝니다. 첫 열에는 x가 모두 0인 픽셀이 놓이며, 아래로 이동하면 y만 바뀝니다. 따라서 (3, 1)은 “오른쪽으로 3, 아래로 1 이동한 위치”라고 읽을 수 있습니다.

크기와 마지막 좌표

프로그래밍에서는 첫 번째 항목을 0부터 세는 경우가 많습니다. 따라서 가로가 width픽셀인 이미지의 x좌표는 0부터 width - 1까지입니다. 세로 좌표도 같은 원리로 0부터 height - 1까지입니다.

가로 4픽셀 이미지에는 픽셀이 네 개 있습니다. 첫 픽셀에 0이라는 주소를 부여하면 주소는 0, 1, 2, 3이 됩니다. 마지막 주소가 3이라고 해서 픽셀이 세 개라는 뜻은 아닙니다. 개수는 4이고 마지막 주소는 3입니다. 개수와 주소를 같은 값으로 생각하는 순간 이미지 오른쪽이나 아래쪽에서 한 칸씩 벗어나는 오류가 생깁니다.

Count

4 pixels

실제로 존재하는 픽셀의 개수입니다. width = 4로 표현합니다.

Last address

x = 3

0부터 주소를 붙였을 때 마지막 픽셀을 가리키는 값입니다.

이미지 크기와 사용할 수 있는 픽셀 좌표 범위
이미지 크기x 좌표 범위y 좌표 범위오른쪽 아래 픽셀
4 × 30~30~2(3, 2)
400 × 3000~3990~299(399, 299)
width × height0 ~ width - 10 ~ height - 1(width - 1, height - 1)

이미지 경계와 유효 픽셀 좌표

픽셀이 400개 있어도 0부터 세기 때문에 마지막 픽셀의 x좌표는 399입니다. 400은 이미지의 오른쪽 경계를 설명할 때는 쓸 수 있지만, 이미지 안의 개별 픽셀 주소로는 범위를 벗어납니다.

크기와 좌표의 코드 표현

이미지 크기와 개별 픽셀의 위치는 2주차에 학습한 정수 자료형(int)으로 표현할 수 있습니다. 값의 역할을 나타내는 변수명을 사용하면 크기와 위치를 구분해 관리할 수 있습니다.

2주차에서 print("이름:", name)처럼 함수 이름 뒤에 괄호를 붙여 실행한 것을 함수 호출이라고 하고, 괄호 안에 넣은 값을 인자라고 합니다. 이번 절의 코드는 대입 몇 줄과 함수 호출 한 줄로만 이루어집니다.

크기와 위치의 변수

2주차에서 학습한 대입은 오른쪽 값을 구한 뒤 왼쪽 변수와 연결하는 순서로 처리됩니다. 이 원리를 이용해 이미지의 크기와 점의 위치를 각각 변수로 표현합니다.

canvas_width = 400
canvas_height = 300

point_x = 120
point_y = 80

canvas_widthcanvas_height는 이미지의 가로·세로 픽셀 수이고, point_xpoint_y는 이미지 안에 있는 한 점의 좌표입니다. 크기는 전체 영역을, 좌표는 그 안의 위치를 지정합니다. 변수명에 역할을 드러내면 같은 정수 값이라도 용도를 구분할 수 있습니다.

크기·위치 변수와 값의 변화
변수명값의 의미다른 값을 유지하고 이 값만 증가시킨 경우
canvas_width이미지의 가로 픽셀 수이미지가 가로로 넓어짐
canvas_height이미지의 세로 픽셀 수이미지가 세로로 길어짐
point_x점의 가로 위치지정하는 위치가 오른쪽으로 이동
point_y점의 세로 위치지정하는 위치가 아래쪽으로 이동

값을 묶는 튜플

이미지의 크기는 가로와 세로를, 점의 위치는 x와 y를 함께 지정해야 합니다. 이처럼 여러 값을 정해진 순서로 묶어 표현할 때 튜플을 사용합니다. 이번 코드에서는 괄호 안의 값을 쉼표로 구분해 작성합니다.

size = (canvas_width, canvas_height)
position = (point_x, point_y)
color = (40, 110, 230)

앞서 대입한 변수의 값을 사용하므로 size(400, 300), position(120, 80)입니다. color는 같은 묶음 규칙이 색상에도 쓰인다는 점을 미리 보여 주는 예이며, 세 값이 색상에 미치는 영향은 2교시에서 살펴봅니다.

이미지 데이터에 사용하는 세 가지 튜플
변수와 값용도값의 순서
size = (400, 300)이미지 크기가로, 세로
position = (120, 80)점의 위치x, y
color = (40, 110, 230)색상R, G, B

튜플은 값의 개수와 순서가 중요합니다. 예를 들어 위치를 (80, 120)으로 바꾸면 x와 y가 서로 바뀌어 다른 점을 가리킵니다. 같은 두 값의 묶음이라도 크기로 쓰일 때는 가로·세로, 위치로 쓰일 때는 x·y로 해석하므로 사용 맥락을 함께 확인합니다.

2주차에 학습한 변수 출력을 이용해 이번에는 x와 y 두 값을 한 줄에서 확인합니다. 두 변수를 쉼표로 구분하면 작성한 순서대로 함께 출력됩니다. 앞에서 대입한 point_x = 120, point_y = 80을 사용합니다.

print(point_x, point_y)

120 80

이 호출은 두 값을 각각 인자로 전달합니다. 기본적으로 두 값 사이에는 공백이 들어가며 쉼표 자체는 출력되지 않습니다. 좌표를 확인할 때는 x, y 순서로 작성해 가로 위치와 세로 위치를 함께 읽습니다.

빈 화면에 점 하나를 놓으려면 어디에(위치 튜플)와 어떤 모습으로(색상 튜플)라는 두 정보가 필요하고, 이미지 처리 함수는 이 둘을 숫자로 받습니다. 여기까지 크기, 위치, 색상을 모두 값과 튜플로 적었으므로, 다음 절에서는 이 값들을 Image.new()에 전달해 실제 이미지를 만듭니다.

Pillow 이미지 생성

Pillow는 Python에서 이미지를 생성·편집·저장하는 라이브러리입니다. 코드에서는 PIL이라는 패키지명으로 기능을 불러옵니다. 먼저 Image 모듈을 사용해 크기와 배경색이 지정된 이미지를 만듭니다. 앞의 이미지 좌표 절에서 본 규칙과 같이 Pillow도 왼쪽 위를 원점 (0, 0)으로 사용합니다.

Colab 실습 준비

Colab에서 새 노트북을 엽니다. 이 노트북에서 빈 이미지 생성, 속성 확인, 좌표 계산을 순서대로 실행합니다. 코드 셀은 Shift+Enter 또는 셀 왼쪽 ▶ 버튼으로 실행합니다.

이미지 생성 코드 작성

Image.new()로 400 × 300 크기의 이미지를 생성합니다. 먼저 크기와 배경색을 변수로 지정한 뒤, 이 값을 이미지 생성 함수에 전달합니다. 아래 코드부터는 대입과 함수 호출이 함께 나오므로, 코드를 읽는 순서를 먼저 정리합니다.

코드 해석의 기본 절차

  1. 각 줄이 수행하는 동작을 확인하고, 줄 사이의 실행 순서를 파악합니다.
  2. 한 줄 안에서 변수명, 연산자, 값, 함수 호출이 각각 어떤 역할을 하는지 구분합니다.
  3. 대입문은 오른쪽 식의 값을 먼저 구한 뒤 왼쪽 변수에 대입하는 순서로 해석합니다.
  4. 함수에 전달하는 값을 인자라고 하며, 호출 괄호 안에 작성하고 여러 인자는 쉼표로 구분합니다.
  5. 오류가 발생하면 메시지에서 오류의 종류와 위치를 확인한 뒤, 문법과 앞선 코드의 실행 여부를 점검합니다.
from PIL import Image

canvas_width = 400
canvas_height = 300
background_color = (244, 239, 229)

image = Image.new(
    "RGB",
    (canvas_width, canvas_height),
    background_color
)

image

Image.new() 해석

이미지 생성 코드는 모듈 불러오기 → 값의 대입 → 이미지 생성 → 결과 표시로 구성됩니다. from PIL import Image는 이미지 모듈을 불러오고, Image.new()는 지정한 모드·크기·배경색으로 새 이미지를 생성합니다. Colab 코드 셀의 마지막 줄에 image를 작성하면 해당 이미지가 출력 영역에 표시됩니다.

이미지 생성 코드의 주요 구문
코드구문의 의미주의할 점
from PIL import ImagePillow가 제공하는 이미지 도구 Image를 현재 노트북으로 가져옴fromimport는 Python이 정한 단어이므로 번역하거나 바꾸지 않음
Image.newImage 도구에 들어 있는 새 이미지 만들기 기능을 선택Image의 첫 글자와 RGB는 대문자 그대로 작성
( ... )기능을 실행할 때 필요한 입력을 괄호 안에 전달여는 괄호와 닫는 괄호가 모두 있어야 함
,모드, 크기, 배경색이라는 세 입력의 경계를 구분줄이 바뀌어도 쉼표가 각 입력을 나눔
"RGB"R·G·B 세 채널 모드의 이름을 문자열로 전달따옴표를 포함해 작성
image = ...오른쪽에서 만든 이미지 결과를 왼쪽 변수 image에 저장이미지를 만들기 전에 결과가 저장되는 것이 아님
1 / Read values"RGB", (400, 300), background_color
모드·크기·배경색 준비
2 / MakeImage.new(...)
400 × 300 픽셀 이미지 생성
3 / Assignimage = 결과
image → 생성된 이미지

괄호 내부의 줄바꿈

Image.new("RGB", (400, 300), background_color)를 한 줄에 적어도 실행 결과는 같습니다. 수업 자료에서는 세 입력을 눈으로 구분하기 쉽도록 줄을 나누었습니다. 들여쓰기는 이 명령의 입력이 계속되고 있음을 보여줍니다. 닫는 괄호가 나오기 전까지는 같은 Image.new() 명령입니다.

Image.new()에 전달하는 세 가지 정보
코드역할연결되는 개념
"RGB"이미지가 색상을 저장하는 방식2교시 RGB 색상
(canvas_width, canvas_height)가로와 세로 픽셀 수해상도와 이미지 크기
background_color처음 모든 픽셀에 넣을 색픽셀의 색상 값

빈 이미지 생성

아래 코드를 새 셀에서 실행해 400 × 300 크기의 빈 이미지를 확인합니다. 배경색은 제공된 값을 사용하며, 세 채널의 의미와 색상 변경은 2교시에서 다룹니다.

코드 실행

Image.new() 실행

  1. 노트북 제목을 week03-period1-자기이름으로 지정합니다.
  2. 이미지 생성 코드를 새 셀에 입력하고 실행합니다.
  3. 셀의 출력 영역에 연한 배경색의 빈 이미지가 표시되는지 확인합니다.
from PIL import Image

canvas_width = 400
canvas_height = 300
background_color = (244, 239, 229)

image = Image.new(
    "RGB",
    (canvas_width, canvas_height),
    background_color
)

image

이미지 구조 확인

생성한 이미지의 속성은 코드로 확인할 수 있습니다. size는 가로·세로 픽셀 수, mode는 픽셀 데이터의 저장 방식이며, getbands()는 채널 이름을 반환합니다.

.은 대상의 속성이나 기능에 접근하는 표기입니다. image.size는 이미지의 크기 속성을 참조하고, image.getbands()는 채널 이름을 반환하는 메서드를 호출합니다. 메서드는 객체에 연결된 기능이며, 호출할 때 이름 뒤에 괄호를 사용합니다.

print("크기:", image.size)
print("모드:", image.mode)
print("채널:", image.getbands())
크기: (400, 300)
모드: RGB
채널: ('R', 'G', 'B')
이미지 객체에서 확인할 세 가지 정보
확인 코드괄호출력해석
image.size없음(400, 300)이미지가 이미 가진 크기 정보를 읽음
image.mode없음RGB이미지가 이미 가진 모드 정보를 읽음
image.getbands()있음('R', 'G', 'B')채널 이름을 돌려주는 기능을 실행

점 표기법의 대상과 속성

점 표기법은 대상.속성 또는 대상.메서드()의 구조입니다. image.size에서 image는 대상, size는 크기 속성입니다. size.image처럼 순서를 바꾸면 다른 대상을 참조하게 됩니다.

이 확인 과정은 오류를 찾을 때도 유용합니다. 예상한 크기와 실제 image.size가 다르면 이미지 생성 셀의 값을 확인해야 합니다. 색상 튜플을 세 값으로 작성했는데 이미지 모드가 RGB가 아니라면, 어떤 모드로 이미지를 만들었는지 다시 살펴볼 수 있습니다. 추측보다 현재 상태를 출력해 확인하는 습관이 안정적인 작업 흐름을 만듭니다.

크기 튜플과 색상 튜플

(canvas_width, canvas_height)는 가로·세로 크기 튜플이며, background_color에 대입한 (244, 239, 229)는 색상 튜플입니다. 두 튜플은 값의 개수와 각 위치의 의미가 다릅니다. RGB 채널별 값은 2교시에서 구체적으로 해석합니다.

생성 결과 확인

이미지의 크기·모드·채널

이미지 생성 셀 아래에 새 셀을 추가하고 확인 코드를 실행합니다.

print("크기:", image.size)
print("모드:", image.mode)
print("채널:", image.getbands())

크기: (400, 300)
모드: RGB
채널: ('R', 'G', 'B')

NameError와 선행 셀 실행

현재 런타임에서 이미지 생성 셀을 실행하지 않은 상태로 확인 셀을 실행하면 image를 참조할 수 없습니다. 이미지 생성 셀을 먼저 실행한 뒤 확인 셀을 실행합니다. 필요하면 런타임을 다시 시작하고 셀을 위에서 아래로 실행해 상태를 재현합니다.

좌표 계산

이미지의 크기와 좌표 범위를 확인했으므로, 변수와 산술 연산으로 위치를 계산합니다. 이 단원의 코드는 계산 결과를 출력하며, 이미지를 직접 수정하지는 않습니다.

계산식의 해석

가로 400픽셀 이미지의 마지막 x좌표를 변수에 저장한다면 다음처럼 작성할 수 있습니다. 한 줄을 세 단계로 나누면 계산과 대입을 혼동하지 않게 됩니다.

canvas_width = 400
last_x = canvas_width - 1
print(last_x)
1 / Findcanvas_width
현재 값 400 확인
2 / Calculate400 - 1
계산 결과 399
3 / Assignlast_x = 399
last_x → 399
산술 연산자의 의미와 결과
기호코드 예연산의 의미결과
*800 * 600800과 600의 곱480000
-400 - 1400과 1의 차399
+120 + 30120과 30의 합150
//600 // 2600을 2로 나눈 정수 몫300

Python의 곱셈 연산자

설명 문장에서는 이미지 크기를 800 × 600처럼 적지만, Python 코드에서 곱셈을 실행할 때에는 별표 *를 사용합니다. 키보드에 있는 문자 x나 인쇄용 기호 ×를 입력하면 곱셈으로 처리되지 않습니다.

좌표 이동 코드

좌표는 가로 위치와 세로 위치를 독립적으로 조정하는 기준입니다. 도형을 왼쪽으로 이동하려면 x값을 줄이고, 아래로 이동하려면 y값을 늘립니다. 두 축의 변화와 결과를 연결하면 위치를 의도에 맞게 수정할 수 있습니다.

Move right오른쪽으로 한 칸(x + 1, y)

x만 1 커지고 y는 그대로입니다.

Move left왼쪽으로 한 칸(x - 1, y)

x만 1 작아지고 y는 그대로입니다.

Move down아래로 한 칸(x, y + 1)

y가 1 증가하고 x는 유지됩니다.

Move up위로 한 칸(x, y - 1)

y가 1 작아집니다.

다음 코드는 점의 위치를 나타내는 두 정수 값을 변경합니다. (120, 80)에서 오른쪽으로 30픽셀, 위로 20픽셀 이동할 때의 좌표를 계산하며, 이미지에 점을 그리지는 않습니다.

point_x = 120
point_y = 80

point_x = point_x + 30
point_y = point_y - 20

print(point_x, point_y)
좌표 이동 코드가 실행되는 여섯 단계
실행 순서처리 내용좌표와 계산 결과
1. point_x = 120정수 120을 point_x에 대입x = 120
2. point_y = 80정수 80을 point_y에 대입(120, 80)
3. point_x + 30오른쪽의 기존 x값 120에 30을 더함계산 결과 150
4. point_x = 150계산 결과를 같은 이름에 다시 대입(150, 80)
5. point_y = point_y - 20기존 y값 80에서 20을 빼고 결과 60을 다시 대입(150, 60)
6. print(...)쉼표로 나눈 두 변수의 현재 값을 출력150 60

point_x = point_x + 30수학의 등식이 아니라 실행 순서가 있는 명령입니다. 오른쪽의 기존 값을 먼저 찾아 계산하고, 계산이 끝난 뒤 왼쪽 변수의 값을 바꿉니다. 반면 point_y는 위로 이동해야 하므로 값을 더하지 않고 뺍니다.

좌표 계산과 이미지 출력의 구분

이 코드는 점의 위치를 숫자로 계산하고 출력할 뿐, 이미지를 생성하거나 픽셀을 수정하는 명령은 포함하지 않습니다. 앞에서 만든 이미지도 이 계산만으로 바뀌지 않습니다. 좌표 계산과 이미지 수정은 서로 다른 단계입니다. 2교시에는 이 좌표를 draw.rectangle()이나 draw.ellipse() 같은 그리기 명령에 전달합니다.

점의 이동

같은 노트북에 새 셀을 추가해 좌표 이동 코드를 실행합니다.

코드 실행

(120, 80)의 이동 결과

  1. 같은 노트북의 새 코드 셀에 아래 코드를 입력합니다.
  2. Shift+Enter 또는 셀 왼쪽 ▶ 버튼으로 실행합니다.
  3. 출력이 150 60인지 확인합니다.
point_x = 120
point_y = 80

point_x = point_x + 30
point_y = point_y - 20

print(point_x, point_y)

150 60

실습 점검

  • 실행 표시가 유지되면 런타임 연결 상태와 실행 완료 여부를 확인합니다.
  • 출력이 없으면 print(point_x, point_y)까지 적었는지 확인합니다.
  • 이 코드는 이미지를 생성하지 않으며 계산된 좌표만 출력합니다.
개별 좌표 추적 · 3분

(1, 1)의 이동

  1. 오른쪽으로 두 칸 이동한 좌표를 적습니다.
  2. 그 위치에서 아래로 한 칸 이동한 좌표를 적습니다.
  3. 가로 4 × 세로 3 이미지 안에 남아 있는지 확인합니다.
이동 결과 확인

(1, 1)에서 오른쪽으로 두 칸 이동하면 (3, 1), 다시 아래로 한 칸 이동하면 (3, 2)입니다. 가로 4 × 세로 3 이미지의 유효 범위는 x가 0~3, y가 0~2이므로 이미지 안의 좌표입니다.

좌표와 화면 구성

정렬, 여백, 중심, 반복 간격과 같은 화면 구성 요소도 좌표의 관계로 표현할 수 있습니다. 왼쪽 배치는 상대적으로 작은 x값으로, 아래쪽 여백은 도형의 아래 경계와 캔버스의 아래 경계 사이 거리로 나타냅니다.

시각 구성과 좌표 관계
시각적 의도좌표로 생각하는 방법확인 질문
왼쪽 정렬여러 도형이 같은 시작 x값을 사용각 도형의 왼쪽 경계가 같은가?
일정한 위쪽 여백첫 도형의 y값을 여백 값으로 지정원점에서 도형까지의 거리가 충분한가?
화면 중심 배치캔버스 중심과 도형 중심을 일치가로와 세로 중심이 각각 맞는가?
규칙적인 간격다음 도형의 x 또는 y에 같은 값을 반복해 더함도형 사이의 차이가 일정한가?
비대칭 균형크기가 다른 도형을 서로 다른 영역에 배치수치가 달라도 시각적 무게가 균형을 이루는가?

마지막 행의 비대칭 균형은 좌표만으로 자동 판정할 수 없습니다. 좌표는 위치를 정확히 기록하지만, 어떤 구성이 더 안정적이거나 긴장감 있게 느껴지는지는 사람이 결과를 보고 판단해야 합니다. 프로그래밍은 미적 판단을 없애는 것이 아니라, 판단한 내용을 다시 실행할 수 있는 값으로 옮깁니다.

중심과 여백

좌표를 직접 정하는 첫 단계에서는 모든 값을 숫자로 적어도 됩니다. 그러나 캔버스 크기가 바뀔 때마다 중심과 여백을 다시 계산해야 한다면 변수를 사용하는 편이 안전합니다. 캔버스의 가로 중심은 canvas_width // 2, 세로 중심은 canvas_height // 2로 구할 수 있습니다.

정수 나눗셈 연산자 //

2주차의 /는 나눈 결과를 float로 만듭니다. 픽셀 위치를 정수로 유지하려면 //를 사용해 나눗셈의 정수 몫을 얻을 수 있습니다. 이번 주에는 캔버스의 중심처럼 정확한 정수 좌표가 필요할 때만 이 표기를 사용합니다.

canvas_width = 600
canvas_height = 400

center_x = canvas_width // 2
center_y = canvas_height // 2

print(center_x, center_y)
300 200

여백도 같은 방식으로 관계를 만들 수 있습니다. margin = 40이라고 정하면 왼쪽 위 안전 영역은 (40, 40)에서 시작합니다. 오른쪽 여백을 40만큼 남긴 위치는 canvas_width - margin, 아래쪽 여백을 40만큼 남긴 위치는 canvas_height - margin입니다.

margin = 40

left = margin
top = margin
right = canvas_width - margin
bottom = canvas_height - margin

print(left, top, right, bottom)
40 40 560 360

이 코드는 캔버스 크기와 여백 사이의 관계를 표현합니다. 가로·세로 값을 변경한 뒤 계산 코드를 다시 실행하면 같은 여백 기준에 맞춰 오른쪽과 아래쪽 경계가 계산됩니다. 변수의 값만 수정해도 기존 계산 결과가 자동으로 갱신되는 것은 아닙니다.

설계 기준선과 마지막 픽셀 좌표

canvas_width - margin으로 구한 560은 캔버스의 오른쪽 경계 600에서 40만큼 떨어진 설계 기준선입니다. 빈 픽셀을 좌우에 정확히 40개씩 남기고 픽셀 주소를 지정한다면 오른쪽에서 사용할 마지막 주소는 canvas_width - margin - 1, 즉 559입니다. 이번 활동에서는 화면 구성을 위한 기준선으로 560을 사용하고, 2교시의 도형 명령에서는 Pillow가 경계 상자의 끝점을 포함한다는 규칙을 다시 확인합니다.

단계별 계산 · 3분

800 × 500 캔버스의 안전 영역

사방에 50픽셀의 여백을 남긴 직사각형 영역을 설계합니다. 다음 네 값을 순서대로 계산합니다.

  1. left = margin
  2. top = margin
  3. right = canvas_width - margin
  4. bottom = canvas_height - margin
안전 영역 계산 확인

여백이 50이므로 왼쪽과 위쪽은 각각 50입니다. 오른쪽은 800 - 50 = 750, 아래쪽은 500 - 50 = 450입니다. 결과는 (50, 50, 750, 450)입니다. 이 네 값은 다음 교시에서 사각형과 타원의 경계 상자를 읽을 때 다시 사용합니다.

화면 구성 설계

앞에서 계산한 중심과 여백을 기준으로 600 × 400 캔버스에 기준점 하나를 정합니다. 기준점은 도형을 그리기 전에 정해 두는 자리이며, 2교시부터는 이 좌표가 도형의 왼쪽 위 모서리가 됩니다. 정렬, 중심, 여백 같은 시각적 의도를 계산 가능한 좌표로 옮기는 적용 단계이며, 조건은 다음과 같습니다.

먼저 사용할 수 있는 안전 영역을 계산합니다. 왼쪽과 위쪽은 40에서 시작하고, 오른쪽은 600 - 40 = 560, 아래쪽은 400 - 40 = 360입니다. 기준점은 x가 40~560, y가 40~360 사이에 있어야 합니다.

구성 의도와 좌표 예시
시각적 의도좌표 예시판단 근거
왼쪽의 주된 형태(150, 200)x가 중심 300보다 작고, y는 세로 중심에 가까움
오른쪽 위의 형태(450, 110)x가 중심보다 크고, y는 중심 200보다 작음
중심보다 조금 아래(320, 275)x는 중심에 가깝고, y가 세로 중심보다 75 큼

이 좌표들은 예시일 뿐입니다. 값은 안전 영역 안에 있다는 기술적 조건구성 의도에 맞는다는 표현적 조건을 함께 만족해야 합니다. 예를 들어 “오른쪽 위”를 의도하면서 y값을 330으로 두면 범위 안에는 있지만 의도에는 맞지 않습니다.

개별 설계 · 5분

주된 형태의 기준점

개별적으로 설계한 기준점을 3교시에서 사각형의 왼쪽 위 기준점으로 적용합니다. 점이 안전 영역 안에 있어도 도형 전체가 들어가는 것은 아니므로, 사각형의 크기와 여백을 함께 확인해 좌표를 조정하고 그 이유를 기록합니다. 이에 필요한 경계 상자와 도형 이동은 2교시에서 학습합니다.

  1. 주된 형태를 어느 영역에 둘지 의도를 한 구절로 정합니다.
  2. 그 의도에 맞는 기준점 좌표를 하나 정하고, x와 y가 안전 영역 안에 있는지 따로 확인합니다.
  3. 좌표가 의도에 맞는 이유를 한 문장으로 씁니다.
  4. 기준점을 30픽셀 이동하고, 어느 값을 어떻게 바꾸었는지 기록합니다. 예를 들어 (320, 275)를 오른쪽 위로 30픽셀씩 옮기면 x는 더하고 y는 빼서 (350, 245)가 됩니다.

핵심 정리

디지털 이미지는 정해진 크기의 픽셀 격자이며, 각 픽셀은 왼쪽 위 원점을 기준으로 한 좌표색상 값을 가집니다. 좌표를 사용한다는 것은 단순히 숫자를 입력하는 일이 아니라, 화면 구성의 의도를 반복 가능한 관계로 기록하는 일입니다.

보충 설명

이하 내용은 이미지의 저장 방식과 표시 방식을 구분하기 위한 참고 자료입니다. 좌표 계산과 빈 이미지 생성의 기본 절차를 마친 뒤 필요한 항목을 확인합니다.

래스터와 벡터

오늘 다루는 Pillow는 래스터 이미지를 처리합니다. 래스터는 각 위치의 픽셀 값을 기록합니다. 반면 벡터 그래픽은 선, 곡선, 도형의 수학적 관계를 기록합니다. 두 방식 가운데 하나가 항상 우수한 것은 아닙니다. 사진처럼 미세한 색 변화가 많은 장면은 래스터가 자연스럽고, 로고처럼 크기를 자주 바꾸는 단순한 형태는 벡터가 유리합니다.

래스터 이미지와 벡터 그래픽의 구조 비교
구분래스터 이미지벡터 그래픽
기록 단위좌표마다 저장된 픽셀의 색상 값점, 선, 곡선, 도형을 만드는 수학적 명령
확대할 때원래 픽셀 수보다 크게 표시하면 경계가 거칠어질 수 있음도형을 다시 계산하므로 다양한 크기에서 선명하게 표현 가능
적합한 예사진, 회화 스캔, 픽셀 아트, Pillow 결과 이미지로고, 아이콘, 다이어그램, 글자 윤곽선
대표 형식PNG, JPEGSVG
이번 주의 초점좌표와 RGB 값으로 픽셀을 생성개념 비교만 하고 직접 제작하지 않음

래스터와 벡터의 확대 방식

래스터 파일의 원은 이미 정해진 격자 안의 픽셀 값으로 저장되어 있습니다. 크게 확대하면 기존 픽셀도 함께 커집니다. 벡터 파일의 원은 중심과 반지름 같은 관계로 저장되어 있어 새로운 크기에 맞추어 경계를 다시 계산할 수 있습니다. 이번 주에는 Pillow가 계산한 도형을 최종적으로 래스터 픽셀에 기록합니다.

해상도, 표시 크기, 파일 용량

해상도는 가로·세로 픽셀 수, 표시 크기는 화면이나 문서에 표시되는 크기, 파일 용량은 저장에 필요한 바이트 수입니다. 세 값은 서로 다른 기준을 나타냅니다.

이미지의 크기를 말할 때 구분해야 하는 세 기준
기준질문달라지는 요인
픽셀 해상도몇 개의 픽셀로 이루어졌는가?800 × 600픽셀가로·세로 픽셀 수
표시 크기지금 화면에서 얼마나 크게 보이는가?웹페이지에서 가로 400픽셀로 표시브라우저, CSS, 화면 배율
파일 용량저장할 때 몇 바이트를 차지하는가?82KB 또는 1.2MB파일 형식, 압축 방식, 이미지 내용

예를 들어 800 × 600 이미지를 웹페이지에서 가로 400픽셀로 표시해도 원본이 가진 픽셀 수는 그대로입니다. 반대로 작은 원본을 크게 표시하면 화면에서 차지하는 공간은 커지지만 새로운 세부 정보가 저절로 생기지는 않습니다. 따라서 “크게 보인다”와 “많은 픽셀을 가진다”를 같은 뜻으로 사용해서는 안 됩니다.

픽셀 수와 채널 값의 개수

800 × 600 이미지는 480,000개의 픽셀로 구성됩니다. RGB 이미지에서는 픽셀마다 빨강, 초록, 파랑의 세 채널 값을 사용하므로 전체 채널 값의 개수는 480000 * 3, 즉 1,440,000개입니다.

픽셀 데이터와 압축 파일 용량

RGB 채널 값의 개수는 이미지 구조를 이해하기 위한 계산입니다. PNG와 JPEG 같은 파일은 픽셀 정보를 각기 다른 방식으로 압축하므로 실제 파일 용량은 이미지 내용과 저장 방식에 따라 달라집니다. 가로 × 세로 × 3의 결과를 그대로 PNG 파일 용량이라고 해석하지 않습니다.

학습 내용 점검

하나의 이미지에 대해 픽셀 수, 좌표 범위, 이동 결과를 함께 확인합니다.

핵심 개념 점검

  • 픽셀, 해상도, 좌표의 개념 구분
  • y값 증가에 따른 아래쪽 이동 예측
  • (width - 1, height - 1)을 이용한 마지막 픽셀 좌표 계산
  • 이미지 크기와 픽셀 위치의 정수 변수 표현
  • 위치 튜플과 RGB 튜플의 순서 구분
  • Colab에서 좌표 계산과 이미지 생성 결과 확인
개별 점검

6 × 4 이미지의 좌표

  1. 전체 픽셀 수를 계산합니다.
  2. 왼쪽 위와 오른쪽 아래 픽셀 좌표를 적습니다.
  3. (2, 1)에서 오른쪽으로 3칸, 아래로 2칸 이동한 좌표를 적습니다.
  4. 그 좌표가 이미지 안에 있는지 확인하고 이유를 씁니다.
정답 확인

전체 픽셀 수는 6 * 4 = 24개입니다. 왼쪽 위는 (0, 0), 오른쪽 아래는 (5, 3)입니다. (2, 1)에서 오른쪽으로 3칸, 아래로 2칸 이동하면 (5, 3)이므로 이미지 안의 마지막 픽셀입니다.

학습 범위

이번 교시의 핵심은 이미지를 좌표와 색상 값을 가진 픽셀 데이터로 이해하는 것입니다. RGB 채널 해석과 도형 생성은 다음 교시의 학습 내용입니다.

수업 후 개별 복습

유효 좌표 범위와 축 방향을 점검하는 복습 문제입니다. 각 항목을 해결한 뒤 해설과 비교합니다.

1. 800 × 600 이미지의 오른쪽 아래 픽셀 좌표는?

(799, 599)입니다. 가로와 세로 크기에서 각각 1을 뺍니다.

2. 800 × 600 이미지에서 (800, 200)은 이미지 안의 픽셀인가?

아닙니다. 유효한 x좌표는 0부터 799까지입니다. y좌표 200은 범위 안이지만 x좌표 800이 범위를 벗어납니다.

3. (120, 80)에서 아래로 25픽셀 이동한 좌표는?

(120, 105)입니다. 이미지 좌표에서는 아래로 이동할 때 y값을 더합니다.

4. 좌표 (40, 210)에서 40과 210은 각각 무엇을 뜻하는가?

40은 왼쪽에서 오른쪽으로 이동한 x 위치이고, 210은 위에서 아래로 이동한 y 위치입니다. 좌표는 항상 (x, y) 순서로 읽습니다.

2교시 학습 내용

2교시에서는 RGB 색상 튜플을 해석하고, ImageDraw로 사각형·타원·다각형을 생성합니다. 좌표와 색상 값을 도형 명령의 인자로 연결하는 과정이 핵심입니다.

참고 자료