RGB 데이터와 도형 생성
- 핵심 개념
- RGB, 색상 튜플, 도형
- 이전 학습
- 픽셀, 좌표, 유효 범위
- 도구
- Pillow Image, ImageDraw
- 연결 실습
- 기하학적 이미지 제작
학습 목표
- RGB를 빨강, 초록, 파랑 빛의 세 채널로 설명
0부터255까지의 세 정수로 색과 밝기 예측- RGB 튜플의 변수 대입과 재사용 원리 설명
Image.new()와ImageDraw.Draw()의 역할 구분- 사각형·타원·다각형의 좌표와 색상·윤곽선 인자 해석
학습 내용
- RGB와 색상 변화
세 채널의 의미와 단일 채널 변화 비교
- 색상 데이터
RGB 튜플·변수와 배경색 변경
- 이미지와 도구
이미지 생성과 그리기 도구 연결의 구분
- 사각형 생성과 수정
경계 상자 해석, 최초 실행과 재실행
- 도형과 화면 구성
타원·다각형, 겹침 순서와 팔레트 역할
- 결과 확인과 저장
전체 코드 실행, PNG 저장과 팔레트 비교
이미지 좌표 복습
1교시에서는 픽셀 격자의 구조와 왼쪽 위 원점 (0, 0)을 기준으로 한 좌표를 학습했습니다. RGB 색상 값을 해석하기 전에 원점, 유효 범위와 이동 규칙을 확인합니다.
좌표가 같아도 색상 값에 따라 픽셀의 표현은 달라집니다. 예를 들어 (120, 80) 위치에 검정, 빨강, 흰색을 지정하면 서로 다른 결과가 나타납니다. 좌표는 위치를, RGB 값은 해당 위치의 색상을 나타냅니다.
1. 이미지 좌표에서 (0, 0)은 어디인가?
이미지의 왼쪽 위입니다. x는 오른쪽, y는 아래쪽으로 증가합니다.
2. 500 × 300 이미지의 오른쪽 아래 픽셀 좌표는?
(499, 299)입니다. 각 크기에서 1을 뺀 값이 마지막 픽셀 주소입니다.
3. (80, 120)에서 오른쪽으로 30, 위로 20 이동하면?
(110, 100)입니다. 오른쪽 이동은 x에 더하고, 위쪽 이동은 y에서 뺍니다.
좌표와 색상의 역할
1교시에서는 background_color에 (244, 239, 229)를 대입하고, 이 변수를 Image.new()의 세 번째 인자로 전달했습니다. 이번 교시에서는 튜플의 각 값이 의미하는 색상 채널을 해석합니다.
RGB 원리
세 색상 채널
RGB는 빨강(Red), 초록(Green), 파랑(Blue)의 세 성분으로 색을 표현하는 방식입니다. 각 성분을 채널이라고 합니다. Pillow의 RGB 모드에서는 각 채널을 0부터 255까지의 정수로 나타냅니다.
세 채널의 값은 독립적으로 조절할 수 있습니다. R만 변경하면 빨강 성분이, G만 변경하면 초록 성분이 달라집니다. 색상은 한 채널의 값만으로 결정되지 않으므로 세 값의 상대적인 크기와 차이를 함께 확인합니다.
세 조명의 밝기를 각각 조절하듯 RGB도 세 채널의 값을 따로 바꿉니다. 빛이 같은 위치에 더해지면 다른 색이 나타나며, 세 채널이 모두 최대인 (255, 255, 255)는 흰색입니다. 물감의 혼합이 아니라 빛의 합성을 설명하는 비유입니다.
0: 해당 색의 빛을 켜지 않은 상태255: 해당 색의 빛을 가장 강하게 켠 상태(R, G, B): 항상 빨강, 초록, 파랑 순서로 세 값을 작성
8비트 채널과 값의 범위
Pillow의 일반적인 RGB 모드는 채널 하나를 8비트로 기록합니다. 8개의 이진 자리로 표현할 수 있는 경우는 2 ** 8 = 256가지이며, 0부터 시작하므로 값의 범위는 0~255가 됩니다. 세 채널이 각각 256가지 값을 가지므로 가능한 조합은 256 ** 3 = 16,777,216가지입니다.
| RGB 값 | 예상 색 | 켜진 채널 |
|---|---|---|
(0, 0, 0) | 검정 | 모두 꺼짐 |
(255, 255, 255) | 흰색 | 세 채널 모두 최대 |
(255, 0, 0) | 빨강 | R만 최대 |
(0, 255, 0) | 초록 | G만 최대 |
(0, 0, 255) | 파랑 | B만 최대 |
(255, 255, 0) | 노랑 | R과 G가 최대 |
(0, 255, 255) | 청록 | G와 B가 최대 |
(255, 0, 255) | 자홍 | R과 B가 최대 |
(128, 128, 128) | 중간 회색 | 세 채널의 밝기가 같음 |
가산 혼합과 물감 혼합의 차이
빨간 빛과 초록 빛을 강하게 더하면 노란 빛에 가까워집니다. 물감을 섞을 때의 경험과 결과가 다를 수 있으므로, 이번 수업에서는 빛의 세 채널 밝기로 판단합니다.
RGB 값의 해석
- 첫 번째는 R, 두 번째는 G, 세 번째는 B입니다.
- 가장 큰 값과 작은 값을 비교해 색상 계열을 예측합니다.
- 세 값이 같으면 검정부터 흰색까지의 무채색이 됩니다. 값의 차이가 생기면 색상 성분이 나타납니다.
| 값 | 채널 비교 | 예상 | 근거 |
|---|---|---|---|
(210, 70, 60) | R이 가장 큼 | 따뜻한 빨강 계열 | G와 B보다 R이 크게 우세함 |
(50, 120, 210) | B가 가장 큼 | 차가운 파랑 계열 | B가 우세하고 G가 일부 섞임 |
(220, 215, 205) | 세 값이 높고 가까움 | 밝고 따뜻한 회백색 | 전체 값이 높으며 R이 조금 더 큼 |
(35, 38, 42) | 세 값이 낮고 가까움 | 어두운 청회색 | 전체 값이 낮으며 B가 조금 더 큼 |
RGB 숫자는 색을 설명하는 정확한 데이터이지만, 숫자의 차이가 사람이 느끼는 밝기 차이와 언제나 같은 비율로 대응하는 것은 아닙니다. 또한 같은 값도 화면의 밝기와 색상 설정에 따라 조금 다르게 보일 수 있습니다. 이번 수업에서는 먼저 채널의 상대적 크기로 색의 방향을 예측하고 실제 결과를 확인하는 습관을 기릅니다.
단일 채널 변화 비교
색을 탐색할 때 세 값을 동시에 바꾸면 어떤 변화가 결과를 만들었는지 알기 어렵습니다. 먼저 기준색을 정하고 한 채널만 일정한 간격으로 바꾸면 숫자와 시각적 변화의 관계를 읽을 수 있습니다.
| 변형 | RGB 값 | 바꾼 값 | 예상 관찰 |
|---|---|---|---|
| 기준 | (220, 80, 60) | 없음 | R이 강한 따뜻한 색 |
| R 감소 | (160, 80, 60) | R만 -60 | 빨강의 우세가 줄어듦 |
| G 증가 | (220, 140, 60) | G만 +60 | 노랑·주황 방향의 성격이 강해짐 |
| B 증가 | (220, 80, 120) | B만 +60 | 세 채널 차이가 줄고 자홍 성분이 더해짐 |
채널 값을 비교해 색상의 변화를 예상한 뒤, 다음 단원의 배경색 변경 실습에서 실제 결과를 확인합니다.
색의 성격 예측
(240, 40, 40)은 어느 채널이 가장 강한가?(40, 40, 240)과 비교하면 어느 쪽이 파랑에 가까운가?(40, 40, 40)과(210, 210, 210)중 어느 쪽이 더 밝은 회색인가?(255, 180, 0)에서 B 값을 높이면 색의 성격은 어느 쪽으로 이동할지 예상합니다.
색상 분석 답 확인
(240, 40, 40)은 R이 가장 강해 빨강 계열입니다. (40, 40, 240)은 B가 가장 강해 파랑에 가깝습니다. (210, 210, 210)이 더 밝은 회색입니다. 마지막 색에서 B를 높이면 빨강과 초록만 강한 주황·노랑 계열에 파랑 성분이 더해집니다. B가 R과 G에 가까워질수록 세 채널의 차이가 줄어 색은 더 중성적으로 보입니다. 정확한 인상은 실제 결과를 함께 확인합니다.
색상 데이터와 변수
코드 해석·실행·수정 절차
- 명령의 역할과 전달하는 인자를 구분해 코드를 해석합니다.
- 제공된 코드를 먼저 실행해 기준 결과를 확인합니다.
- 위치·크기·색상 가운데 한 속성씩 변경하고, 다시 실행한 결과와 비교합니다.
RGB 튜플과 변수
RGB 튜플은 빨강, 초록, 파랑 채널 값을 정해진 순서로 저장합니다. (235, 86, 75)에서 R은 235, G는 86, B는 75입니다.
코드에서는 세 정수를 쉼표로 구분한 튜플을 변수에 대입합니다. 각 값의 순서는 R, G, B이며, 위치를 바꾸면 다른 색상이 됩니다.
RGB 채널의 정수 자료형
(235, 86, 75)의 세 값은 계산 가능한 정수입니다. ("235", "86", "75")처럼 따옴표를 붙이면 세 값이 숫자가 아니라 문자열이 되므로 Pillow의 RGB 색상 값으로 올바르게 사용할 수 없습니다. 설명 글자에는 따옴표를 쓰고, 채널 숫자에는 쓰지 않습니다.
color_a = (230, 70, 50)
빨강 계열: R 값이 가장 큽니다.
color_b = (50, 70, 230)
파랑 계열: 같은 세 숫자의 순서만 바뀌었습니다.
색상 튜플을 변수에 대입하면 여러 도형에서 같은 값을 재사용할 수 있습니다. 반복되는 RGB 숫자 대신 변수를 참조하면 색상 정의를 한곳에 모아 관리할 수 있습니다. 변경된 색상을 이미지에 반영하려면 해당 변수를 사용하는 그리기 코드도 다시 실행해야 합니다.
paper = (244, 239, 229)
coral = (235, 86, 75)
blue = (48, 95, 180)
ink = (28, 31, 38)
배경색 변경과 결과 확인
1교시의 빈 이미지 생성 코드를 이용해 RGB 값과 화면의 색상을 연결합니다. 기존 노트북을 계속 사용하며, 새 노트북을 사용하는 경우에도 아래 코드를 한 셀에 입력하면 실행할 수 있습니다.
단일 채널과 배경색
from PIL import Image
background_color = (220, 80, 60)
image = Image.new("RGB", (400, 300), background_color)
image
- 코드를 실행해 R이 우세한 배경색을 확인합니다.
background_color의 R 값만 220에서 160으로 변경합니다. G와 B 값은 유지합니다.- 색상 변수의 대입과 이미지 생성을 포함한 셀 전체를 다시 실행해 배경색을 비교합니다.
변수의 숫자만 수정해도 이미 표시된 이미지가 바뀌는 것은 아닙니다. 수정한 값을 사용해 이미지를 다시 생성해야 결과에 반영됩니다.
이미지와 그리기 도구
배경색 변경에는 Image.new()만 사용했습니다. 이제 이미지의 일부 영역에 도형을 그리기 위해 ImageDraw를 추가합니다. 이미지를 생성하는 기능과 그 이미지의 픽셀을 수정하는 기능을 구분합니다.
from PIL import Image, ImageDraw는 이미지 모듈과 그리기 모듈을 불러옵니다. 1교시의 Image에 ImageDraw가 추가된 구문입니다.
from PIL import Image, ImageDraw
image와 draw의 역할
Image.new()는 지정한 크기와 배경색으로 이미지를 생성합니다. 이어서 ImageDraw.Draw(image)를 호출하면 그 이미지에 연결된 그리기 도구가 생성됩니다. 두 함수는 서로 다른 결과를 반환합니다.
두 대입문은 오른쪽 함수 호출 → 반환값 확인 → 왼쪽 변수에 대입의 순서로 처리됩니다. image는 이미지를, draw는 해당 이미지에 연결된 그리기 도구를 참조합니다.
image는 색상 데이터가 남는 캔버스에, draw는 그 캔버스에 연결한 붓에 해당합니다. 도구를 준비하는 것만으로 그림이 생기지는 않습니다. draw.rectangle(...)을 실행하면 새 캔버스를 만드는 대신 연결된 이미지의 픽셀 값이 바뀝니다.
| 코드 | 1. 오른쪽 실행 | 2. 만들어지는 결과 | 3. 왼쪽에 저장 |
|---|---|---|---|
image = Image.new(...) | 모드·크기·배경색으로 Image.new() 실행 | 실제 픽셀을 가진 새 이미지 | 생성한 이미지를 image로 참조 |
draw = ImageDraw.Draw(image) | 이미 만들어진 image를 Draw()에 전달 | 그 이미지에 도형을 그릴 수 있는 도구 | 연결한 도구를 draw로 참조 |
ImageDraw 모듈과 draw 변수
ImageDraw는 Pillow의 모듈명이고, draw는 ImageDraw.Draw(image)의 반환값을 참조하는 변수명입니다. 이름의 역할과 대소문자를 구분해야 합니다.
준비 코드는 이미지와 그리기 도구를 생성하지만, 도형을 그리거나 결과를 표시하지는 않습니다. 코드 실행과 화면 출력은 별개의 단계이므로 출력이 없다는 사실만으로 오류를 판단할 수 없습니다.
도형 실습부터는 600 × 400 캔버스를 사용합니다. 아래 준비 코드처럼 새 셀에서 Image.new()를 다시 실행하면 image는 새 이미지를 가리키고, 이전 셀의 출력은 그대로 남습니다.
from PIL import Image, ImageDraw
canvas_width = 600
canvas_height = 400
background_color = (244, 239, 229)
image = Image.new(
"RGB",
(canvas_width, canvas_height),
background_color
)
draw = ImageDraw.Draw(image)
사각형의 생성과 수정
경계 상자
사각형과 타원은 네 숫자로 이루어진 경계 상자를 사용합니다. (left, top, right, bottom)은 왼쪽 경계의 x, 위쪽 경계의 y, 오른쪽 경계의 x, 아래쪽 경계의 y를 순서대로 기록합니다.
왼쪽 위와 오른쪽 아래 두 모서리로 도형이 들어갈 범위를 정합니다. 틀의 가로·세로 길이가 달라지면 그 안에 들어가는 도형의 비율도 달라집니다. 사각형과 타원은 모두 이런 경계 상자를 사용합니다. 나무 틀은 범위를 보여 주는 비유이며 실제 이미지에 자동으로 그려지는 테두리는 아닙니다.
| 값 | 의미 | 화면에서의 위치 |
|---|---|---|
left = 180 | 도형이 시작하는 왼쪽 x좌표 | 원점에서 오른쪽으로 180픽셀 |
top = 120 | 도형이 시작하는 위쪽 y좌표 | 원점에서 아래로 120픽셀 |
right = 380 | 도형이 끝나는 오른쪽 x좌표 | 왼쪽보다 오른쪽에 있어야 함 |
bottom = 320 | 도형이 끝나는 아래쪽 y좌표 | 위쪽보다 아래에 있어야 함 |
경계 상자의 끝점 포함 규칙
Pillow의 ImageDraw.rectangle() 경계 상자는 시작점과 끝점을 모두 포함합니다. 따라서 (40, 40, 259, 179)는 정확히 가로 220 × 세로 140픽셀입니다. 이번 실습에서는 우선 네 숫자를 도형을 감싸는 왼쪽·위·오른쪽·아래 경계로 읽습니다.
draw.rectangle() 해석
draw.rectangle()는 그리기 도구 draw의 사각형 그리기 메서드를 호출합니다. 괄호 안에는 좌표와 색상을 인자로 전달합니다.
draw.rectangle((40, 40, 260, 180), fill=coral)
| 코드 | 역할 | 구문의 의미 |
|---|---|---|
draw | 앞에서 이미지와 연결한 그리기 도구 | 이미지에 연결된 대상 |
. | 앞의 대상에서 뒤의 기능을 선택 | 대상의 메서드 접근 |
rectangle | 사각형을 그리는 기능 이름 | 사각형 그리기 메서드 |
( ... ) | 기능 실행에 필요한 입력의 시작과 끝 | 인자를 전달하는 호출 괄호 |
(40, 40, 260, 180) | 사각형이 들어갈 경계 상자 | 왼쪽·위·오른쪽·아래 경계 |
fill=coral | 내부색 입력의 이름과 값 | 내부색으로 coral 값 사용 |
이 명령은 (40, 40, 260, 180) 영역의 픽셀을 coral 값으로 채웁니다. 점 .은 대상의 속성이나 메서드에 접근하는 표기이며, rectangle()는 연결된 이미지를 직접 수정합니다. 수정된 결과는 image로 확인합니다.
대입과 키워드 인자의 구분
coral = (235, 86, 75)의 =은 값을 변수에 연결하는 대입 연산자입니다. 반면 함수 호출 내부의 fill=coral은 인자의 이름과 값을 함께 지정하는 키워드 인자입니다. coral의 값을 내부색 인자 fill에 전달하며, 별도의 fill 변수를 정의하지 않습니다.
사각형 생성 실습
먼저 제공된 좌표와 색상으로 사각형 하나를 생성합니다. 이 단계에서는 값을 변경하지 않고, 빈 이미지에 도형이 추가되는 결과를 확인합니다.
빈 이미지 위의 사각형
- 아래 코드를 한 줄씩 읽은 뒤 새 셀에 적고 실행합니다.
- 연한 배경의 왼쪽 위에 코랄색 사각형이 표시되는지 확인합니다.
from PIL import Image, ImageDraw
canvas_width = 600
canvas_height = 400
background_color = (244, 239, 229)
coral = (235, 86, 75)
image = Image.new(
"RGB",
(canvas_width, canvas_height),
background_color
)
draw = ImageDraw.Draw(image)
draw.rectangle((40, 40, 260, 180), fill=coral)
image
이미지 재생성과 상태 변화
Image.new()를 다시 실행하면 같은 변수명 image에 새로운 빈 이미지가 대입됩니다. 이전 이미지에 그려 두었던 도형이 새 이미지로 자동 이동하지는 않습니다. 이어서 ImageDraw.Draw(image)도 다시 실행해 새 이미지에 그리기 도구를 연결해야 합니다.
image = Image.new(...)draw.rectangle(...)image = Image.new(...)이 동작은 오류가 아니라 대입의 결과입니다. 2주차에 score = 10 다음 score = 20을 실행하면 새 값이 남았던 것과 같습니다. 이미지 역시 변수에 저장된 값이므로 새 이미지를 대입하면 현재 image가 가리키는 대상이 바뀝니다.
이미지 재생성과 실행 순서
좌표나 색상을 수정한 뒤에는 변수 대입 → 이미지 생성 → 그리기 도구 연결 → 도형 그리기 → 표시의 순서로 셀 전체를 다시 실행합니다. 이전 픽셀이 남지 않은 새 이미지에서 그려야 수정 결과를 정확히 비교할 수 있습니다. PNG 저장은 전체 구성을 완성한 뒤 다룹니다.
사각형의 좌표 수정
사각형의 크기를 유지하면서 이동하려면 왼쪽 위와 오른쪽 아래의 두 모서리에 같은 이동량을 적용합니다. 한쪽 모서리만 변경하면 위치뿐 아니라 크기도 달라집니다.
사각형의 평행 이동
- 기준 사각형의 경계 상자
(40, 40, 260, 180)를 확인합니다. - 왼쪽 위를 1교시의 예시 기준점
(150, 200)으로 이동하려면 x에 110, y에 160을 더합니다. - 두 모서리에 같은 이동량을 적용해 전체 경계 상자를
(150, 200, 370, 340)으로 변경합니다. - 앞의 사각형 생성 셀 전체를 다시 실행하고, 크기는 유지되며 위치만 바뀌었는지 확인합니다.
3교시에서는 1교시에서 개별 설계한 기준점 하나를 사각형의 왼쪽 위 기준점으로 사용합니다. 사각형 전체가 여백 안에 들어오도록 기준점을 조정한 뒤, 두 모서리를 함께 이동하는 원리를 적용합니다.
타원과 다각형
경계 상자와 타원의 비율
draw.ellipse()는 지정한 경계 상자에 맞는 타원을 그립니다. 사각형과 좌표 형식은 같지만, 영역 전체를 채우는 대신 타원 내부의 픽셀을 채웁니다. 예제의 blue는 앞에서 정의한 파란색 튜플입니다.
앞에서 살펴본 (180, 120, 380, 320) 경계 상자의 가로 차이는 380 - 180 = 200, 세로 차이는 320 - 120 = 200입니다. 가로와 세로가 같으므로 draw.ellipse()를 사용하면 원이 됩니다. 두 차이가 다르면 타원이 됩니다. 예를 들어 (180, 120, 480, 320)은 가로 차이 300, 세로 차이 200이므로 가로로 긴 타원을 만듭니다.
두 예제는 각각 빈 이미지에서 실행해 비교합니다. 앞의 이미지와 그리기 도구 준비 코드를 다시 실행한 뒤, 아래 명령 중 하나를 새 셀에 입력하고 마지막 줄에 image를 추가해 결과를 확인합니다.
draw.ellipse((180, 120, 380, 320), fill=blue)
가로 차이 200, 세로 차이 200으로 같은 비율입니다.
draw.ellipse((180, 120, 480, 320), fill=blue)
가로 차이 300, 세로 차이 200으로 가로가 더 깁니다.
다각형의 꼭짓점
draw.polygon()은 경계 상자 대신 여러 점의 좌표를 받습니다. 첫 점에서 둘째 점, 둘째 점에서 셋째 점으로 선을 잇고, 마지막 점에서 첫 점으로 돌아와 형태를 닫습니다. 삼각형에는 세 점, 사각형에는 네 점이 필요합니다.
먼저 다각형 내부에 사용할 노란색을 yellow에 대입합니다. 테두리에는 앞에서 정의한 짙은 색상 ink를 사용합니다.
yellow = (244, 190, 55)
triangle_points = (
(420, 70),
(560, 260),
(350, 260)
)
draw.polygon(
triangle_points,
fill=yellow,
outline=ink
)
코드를 실행하면 현재 이미지에 삼각형이 추가됩니다. 마지막 줄에 image를 추가해 내부 색상과 테두리를 확인합니다.
| 코드 범위 | 묶는 대상 | 의미 |
|---|---|---|
triangle_points = ... | 오른쪽 전체 값 | 꼭짓점 튜플을 triangle_points에 대입 |
가장 바깥쪽 ( ... ) | 꼭짓점 세 개 | 삼각형을 만드는 전체 점 목록 |
(420, 70) | 첫 번째 점의 x와 y | 오른쪽 420, 아래 70 위치의 꼭짓점 |
(560, 260) | 두 번째 점의 x와 y | 오른쪽 아래 방향의 꼭짓점 |
(350, 260) | 세 번째 점의 x와 y | 왼쪽 아래 방향의 꼭짓점 |
안쪽 튜플은 한 꼭짓점의 x·y 좌표를 나타내고, 바깥쪽 튜플은 꼭짓점들을 순서대로 저장합니다. 이 구조를 통해 점의 좌표와 도형의 연결 순서를 함께 지정합니다.
단순 다각형의 꼭짓점은 윤곽을 따라 연결되는 순서로 작성합니다. 순서가 달라지면 선분이 교차해 의도와 다른 형태가 생길 수 있으므로, 코드 작성 전에 각 점과 연결 순서를 확인합니다.
선의 경로와 색상
draw.line(((40, 340), (560, 340)), fill=ink, width=6)은 (40, 340)에서 (560, 340)까지 가로선을 그립니다. 선은 내부 면적이 없으므로 fill이 선의 색을 뜻합니다. 3교시에는 이와 같은 기준선이 제공되며, 선의 좌표와 두께를 지정하는 코드는 유지합니다.
도형의 색상과 윤곽
fill=coral도형 안쪽 픽셀을 지정한 RGB 색상으로 채웁니다.
outline=ink도형의 바깥 경계를 지정한 색으로 그립니다.
width=4테두리의 두께를 픽셀 단위 정수로 지정합니다.
(40, 40, 260, 180)좌표 데이터로 도형이 차지할 영역을 정합니다.
세 도형의 결합
| 명령 | 위치 데이터 | 읽는 방법 |
|---|---|---|
rectangle | (left, top, right, bottom) | 왼쪽 위와 오른쪽 아래 경계로 사각형 영역을 정함 |
ellipse | (left, top, right, bottom) | 같은 경계 상자 안에 꼭 맞는 타원 또는 원을 그림 |
polygon | ((x1, y1), (x2, y2), ...) | 여러 꼭짓점을 작성한 순서대로 연결해 닫힌 도형을 그림 |
다음은 사각형·타원·다각형을 함께 그리는 코드입니다. 앞의 사각형 생성 셀에서 좌표를 기준값 (40, 40, 260, 180)으로 되돌린 뒤 셀 전체를 다시 실행하고, 새 셀에 아래 코드를 입력합니다. 같은 이미지 위에 세 도형이 순서대로 추가됩니다.
함수 인자와 쉼표
경계 상자 뒤, fill 뒤, outline 뒤의 쉼표는 각 입력을 분리합니다. 괄호 안에서 줄을 나누어 작성할 때에도 쉼표를 유지해야 합니다. 마지막 width=4 뒤의 쉼표는 생략할 수 있지만, 수업 코드에서는 다음 줄을 추가하기 쉽도록 남겨 둘 수 있습니다.
coral = (235, 86, 75)
blue = (48, 95, 180)
yellow = (244, 190, 55)
ink = (28, 31, 38)
draw.rectangle(
(40, 40, 260, 180),
fill=coral,
outline=ink,
width=4
)
draw.ellipse(
(180, 120, 380, 320),
fill=blue
)
draw.polygon(
((420, 70), (560, 260), (350, 260)),
fill=yellow
)
도형 명령만으로는 새 출력이 표시되지 않습니다. 위 코드의 마지막에 image를 별도의 줄로 추가하고 셀을 실행해 현재 결과를 확인합니다. 이미 표시된 이전 셀의 이미지는 자동으로 갱신되지 않습니다.
그리기 순서
현재 수업의 불투명 RGB 도형은 기존 픽셀 위에 새 색상 값을 기록합니다. 두 도형이 겹치면 코드에서 나중에 실행한 도형이 겹친 부분에서 앞 도형을 가립니다.
이 방식은 종이에 물감을 올리는 순서와 비슷해 페인터스 알고리즘이라고 설명할 수 있습니다. 먼저 그린 형태는 아래에 놓이고, 나중에 그린 형태는 그 위에 놓입니다. 별도의 레이어 패널이 없어도 코드의 실행 순서가 시각적 앞뒤 관계를 만듭니다.
각 줄을 왼쪽에서 오른쪽으로 읽습니다. 위쪽은 원을 나중에, 아래쪽은 사각형을 나중에 그렸습니다. 같은 위치와 색상이라도 순서가 바뀌면 겹친 부분의 색이 달라집니다. 불투명 RGB 이미지에서는 물감처럼 색을 섞거나 도형을 별도 레이어로 보관하는 것이 아니라, 해당 픽셀을 나중에 지정한 색으로 덮어씁니다.
draw.rectangle((40, 40, 260, 180), fill=coral)
draw.ellipse((180, 120, 380, 320), fill=blue)
겹친 부분에서는 나중에 그린 파란 타원이 보입니다.
draw.ellipse((180, 120, 380, 320), fill=blue)
draw.rectangle((40, 40, 260, 180), fill=coral)
좌표가 같아도 겹친 부분에서는 나중에 그린 코랄 사각형이 보입니다.
두 줄의 순서 교체
색상과 좌표는 그대로 두고 파란 원이 코랄 사각형 뒤로 가게 하려면 어느 두 줄의 순서를 바꾸어야 하는지 적습니다. 코드는 위에서 아래로 실행된다는 2주차 원리를 사용합니다.
그리기 순서 답 확인
파란 원을 먼저 그리고 코랄 사각형을 나중에 그립니다. Pillow에서 별도의 레이어 패널을 조작하는 것이 아니라, 코드 줄의 실행 순서가 앞뒤 관계를 만듭니다.
화면 구성과 팔레트
팔레트의 역할
팔레트는 화면에 사용할 색상의 집합입니다. 이 실습에서는 색상을 배경색, 주조색, 보조색, 강조색, 윤곽색으로 구분합니다. 각 역할에 변수를 연결하면 색상이 달라져도 화면의 구성 체계를 유지할 수 있습니다.
| 역할 | 변수 예 | 사용 원칙 | 확인할 질문 |
|---|---|---|---|
| 배경색 | background_color | 가장 넓은 면적을 차지하며 다른 색의 기준이 됨 | 주요 도형이 배경과 구분되는가? |
| 주조색 | primary_color | 큰 형태 또는 중심 형태에 사용 | 화면의 첫인상을 형성하는가? |
| 보조색 | secondary_color | 주조색과 차이를 만들되 경쟁하지 않게 사용 | 주요 형태와 관계가 읽히는가? |
| 강조색 | accent_color | 작은 면적에 제한적으로 사용해 시선을 모음 | 어디를 먼저 보아야 하는지 분명한가? |
| 윤곽색 | outline_color | 배경과 도형 모두에서 경계가 보이도록 선택 | 얇은 선도 충분히 구분되는가? |
background_color = (244, 239, 229)
primary_color = (235, 86, 75)
secondary_color = (48, 95, 180)
accent_color = (244, 190, 55)
outline_color = (28, 31, 38)
coral이나 blue처럼 색 자체를 이름으로 사용할 수도 있지만, primary_color와 accent_color처럼 역할로 이름을 정하면 팔레트 전체를 다른 색조로 바꾸기 쉽습니다. 강조색을 노랑에서 연두로 바꾸어도 도형 코드에서는 계속 accent_color라는 같은 의미를 유지할 수 있습니다.
색상·명암·형태의 구분
서로 다른 RGB 값을 사용해도 두 색의 밝기가 비슷하면 경계가 약하게 보일 수 있습니다. 특히 작은 글자나 얇은 선은 배경과 충분한 명암 차이가 필요합니다. 이번 기하학 이미지에서는 색뿐 아니라 크기, 위치, 윤곽선도 함께 사용해 형태를 구분합니다.
권장 그리기 순서
모든 도형을 임의의 순서로 나열하기보다 화면의 구조에 따라 순서를 정하면 코드를 읽기 쉽습니다. 일반적인 출발 순서는 배경 → 큰 면 → 보조 형태 → 작은 강조 → 윤곽과 선입니다. 반드시 지켜야 하는 규칙은 아니지만, 나중에 무엇이 무엇을 가리는지 예측하기 쉬운 기준이 됩니다.
| 순서 | 요소 | 역할 | 코드 예 |
|---|---|---|---|
| 1 | 배경 | 전체 화면의 기본 톤 | Image.new(..., background_color) |
| 2 | 큰 사각형 | 화면의 주요 무게와 방향 설정 | draw.rectangle(...) |
| 3 | 원 또는 타원 | 직선 구조와 대비되는 곡선 추가 | draw.ellipse(...) |
| 4 | 작은 다각형 | 시선을 모으는 강조점 생성 | draw.polygon(...) |
| 5 | 선과 윤곽 | 정렬 기준이나 경계 강조 | draw.line(...) |
형태가 앞에 있다는 사실과 시선이 먼저 간다는 사실은 완전히 같지 않습니다. 작은 노란 삼각형은 가장 나중에 그려져 앞에 놓이더라도, 면적이 큰 파란 원보다 반드시 강하게 보인다고 단정할 수 없습니다. 색 대비, 크기, 위치, 주변 여백이 함께 시각적 위계를 만듭니다. 코드는 순서를 정하고, 최종 위계는 결과를 보며 조정합니다.
전체 코드와 실행 결과
아래 코드는 기하학적 이미지 제작의 기준 예제입니다. 크기와 팔레트 설정 → 이미지 생성 → 도형 배치 → 결과 확인 → 파일 저장의 흐름을 확인합니다. 먼저 제공된 값 그대로 실행해 예상 이미지와 PNG 파일이 만들어지는지 확인하고, 그 뒤에 수정할 속성을 구분합니다. 기준 결과가 있어야 입력 오류와 구성 변경의 영향을 구분할 수 있습니다.
| 학습 내용 | 확인 사항 | 3교시 적용 |
|---|---|---|
| 기준점 설계 | 기준점 하나의 좌표와 배치 의도 | 그 점을 사각형의 왼쪽 위 기준점으로 사용 |
| 경계 상자와 이동 | 왼쪽 위·오른쪽 아래 좌표의 관계 | 가로·세로 크기를 유지한 사각형의 위치 변경 |
| 안전 영역과 여백 | 기준점뿐 아니라 도형 전체의 범위 | 여백 확보를 위한 기준점 조정과 이유 기록 |
전체 코드의 단계별 구성
전체 코드는 주석으로 구분한 일곱 개의 작업 단계로 구성됩니다. 각 단계에서 생성하거나 수정하는 값과 이미지를 확인하면서 위에서 아래로 실행 순서를 추적합니다.
| 표기 | Python의 처리 | 학생이 활용하는 방법 |
|---|---|---|
# 설명 | # 뒤부터 줄 끝까지 실행하지 않음 | 다음 코드 묶음의 목적을 먼저 읽음 |
| 빈 줄 | 실행 결과에 영향을 주지 않음 | 준비·도형·출력 같은 단계의 경계로 봄 |
| 괄호 안의 들여쓰기 | 괄호가 닫힐 때까지 같은 명령의 입력으로 처리 | 좌표·색상·두께를 한 줄씩 구분해 읽음 |
| 위에서 아래의 줄 순서 | 앞에서 만든 값과 상태를 다음 줄이 사용 | 도구 → 이미지 → 도형 → 출력 순서를 유지 |
from PIL import Image, ImageDraw
# 1. 크기와 팔레트
canvas_width = 600
canvas_height = 400
background_color = (244, 239, 229)
primary_color = (235, 86, 75)
secondary_color = (48, 95, 180)
accent_color = (244, 190, 55)
outline_color = (28, 31, 38)
# 2. 빈 이미지와 그리기 도구
image = Image.new(
"RGB",
(canvas_width, canvas_height),
background_color
)
draw = ImageDraw.Draw(image)
# 3. 큰 사각형으로 기본 구조 만들기
draw.rectangle(
(50, 60, 330, 240),
fill=primary_color,
outline=outline_color,
width=4
)
# 4. 곡선 형태를 겹쳐 대비 만들기
draw.ellipse(
(230, 100, 510, 360),
fill=secondary_color,
outline=outline_color,
width=4
)
# 5. 작은 삼각형으로 강조점 만들기
triangle_points = (
(390, 55),
(560, 220),
(340, 220)
)
draw.polygon(
triangle_points,
fill=accent_color,
outline=outline_color,
width=4
)
# 6. 아래쪽 기준선 추가하기
draw.line(
((40, 340), (560, 340)),
fill=outline_color,
width=6
)
# 7. 결과 확인과 PNG 파일 저장
display(image)
image.save("week03_학번_이름.png")
실행 상태 추적
| 단계 | 컴퓨터 내부에서 달라진 것 | Colab 화면에서 즉시 보이는 것 |
|---|---|---|
| 1. 도구 가져오기 | Image와 ImageDraw 이름을 사용할 수 있게 됨 | 정상이라면 별도 출력 없음 |
| 2. 크기와 팔레트 | 일곱 개 변수에 숫자와 RGB 튜플이 저장됨 | 별도 출력 없음 |
| 3. 이미지 생성 | 600 × 400 배경 이미지가 image에 저장됨 | 아직 display() 전이므로 보이지 않음 |
| 4. 도형 그리기 | 사각형·타원·삼각형·선이 같은 image의 픽셀을 차례로 수정 | 각 명령마다 자동 미리보기되지 않음 |
5. display(image) | 현재 이미지 상태는 그대로 유지 | 완성된 이미지가 셀 아래에 표시됨 |
6. image.save(...) | 현재 이미지가 PNG 파일로 기록됨 | 파일 목록에서 파일명을 확인할 수 있음 |
미리보기와 저장
display(image)는 현재 런타임 메모리에 있는 이미지를 노트북 화면에 보여줍니다. 이 출력만으로는 제출할 PNG 파일이 만들어지지 않습니다. image.save("week03_학번_이름.png")를 실행해야 현재 이미지가 파일로 기록됩니다.
Pillow의 save()는 별도의 형식을 지정하지 않으면 파일명의 확장자를 보고 저장 형식을 결정합니다. 이번 주에는 면 색과 윤곽선이 분명한 기하학 이미지이므로 .png를 사용합니다. 파일명을 .jpg로 바꾸는 것은 단순히 글자만 바꾸는 일이 아니라 다른 저장 형식을 선택하는 일입니다.
| 코드 | 역할 | 구문의 의미 |
|---|---|---|
display | Colab 출력 영역에 이미지 등을 표시하는 기능 | 출력 영역에 결과 표시 |
(image) | 보여 줄 대상을 괄호 안에 전달 | 출력 대상 이미지 |
image. | 저장 기능을 사용할 대상 | 저장할 이미지 객체 |
save | 이미지 파일을 기록하는 기능 | 이미지 저장 메서드 |
("week03_학번_이름.png") | 파일명을 문자열 입력으로 전달 | 저장 파일명 지정 |
.png | 파일 형식을 나타내는 확장자 | PNG 저장 형식 지정 |
파일명 구분과 결과 보관
수정 전후를 비교하려면 result_a.png, result_b.png처럼 파일명을 구분합니다. 같은 경로에 같은 파일명으로 저장하면 기존 파일을 덮어씁니다. Colab 런타임의 파일은 영구 보관되지 않으므로 완성한 PNG를 자신의 컴퓨터에 다운로드합니다.
코드 수정 범위
2교시의 기준 코드에서는 색상·좌표·두께·파일명을 수정 대상으로 구분합니다. 라이브러리와 메서드의 이름, 괄호·쉼표 등의 구문은 유지합니다. 수정 대상과 문법 요소를 구분하면 의도한 변화의 원인을 추적하기 쉽습니다.
| 구분 | 코드 예 | 이번 실습의 행동 | 이유 |
|---|---|---|---|
| 수정 | (235, 86, 75) | 0~255 안에서 채널 값 하나 변경 | 도형의 색을 조절하는 데이터 |
| 수정 | (50, 60, 330, 240) | 위치 변경은 두 모서리를 같은 거리만큼 이동, 크기 변경은 경계 간격 조정 | 위치와 크기의 변화를 구분하기 위한 좌표 데이터 |
| 수정 | width=4 | 4를 2 또는 8처럼 양의 정수로 변경 | 윤곽선 두께를 조절하는 데이터 |
| 수정 | "week03_학번_이름.png" | 따옴표와 .png는 남기고 학번·이름 교체 | 제출 파일을 식별하기 위한 문자열 |
| 유지 | from, import, PIL | 철자와 대소문자를 그대로 유지 | Python과 라이브러리가 정한 이름 |
| 유지 | Image.new, draw.rectangle | 기능 이름과 점을 그대로 유지 | 실행할 기능을 찾는 경로 |
| 유지 | 괄호, 쉼표, 따옴표 | 여는 기호·닫는 기호와 입력 구분을 유지 | 코드 구조를 Python에 전달하는 문법 |
빨강 채널 변화와 결과 예측
primary_color = (235, 86, 75)에서 첫 값 235만 175로 바꿉니다. 실행하기 전에 어느 도형이 바뀌는지, R의 우세가 강해질지 약해질지 적습니다. 그다음 변수 대입부터 이미지 생성과 도형 그리기를 다시 실행해 실제 결과를 비교합니다.
빨강 채널 수정 결과
primary_color를 사용하는 큰 사각형의 색이 바뀝니다. R은 235에서 175로 줄고 G와 B는 그대로이므로 빨강 채널의 우세가 약해집니다. 타원·삼각형·윤곽선은 다른 색상 변수를 사용하므로 값이 바뀌지 않습니다.
수정 지점과 변화
아래는 2교시 기준 코드의 속성을 비교하기 위한 실험 예시입니다. 캔버스 크기를 변경하면 기존 도형이 새 이미지 범위를 벗어날 수 있으므로 좌표 범위도 함께 확인합니다. 3교시 제출 실습의 수정 범위는 별도로 지정됩니다.
| 수정 지점 | 바뀌는 결과 | 먼저 시도할 변화 |
|---|---|---|
canvas_width, canvas_height | 전체 이미지의 비율과 사용 가능한 영역 | 600 × 400을 500 × 500으로 변경 |
| 다섯 색상 변수 | 배경과 형태의 전체 인상 | 한 변수의 채널 하나만 ±30 변경 |
| 사각형 경계 상자 | 큰 면의 위치, 가로·세로 비율 | 오른쪽 경계만 40 증가 |
| 타원 경계 상자 | 원의 크기 또는 타원의 방향 | 아래쪽 경계를 40 감소 |
triangle_points | 강조점의 방향과 실루엣 | 첫 꼭짓점의 x만 30 이동 |
| 도형 코드의 순서 | 겹친 부분의 앞뒤 관계 | 삼각형을 타원보다 먼저 그리기 |
수정 전 결과를 저장하고 위치·크기·색상 가운데 한 속성씩 변경합니다. 여기서 하나는 숫자의 개수가 아니라 비교할 시각적 속성을 뜻합니다. 사각형의 위치만 바꾸려면 두 모서리의 좌표를 함께 수정해야 하며, 크기와 색상은 유지합니다. 앞의 RGB 연습은 색상 변화 중에서도 한 채널의 영향만 분리해 확인하는 예입니다.
코드 수정과 재실행 절차
- 먼저 제공된 전체 코드를 위에서 아래로 실행해 기준 결과를 확인합니다.
- 변경할 속성을 하나 정하고, 그 속성을 조절하는 값들을 수정합니다. 비교 대상이 아닌 속성은 유지합니다.
- 변수 대입과 이미지 생성부터 모든 도형, 표시, 저장을 순서대로 다시 실행합니다.
- 의도한 변화가 맞는지 이미지로 확인한 뒤 저장합니다.
전체 실행 순서는 변수 대입 → 이미지 생성 → 그리기 도구 연결 → 도형 그리기 → 표시 → 저장입니다.
팔레트 비교
같은 형태에 두 팔레트를 적용합니다. 도형의 좌표와 실행 순서는 그대로 두고 색상 변수만 바꾸면, 형태 변화와 색상 변화의 영향을 분리해서 관찰할 수 있습니다. 위치·크기·색상을 한꺼번에 수정하면 각 속성의 영향을 구분하기 어렵지만, 기하 구조를 고정하면 두 이미지의 차이가 팔레트에서 비롯되었다고 설명할 수 있습니다. 이것이 프로그래밍에서 변인을 통제하며 비교하는 기본 태도입니다.
팔레트 예측
각 RGB 튜플의 채널 값을 비교해 배경의 밝기, 도형의 색상 계열과 윤곽의 대비를 예상합니다. 색 이름을 특정하기보다 수치와 시각적 특성의 관계에 근거해 기록합니다.
background_color = (244, 239, 229)
primary_color = (235, 86, 75)
secondary_color = (48, 95, 180)
accent_color = (244, 190, 55)
outline_color = (28, 31, 38)
밝은 배경, R이 강한 주조색, B가 강한 보조색, R과 G가 강한 강조색의 관계를 관찰합니다.
background_color = (24, 31, 44)
primary_color = (79, 130, 190)
secondary_color = (205, 92, 122)
accent_color = (238, 210, 120)
outline_color = (236, 239, 244)
낮은 값의 배경, B가 강한 주조색, R이 강한 보조색, 세 값이 높은 윤곽색의 관계를 관찰합니다.
팔레트의 사전 분석
- 어느 팔레트의 배경이 더 어두운가?
- 각 팔레트에서 사각형과 타원은 따뜻한 색과 차가운 색 가운데 어느 쪽에 가까운가?
- 어두운 배경에서 형태의 경계를 보이게 하는 값은 무엇인가?
실행 전 예측의 기준 답안
팔레트 B의 배경은 세 값이 모두 낮으므로 더 어둡습니다. 팔레트 A의 사각형은 R이 강해 따뜻하고 타원은 B가 강해 차갑습니다. 팔레트 B에서는 이 역할이 서로 바뀝니다. 어두운 배경에서는 세 값이 모두 높은 outline_color = (236, 239, 244)가 밝은 경계를 만듭니다.
팔레트 실행
- 전체 기준 코드에 팔레트 A를 넣고 위에서 아래로 실행합니다.
- 마지막 저장 이름을
week03_학번_이름_palette_a.png로 바꾸어 저장합니다. - 다섯 색상 변수의 값만 팔레트 B로 교체합니다. 좌표와 도형 순서는 수정하지 않습니다.
- 변경한 색상 변수의 대입부터 이미지 생성, 도형 그리기, 표시를 다시 실행한 뒤
week03_학번_이름_palette_b.png로 저장합니다.
비교와 기록
| 비교 기준 | 팔레트 A | 팔레트 B | RGB 근거 |
|---|---|---|---|
| 배경과 도형의 분리 | 밝은 배경과 어두운 윤곽의 대비 | 어두운 배경과 밝은 윤곽의 대비 | 배경과 윤곽의 세 채널 값 차이 |
| 따뜻한 형태와 차가운 형태 | 사각형이 따뜻하고 타원이 차가움 | 사각형이 차갑고 타원이 따뜻함 | R 또는 B 가운데 우세한 채널 |
| 작은 강조점 | 노란 삼각형 | 연노란 삼각형 | R과 G가 높고 주변 색과 차이가 남 |
| 전체 인상 | 밝고 선명한 낮의 구성 | 어둡고 빛나는 야간의 구성 | 배경의 전체 밝기와 윤곽 대비 |
비교 기록에는 시각적 인상과 그 근거를 함께 작성합니다. 예를 들어 팔레트 B의 경계가 더 뚜렷하다고 판단했다면 어두운 배경과 밝은 윤곽색의 대비를 근거로 제시할 수 있습니다. 표의 설명은 유일한 정답이 아니라 관찰 결과를 RGB 데이터와 연결하는 예시입니다.
팔레트 비교 결과 정리
“도형의 좌표를 바꾸지 않고 색상 변수만 바꾸었을 때, ________은 그대로이고 ________은 달라졌다. 그 근거는 ________이다.”
정리 문장 예시
도형의 좌표를 바꾸지 않고 색상 변수만 바꾸었을 때, 형태의 위치와 겹침은 그대로이고 화면의 밝기와 온도감은 달라졌습니다. 그 근거는 팔레트 B의 배경 RGB 값이 모두 낮고 사각형과 타원에서 우세한 채널이 서로 바뀌었다는 점입니다.
보충 설명
기본 도형 생성과 저장을 마친 뒤 필요한 항목을 선택해 확인합니다. 튜플의 인덱스 접근, 모듈 이름의 구분과 오류 메시지 해석을 위한 참고 자료입니다.
튜플의 기호와 인덱스
RGB 튜플은 쉼표로 구분한 세 값을 둥근괄호 안에 작성합니다. 개별 채널을 참조할 때에는 변수명 뒤의 대괄호에 인덱스를 작성합니다. 튜플 구성과 요소 참조에 사용하는 표기를 구분해야 합니다.
| 기호 또는 코드 | 이름 | 이번 코드에서 하는 일 | 해석 |
|---|---|---|---|
(235, 86, 75) | 튜플 표기 | R·G·B 세 값을 하나의 튜플로 묶음 | 세 정수의 순서 있는 묶음 |
, | 쉼표 | 첫째·둘째·셋째 값의 경계를 구분 | 튜플 요소의 구분 |
coral[0] | 인덱스 접근 | 0번 위치, 즉 첫 번째 R 값을 확인 | 첫 번째 채널 R의 값 |
type(coral) | 자료형 확인 | coral에 저장된 값의 종류를 확인 | 변수에 연결된 값의 자료형 확인 |
"R:" | 문자열 | 출력 결과 앞에 설명 글자를 표시 | 출력 항목을 식별하는 문자열 |
튜플의 개별 값은 인덱스로 참조합니다. 인덱스는 0부터 시작하는 위치 번호입니다. 아래 코드의 coral[0], coral[1], coral[2]는 각각 R, G, B 값을 반환합니다.
채널 값 확인
1교시 노트북에 새 코드 셀을 추가해 채널 값 확인 코드를 실행합니다. 이 보충 실습은 RGB 튜플의 각 값을 인덱스로 참조하는 방법을 확인하는 용도입니다.
coral의 세 채널 값
- 각 줄의 역할을 확인한 뒤 아래 코드를 셀에 입력합니다.
- Shift+Enter로 실행합니다.
- 출력에서
tuple,235,86,75를 찾습니다.
coral = (235, 86, 75)
print(type(coral))
print("R:", coral[0])
print("G:", coral[1])
print("B:", coral[2])
<class 'tuple'>
R: 235
G: 86
B: 75
이번 주의 튜플 사용 범위
튜플의 추가 연산이나 자료구조 일반 이론은 다루지 않습니다. (width, height)는 크기 두 값, (x, y)는 위치 두 값, (R, G, B)는 색상 세 값을 정해진 순서로 묶는 표기로 사용합니다.
라이브러리와 import
Pillow는 이미지의 생성·편집·저장을 지원하는 Python 라이브러리입니다. 이번 실습은 모듈 불러오기, 이미지 생성, 도형 그리기, 결과 표시와 저장의 순서로 구성됩니다.
| 코드 | 역할 | 구문의 의미 |
|---|---|---|
from | 도구를 찾을 위치를 알리는 Python의 예약어 | 대상 패키지 지정 |
PIL | Pillow 기능을 불러올 때 사용하는 패키지 이름 | Pillow의 패키지명 |
import | 뒤의 이름을 현재 코드에서 사용하도록 가져오는 예약어 | 모듈 이름 불러오기 |
Image | 이미지를 만들고 저장하는 기능 | 이미지 생성·편집 모듈 |
, | 가져올 이름 두 개를 구분 | 모듈 이름의 구분 |
ImageDraw | 이미지 위에 도형을 그리는 기능 | 도형 그리기 모듈 |
이 구문은 PIL 패키지의 Image와 ImageDraw 모듈을 현재 코드에서 사용할 수 있도록 불러옵니다. from과 import는 Python 예약어이며, 패키지명과 모듈명은 정해진 철자와 대소문자를 유지해야 합니다.
Pillow와 PIL의 명칭 구분
라이브러리의 현재 배포 이름은 Pillow이지만, Python 코드에서는 기존 호환 이름인 PIL을 사용해 가져옵니다. 따라서 from Pillow import Image로 바꾸지 않습니다. 대문자와 소문자도 서로 다른 이름으로 처리되므로 제공된 철자를 그대로 사용합니다.
| 이름 | 종류 | 이번 수업에서 하는 일 |
|---|---|---|
PIL | 패키지 이름 | 설치한 Pillow 기능을 Python 코드로 불러올 때 사용하는 이름 |
Image | 이미지 기능 | 빈 이미지를 만들고 결과를 저장 |
ImageDraw | 그리기 기능 | 이미지 위에 선과 도형을 기록 |
image, draw | 사용자 정의 변수 | 현재 이미지와 그리기 도구를 참조 |
전체 실행 과정 요약
Image와 ImageDraw 모듈을 불러옵니다.
1교시와 같은 Image.new()로 600 × 400 캔버스를 만듭니다.
생성된 이미지에 도구를 연결하고 도형을 그립니다.
결과를 확인한 뒤 PNG 파일로 남깁니다.
image나 draw 때문에 오류가 날 수 있습니다.image에 저장합니다.draw에 저장합니다.주요 오류와 점검 항목
| 보이는 문제 | 가능한 원인 | 먼저 확인할 것 |
|---|---|---|
SyntaxError | 괄호·따옴표가 닫히지 않았거나 입력 사이의 쉼표가 빠짐 | 가장 최근에 수정한 줄의 여닫는 기호와 쉼표 확인 |
NameError: image | 이미지 생성 셀을 아직 실행하지 않음 | 위쪽 셀부터 순서대로 실행했는지 확인 |
NameError: draw | ImageDraw.Draw(image) 셀을 실행하지 않음 | 그리기 도구의 생성 여부와 변수명 draw의 철자 확인 |
| 오류 메시지 없이 출력이 없음 | 변수와 도형 코드까지만 실행하고 display(image)를 실행하지 않음 | 셀 마지막까지 실행되었는지 확인 |
| 도형이 보이지 않음 | 좌표가 이미지 경계 밖에 있거나 다른 도형에 가림 | 좌표 범위와 도형 코드의 실행 순서 확인 |
| 수정한 색이나 좌표가 반영되지 않음 | 변수만 바꾸고 이미지 생성과 도형 명령을 다시 실행하지 않음 | 변수 대입부터 이미지 생성·그리기·표시를 순서대로 재실행 |
| 예상과 다른 색 | RGB 순서가 바뀌었거나 팔레트 변수를 잘못 사용 | R, G, B 순서와 각 값의 0~255 범위 확인 |
| PNG 파일이 없음 | 미리보기만 하고 save()를 실행하지 않음 | 저장 셀 실행 여부와 파일명 확장자 확인 |
오류 확인 순서
오류 메시지의 마지막 줄에서 종류를 확인한 뒤, 발생 위치와 선행 코드의 실행 여부를 점검합니다.
- 오류 메시지의 마지막 줄에 표시된 이름과 설명을 확인합니다.
SyntaxError는 문법 요소,NameError는 이름의 철자와 정의 여부를 먼저 점검합니다.- 오류가 발생한 줄과 최근 수정한 부분을 기준 코드와 비교합니다.
- 필요한 모듈과 변수를 먼저 준비한 뒤 이미지 생성부터 순서대로 다시 실행합니다.
NameError: name 'draw' is not defined
Python이 현재 실행 공간에서 draw이라는 이름을 찾지 못했다는 뜻입니다.
draw = ImageDraw.Draw(image)
이 줄을 실행했는지, draw의 철자와 대소문자가 아래 도형 코드와 같은지 확인합니다.
학습 내용 점검
핵심 개념 점검
- RGB 튜플의 R·G·B 순서 해석
- 이미지 크기·좌표·색상에 해당하는 변수 구분
image와draw의 역할 구분- 도형 좌표와
fill·outline·width인자 해석 - 실행 순서에 따른 겹침 결과 예측
- 미리보기와 PNG 파일 저장의 구분
도형 명령의 구성 요소
다음 명령을 좌표, 내부 색, 테두리 색, 두께라는 네 요소로 나누어 자신의 말로 설명합니다.
draw.rectangle(
(60, 80, 260, 220),
fill=(240, 90, 70),
outline=(30, 30, 35),
width=5
)
한 줄 설명의 기준 답안
왼쪽 60, 위 80, 오른쪽 260, 아래 220의 경계 상자에 사각형을 그립니다. 내부는 R이 강한 (240, 90, 70) 색으로 채우고, 테두리는 어두운 회색 (30, 30, 35)로 5픽셀 두께로 그립니다.
수업 후 개별 복습
1. (255, 0, 255)는 어떤 두 채널이 켜진 색인가?
R과 B 채널이 최대이고 G는 꺼져 있습니다. 빨강과 파랑 빛이 섞인 자홍 계열입니다.
2. Image.new()와 ImageDraw.Draw()의 역할 차이는?
Image.new()는 모드, 크기, 배경색으로 이미지 데이터를 만들고, ImageDraw.Draw(image)는 그 이미지에 도형을 그릴 수 있는 도구를 연결합니다.
3. ellipse에 전달한 네 좌표는 원의 중심과 반지름인가?
아닙니다. 이번 수업의 draw.ellipse()에는 타원을 감싸는 경계 상자의 왼쪽, 위, 오른쪽, 아래 좌표를 전달합니다.
4. display(image)까지 실행했는데 파일이 생기지 않은 이유는?
display(image)는 현재 결과를 노트북에 보여줄 뿐입니다. 파일로 남기려면 image.save("파일명.png")를 별도로 실행해야 합니다.
학습 범위
이번 실습의 범위는 불투명 RGB 이미지의 색상 지정, 도형 생성과 PNG 저장입니다. 투명도, 그라디언트, 반복 패턴과 안티앨리어싱은 후속 학습 주제입니다.
3교시 실습 개요
3교시에서는 제공된 600 × 400 이미지와 도형 코드를 기준으로 실습합니다. 1교시에서 정한 기준점을 사각형의 위치에 적용하고, 타원의 크기 변경, 팔레트 비교, 그리기 순서의 비교·선택을 차례로 수행합니다.
2교시의 실험 예시와 달리 캔버스 크기와 윤곽선 두께는 유지하며, 노트북의 EDIT 표시 영역에서 단계별로 지정한 항목만 수정합니다. 한 속성씩 변경 → 재실행 → 결과 비교 → 변경 이유 기록의 순서로 진행합니다.
참고 자료
- Pillow 공식 문서: Modes, coordinates and colorsRGB 이미지의 세 채널, 8비트 픽셀, 크기와 좌표, 색상 튜플에 관한 공식 설명
- Pillow 공식 문서: ImageDraw사각형, 타원, 다각형, 내부색, 테두리와 좌표 인자의 공식 사용법
- Pillow 공식 문서: Image file formatsPNG와 JPEG를 포함한 지원 형식과 파일 저장 방식