Function / Parameters / Goal-based mission

6주차 3교시: 이미지 생성기 실습

함수로 입력을 비교하고 아치·직조·회로를 제작해, 최종 작품 한 장을 선택합니다.

모듈 함수를 실제 실행해 제작한 아치·직조·회로 포스터 세 장의 6주차 3교시 표지
함수의 조합 · 모듈 한 개를 정의하고 반복 호출해 포스터 완성

입력 비교와 모듈 포스터

형식
목표 달성형 개인 실습
이전 학습
1교시 함수, 2교시 입력·반환과 기준안 A
출발점
같은 공통 노트북의 create_poster와 poster_a
제출
공통 .ipynb + 최종 작품 .png

학습 목표

  1. 2교시 생성 함수와 A를 재사용하고 같은 입력을 재현합니다.
  2. B는 시드만, C는 개수 또는 큰 경계만 바꾸어 호출합니다.
  3. C 호출을 직접 작성하고 생성 규칙·예상·관찰을 설명합니다.
  4. 선택한 설정으로 세 방향을 제작하고 최종 작품과 같은 노트북을 제출합니다.

1교시에 저장한 같은 노트북에서 3교시 구역으로 이동합니다. 새 파일을 업로드하지 않습니다. 런타임이 끊겼다면 공통 준비부터 앞 교시까지 순서대로 실행해 결과를 복구합니다. 공통 노트북 다운로드는 사본이 없을 때 사용합니다.

실습 결과물

모듈을 그리는 함수를 조합하여 포스터를 완성합니다. 2교시 함수와 기준안 A를 이어받아 B·C를 만들고, 이어받을 시드·개수·경계값을 선택합니다. 그 설정으로 아치·직조·회로 포스터를 제작한 뒤 최종 작품 한 장을 600 × 600 PNG로 저장합니다.

위 이미지는 학생에게 제공하는 함수를 실제로 호출한 결과입니다. 모두 A의 시드 73·개수 56·경계 42/64를 사용합니다. 세 방향의 격자 자리와 표현 단계는 같고 모듈 형태와 팔레트가 다릅니다. 이미지를 누르면 원본 크기로 볼 수 있습니다.

작품의 방향

아치의 곡선, 직조의 교차, 회로의 꺾인 선 중 만들고 싶은 인상을 살펴봅니다. “굵은 모듈과 가는 선이 번갈아 보이는 화면”, “빈 격자가 리듬을 만드는 화면”처럼 원하는 인상을 정하고 입력을 연결합니다.

실습 과정

  1. RECALL기준 재현2교시 함수와 A 확인
  2. PLAN입력 설계B·C에서 한 입력씩 변경
  3. CALL함수 호출C의 키워드 연결 직접 작성
  4. DESIGN작품 제작설정을 이어받아 모듈 조합
  5. SELECT최종 선택의도와 시각 요소로 한 장 선택
  6. SAVE저장과 제출작품 PNG와 공통 노트북

완료 기준

  1. 공통 노트북1·2·3교시의 코드와 출력 유지
  2. 함수와 A2교시 결과를 이어받고 같은 입력 재현
  3. C 호출같은 함수의 다섯 키워드를 직접 연결
  4. B 비교A의 시드만 변경
  5. C 비교A의 개수 또는 큰 경계만 변경
  6. 기록생성 규칙·예상 두 문장·관찰 두 문장
  7. 반환2교시의 정상 반환과 새 결과 확인
  8. 작품선택한 설정의 세 방향 제작과 최종 선택
  9. 선택 근거강조·반복·여백과 연결한 의도와 이유
  10. 저장600 × 600 최종 작품과 A·B·C 비교본
  11. 실행새 세션에서 공통 준비부터 모두 실행하여 PASS
  12. 제출실행 결과가 있는 공통 노트북과 작품 PNG

실습 준비

1교시에 Drive에 저장한 week06_학번_이름.ipynb를 열고 3교시 구역으로 이동합니다. 2교시까지 실행했다면 새 파일 업로드나 함수 재작성 없이 이어갑니다. 1·2교시의 코드·출력·관찰을 유지합니다.

노트북과 런타임 복구

기존 사본을 찾아 엽니다. 런타임만 끊겼다면 공통 준비부터 2교시 마지막까지 실행합니다. 사본을 잃었다면 상단 공통 노트북을 Colab에 업로드해 새 Drive 사본을 만들고 앞 교시 구역을 순서대로 복구합니다.

기준안 A 재현

확인할 것: 같은 함수와 다섯 입력으로 A를 다시 만들 수 있는가?

비교 기준과 재현성

B와 C를 만들기 전에 A를 다시 만들 수 있어야 합니다. 기준이 실행할 때마다 바뀌면 시드나 개수를 바꿨을 때의 차이를 설명하기 어렵습니다. 2교시의 create_poster는 호출할 때마다 시드를 정하므로 같은 환경에서 같은 함수와 입력을 쓰면 A를 재현할 수 있습니다.

3교시 첫 셀은 2교시의 다섯 입력으로 함수를 다시 호출합니다. 기존 A와 픽셀이 같으면 재현 확인 문구가 표시됩니다. 같은 노트북에 남은 함수와 기준안이 있어야 이 비교를 할 수 있습니다.

먼저 예상 · 실행 후 설명

A를 다시 만드는 호출에서 바뀐 입력이 있나요? 같은 환경의 같은 함수·입력이라면 어떤 결과를 예상하나요?

NameError 또는 기준안 오류

공통 준비와 2교시 마지막 정상 셀을 먼저 실행합니다. 기준안 값을 바꿨다면 해당 셀을 다시 실행해 함수·설정·이미지를 함께 갱신합니다.

미완성 이미지의 원인

2교시 함수의 시드·range·반환 위치를 확인합니다. random.seed(seed_number), range(shape_count), 반복문 밖의 return image가 정상인지 점검합니다.

공통 노트북 3교시 시작 셀에서 확인할 호출
공통 노트북 3교시 시작 셀에서 확인할 호출
poster_a_again = create_poster(
    seed_number=seed_a,
    shape_count=shape_count_a,
    medium_threshold=medium_a,
    large_threshold=large_a,
    palette=palette_a,
)
display(poster_a_again)

같은 출력이어도 새로 호출해 만든 이미지와 기존 A는 서로 다른 이미지 객체입니다. 이번 확인은 객체 이름이 같은지 비교하는 것이 아니라 이미지 내용이 같은지 비교합니다. 제공 셀의 픽셀 비교 코드는 확인 도구이므로 직접 다시 작성할 필요는 없습니다.

생성 규칙과 관찰 기록

기록할 것: 실행 전에 예상하고 실행 후에는 보이는 근거를 적습니다.

예상과 관찰의 차이

예상은 입력 변경에서 결과를 추론하는 문장입니다. 관찰은 실제 두 이미지를 보고 확인한 사실입니다. “더 예뻐졌다”만 적으면 어떤 설정이 어떤 차이를 만들었는지 확인하기 어렵습니다. 왼쪽 위·중앙·아래쪽처럼 위치를 정하고 모티프의 크기, 겹침, 강조 고리를 근거로 씁니다.

학번과 이름은 공통 정보에 이미 작성했습니다. 3교시의 기록 셀에서 generator_rule과 두 예상 문장을 적고, B·C 실행 후 같은 셀로 돌아와 관찰을 완성합니다. 자동 검사는 기록 유무를 확인하며 문장의 타당성은 입력과 이미지로 판단합니다.

기록 항목
변수작성할 내용
generator_ruleA의 캔버스·표현·팔레트와 바꿀 입력
prediction_b / observation_b시드 변경의 예상 / 실제 배치·크기 차이
prediction_c / observation_c개수 또는 큰 경계 변경의 예상 / 실제 변화와 근거
먼저 예상 · 실행 후 설명

큰 경계를 올려 강조 동심원을 줄이려는 의도가 출력에서 보이나요? 어떤 위치의 모티프를 근거로 설명할 수 있나요?

동일 결과의 기록

같다고 쓰고 가능한 이유를 설명합니다. 변경 구간의 크기가 없거나 바뀐 모티프가 뒤 모티프에 가려질 수 있습니다. 분류 가능한 구간과 실제 보이는 면적을 구분합니다.

관찰 기록의 구조
항목문장 구조
B 예상시드만 바꾸므로 ___는 유지되고 ___의 선택은 달라질 것이다.
B 관찰A의 ___ 위치와 B의 같은 위치를 비교하면 ___가 다르다.
C 예상큰 경계를 64에서 68로 올리면 크기 ___ 구간의 표현이 바뀔 것이다.
C 관찰___ 위치의 강조 동심원이 ___로 바뀌었으며 ___는 유지된다.

큰 경계 64→68의 경우 분류가 바뀔 수 있는 크기는 64·65·66·67입니다. 68 이상은 여전히 큰 구간입니다. 개수 56→72의 경우 추가되는 모티프는 16개입니다. 시드와 선택 순서가 같아 앞 56개 생성 과정은 같지만, 추가 16개가 그 위에 겹쳐 기존 일부를 가릴 수 있습니다. 이 차이를 예상에 반영합니다.

입력과 반환 점검

2교시의 함수는 이미 완성되어 있습니다. 아래 세 연결을 읽고 호출에서 전달한 입력이 실제로 쓰이는지 확인합니다. 정상이라면 본문을 유지하고 B·C 호출로 진행합니다.

입력과 결과의 연결
위치정상 코드
반복문 앞random.seed(seed_number)
반복 횟수for shape_number in range(shape_count):
반복이 끝난 뒤return image
조기 반환 진단

첫 모티프를 그린 뒤 함수가 종료됩니다. 실제로 시험했다면 관찰 후 네 칸 위치로 복구하고 2교시 기준안 셀부터 다시 실행합니다. 정상 함수를 유지하는 것이 필수 진행의 출발점입니다.

입력별 비교 실험

선택할 것: C에서 밀도를 바꿀지, 강조 표현의 기준을 바꿀지 결정합니다.

디자인 의도와 입력

“겹침이 더 조밀한 이미지”를 원하면 개수 실험을 선택합니다. “큰 동심원으로 강조되는 대상을 줄이고 싶다”면 큰 경계 실험을 선택합니다. B에서는 시드를 바꾸어 같은 규칙이 다른 선택 순서에서 어떤 배치를 만드는지 확인합니다. 두 실험은 서로 다른 질문에 답합니다.

실행 결과Python · Pillow
입력 비교 · A 기준 / B 시드만 변경 / C 큰 경계만 변경
입력 비교 · A 기준 / B 시드만 변경 / C 큰 경계만 변경 · 이미지를 누르면 원본 크기로 볼 수 있습니다.
통제 실험 설정
안변경권장값
A2교시 기준 유지시드 73 / 개수 56 / 경계 42·64
B시드만seed_b = 91
C큰 경계만 또는 개수만threshold: 68 / count: 72

B·C 설정 셀에는 A의 정의를 다시 넣지 않습니다. experiment_kind = "threshold", changed_value = 68이면 큰 경계만 바꿉니다. 개수를 비교하려면 "count"와 72로 바꿉니다. 준비 코드가 count_c와 large_c를 연결합니다. C의 시드·중간 경계·팔레트는 A와 같습니다.

시드는 0~9999 정수, 개수는 40~80 정수입니다. 20→중간 경계, 중간→큰 경계, 큰 경계→80의 차이는 각각 10 이상 둡니다. 팔레트는 0~255 정수 채널의 RGB 튜플 다섯 개입니다. 비교 중에는 A 팔레트를 유지합니다.

경계값 검사 오류

medium - 20, large - medium, 80 - large가 각각 10 이상인지 확인합니다. 기본 42/64와 C 42/68은 조건을 만족합니다. 기준과 같은 changed_value는 실제 변경이 아니므로 다른 값을 고릅니다.

3교시 설정 셀 · 학생이 수정하는 세 줄
3교시 설정 셀 · 학생이 수정하는 세 줄
seed_b = 91
experiment_kind = "threshold"
changed_value = 68

입력별 변경·유지 항목
실험바꾸는 값유지하는 값
B시드 73→91개수 56, 두 경계 42/64, 팔레트
C: threshold큰 경계 64→68시드 73, 개수 56, 중간 경계 42, 팔레트
C: count개수 56→72시드 73, 두 경계 42/64, 팔레트

두 종류의 C를 동시에 제출할 필요는 없습니다. 하나를 선택하고 예상·관찰을 그 실험에 맞춥니다. 개수와 큰 경계를 동시에 바꾸면 차이의 원인을 하나로 설명하기 어려우므로 필수 비교에서는 한 입력만 변경합니다. 설정값을 바꾼 뒤에는 호출 → 작품 제작 → 최종 선택 → 저장 셀도 다시 실행합니다.

C의 함수 호출

작성할 것: 변수 이름 다섯 개를 같은 함수의 입력에 연결합니다.

호출문 작성

2교시에는 정의와 호출이 모두 제공되었습니다. 이번에는 정의를 읽고 C의 호출문을 직접 완성합니다. 같은 함수 이름을 쓰되 오른쪽 값으로 C의 개수와 큰 경계를 연결합니다. 함수 본문을 복사해 create_poster_c를 만드는 대신, 기존 create_poster를 다른 입력으로 실행합니다.

A는 2교시 결과이고 B는 제공된 호출입니다. poster_c = poster_a는 A에 이름만 추가하므로 새로 생성하지 않습니다. 이 줄을 create_poster 호출로 교체합니다. seed_a, count_c, medium_a, large_c, palette_a를 다섯 키워드에 연결합니다.

C의 인자 연결
코드 예시 · 본문의 실행 순서와 함께 확인
poster_c = create_poster(
    seed_number=seed_a,
    shape_count=count_c,
    medium_threshold=medium_a,
    large_threshold=large_c,
    palette=palette_a,
)

왼쪽은 정의의 매개변수 이름, 오른쪽은 설정값 변수입니다. 같은 함수를 재사용합니다.

TypeError의 원인

다섯 키워드가 seed_number, shape_count, medium_threshold, large_threshold, palette인지 확인합니다. count_c는 오른쪽 값 이름이고 왼쪽 키워드는 shape_count입니다.

A·C 동일 결과의 원인

count_c와 large_c를 실제 호출에 연결했는지 먼저 확인합니다. 올바른 큰 경계 실험에서도 이미지가 같을 수 있습니다. 검사가 통과하면 같은 이유를 관찰로 기록합니다.

C의 매개변수와 인자
함수가 받는 이름전달할 변수준비된 값
seed_numberseed_aA와 같은 73
shape_countcount_c기본 56 / 개수 실험은 선택값
medium_thresholdmedium_aA와 같은 42
large_thresholdlarge_c기본 64 / 경계 실험은 선택값
palettepalette_aA와 같은 팔레트

poster_c = poster_a에는 함수 호출이 없습니다. 이미 존재하는 A를 C라는 이름으로도 가리키게 할 뿐입니다. 반면 create_poster(...)의 결과를 poster_c에 받으면 함수의 생성 작업을 실행하고 새 결과를 보관합니다. 눈에 비슷한 결과가 나와도 두 코드가 수행한 작업은 다릅니다.

모듈 포스터 제작

6주차의 최종 작품은 작은 모듈을 함수로 만들고 격자에 조합한 포스터입니다. 아치는 반원과 두 기둥, 직조는 두 대각 띠와 교차점, 회로는 꺾인 경로와 끝점을 하나의 작업으로 묶습니다. 모듈 하나를 여러 번 호출하면서 같은 시각 규칙을 화면 전체에 적용합니다.

A·B·C에서 비교한 시드·개수·두 경계의 설정값을 이어받습니다. A는 기준값, B는 다른 시드, C는 개수나 큰 경계를 조정한 값입니다. 새 함수의 배치 규칙은 10열 × 8행의 격자이므로 앞의 동심원과 위치가 같지는 않습니다. 같은 시드도 함수의 난수 호출 순서가 달라지면 다른 결과가 나온다는 점을 확인합니다.

함수의 역할

draw_arch, draw_weave, draw_circuit는 전달받은 위치·크기·색·굵기로 모듈 하나를 그립니다. create_artwork는 캔버스를 준비하고 모듈 함수를 반복 호출한 뒤 완성 이미지를 반환합니다. 모듈 한 개의 작업과 포스터 전체의 작업을 나누는 구조입니다. 모듈 함수를 고치면 다음 호출에서 그 표현이 공통으로 바뀝니다.

입력과 작업 단위
함수주요 입력수행하는 작업
draw_arch / draw_weave / draw_circuit위치·크기·색·굵기·방향기존 캔버스에 모듈 한 개 그리기
create_artwork시드·개수·두 경계·팔레트·표현모듈을 반복 호출하고 포스터 반환
create_artwork 본문의 호출 · 38은 모듈 크기
create_artwork 본문의 호출 · 38은 모듈 크기
draw_arch(draw, x, y, 38, color, detail_color, background, weight, direction)

세 방향의 표현

아치는 위·아래로 열린 곡선과 기둥의 반복을 사용합니다. 직조는 대각 띠의 교차와 굵기 차이로 짜임을 만듭니다. 회로는 직각 경로와 연결점으로 가벼운 선의 리듬을 만듭니다. 각 방향에 맞춘 팔레트와 제목·구분선도 함께 제공됩니다.

세 방향의 시각적 위계
방향강조 요소보조 요소확인할 점
아치 조합붉은 두꺼운 아치짙은 녹색 기둥·얇은 곡선위·아래 방향의 리듬과 빈 자리
직조 패턴황토색 대각 띠밝은 띠·푸른 교차선교차점과 두께의 대비
회로 연결붉은 경로와 끝점청록색 선·작은 연결점선이 이어져 보이는 방향과 간격

격자와 입력

격자는 80자리이며 서로 같은 자리를 선택하지 않습니다. shape_count가 56이면 56자리를 사용하고 24자리를 비웁니다. 40으로 줄이면 빈 자리가 40개로 늘어납니다. 모듈 개수는 채움과 여백을 직접 조절합니다.

모듈의 크기는 38, 격자 간격은 48로 고정합니다. 매번 선택하는 value는 20~80의 숫자이며 물리적인 크기가 아닙니다. 두 경계는 이 값을 가는 선·기본 굵기·강조 굵기의 세 표현으로 나눕니다. 큰 경계를 64에서 68로 올리면 64~67의 모듈이 강조에서 기본 표현으로 바뀝니다.

세 방향은 같은 자리·선택값·방향을 공유하지만, 모듈 형태와 팔레트가 함께 바뀝니다. 하나의 색이나 형태만의 효과로 설명하지 않고 조합 전체의 인상을 비교합니다. random.sample과 자리 번호를 좌표로 바꾸는 코드는 제공 도구로 사용합니다.

설정과 의도

노트북의 작품 제작 셀에서 source_variant와 artwork_intent를 적습니다. 먼저 A의 기준값으로 세 결과를 보고, 빈 자리를 늘리고 싶다면 C의 개수를 조정하는 식으로 원하는 인상과 입력을 연결합니다.

작품 제작 셀 · 수정할 두 줄
작품 제작 셀 · 수정할 두 줄
source_variant = "A"
artwork_intent = "두꺼운 아치를 강조하고 얇은 곡선과 빈 격자가 번갈아 보이는 리듬을 만들고 싶다."

모듈 함수의 전체 코드

공통 준비를 실행한 상태에서 사용합니다. 노트북에도 같은 코드가 들어 있습니다. 세 모듈 함수의 정의, 반복문 안의 호출, 반복이 끝난 뒤 return image를 순서대로 찾습니다. 그리기 명령과 제목·글꼴 코드는 제공된 재료입니다.

공통 준비 이후 · 제공 함수
공통 준비 이후 · 제공 함수
# 제공 함수 / 모듈 하나를 그리는 작업과 포스터 전체를 만드는 작업을 나눕니다.
from PIL import ImageFont

def draw_arch(draw, x, y, size, color, detail_color, background, weight, direction):
    # 반원과 두 기둥을 묶어 아치 하나를 그립니다.
    band = weight
    if direction % 2 == 0:
        draw.pieslice((x, y, x + size, y + size), 180, 360, fill=color)
        draw.rectangle((x, y + size // 2, x + size, y + size), fill=color)
        draw.pieslice((x + band, y + band, x + size - band, y + size - band), 180, 360, fill=background)
        draw.rectangle((x + band, y + size // 2, x + size - band, y + size), fill=background)
    else:
        draw.pieslice((x, y, x + size, y + size), 0, 180, fill=color)
        draw.rectangle((x, y, x + size, y + size // 2), fill=color)
        draw.pieslice((x + band, y + band, x + size - band, y + size - band), 0, 180, fill=background)
        draw.rectangle((x + band, y, x + size - band, y + size // 2), fill=background)
    if weight >= 9:
        center = x + size // 2
        draw.line((center, y + size // 3, center, y + 2 * size // 3), fill=detail_color, width=3)


def draw_weave(draw, x, y, size, color, detail_color, background, weight, direction):
    # 두 대각 띠와 중앙의 교차점을 묶어 직조 모듈 하나를 그립니다.
    band = weight
    draw.polygon([(x, y), (x + band, y), (x + size, y + size - band),
                  (x + size, y + size), (x + size - band, y + size), (x, y + band)], fill=detail_color)
    draw.polygon([(x + size - band, y), (x + size, y), (x + size, y + band),
                  (x + band, y + size), (x, y + size), (x, y + size - band)], fill=color)
    if direction % 2 == 0:
        center = x + size // 2
        top = y + size // 2
        draw.polygon([(center - band, top), (center, top - band),
                      (center + band, top), (center, top + band)], fill=detail_color)


def draw_circuit(draw, x, y, size, color, detail_color, background, weight, direction):
    # 꺾인 경로와 두 끝점을 묶어 회로 모듈 하나를 그립니다.
    middle = size // 2
    if direction % 2 == 0:
        points = [(x, y + middle), (x + middle, y + middle), (x + middle, y + size)]
    else:
        points = [(x + middle, y), (x + middle, y + middle), (x + size, y + middle)]
    draw.line(points, fill=color, width=max(2, weight // 2))
    radius = max(3, weight // 2)
    for px, py in (points[0], points[-1]):
        draw.ellipse((px - radius, py - radius, px + radius, py + radius), fill=color)
        draw.ellipse((px - 1, py - 1, px + 1, py + 1), fill=background)
    if weight >= 9:
        draw.rectangle((x + middle - 3, y + middle - 3, x + middle + 3, y + middle + 3), fill=detail_color)


def create_artwork(seed_number, shape_count, medium_threshold, large_threshold, palette, graphic_style):
    assert graphic_style in ("arches", "weave", "circuit"), "표현은 arches, weave, circuit 중 하나입니다."
    assert 40 <= shape_count <= 80, "모듈 개수는 40~80입니다."
    background, primary, secondary, accent, ink = palette
    image = Image.new("RGB", (600, 600), background)
    draw = ImageDraw.Draw(image)
    random.seed(seed_number)

    # 10열 × 8행의 80자리 중 앞 shape_count개를 사용합니다. 겹치는 자리는 없습니다.
    positions = random.sample(range(80), 80)
    for module_number in range(shape_count):
        position = positions[module_number]
        column = position % 10
        row = position // 10
        x = 64 + column * 48
        y = 128 + row * 48
        # 값은 모듈의 표현 단계를 고르는 기준입니다. 격자의 간격은 48로 유지합니다.
        value = random.randint(20, 80)
        direction = random.randint(0, 3)
        detail_color = random.choice([primary, secondary])
        if value >= large_threshold:
            color = accent
            weight = 11
        elif value >= medium_threshold:
            color = primary
            weight = 7
        else:
            color = secondary
            weight = 3

        # 같은 위치와 입력을 서로 다른 모듈 함수에 전달합니다.
        if graphic_style == "arches":
            draw_arch(draw, x, y, 38, color, detail_color, background, weight, direction)
        elif graphic_style == "weave":
            draw_weave(draw, x, y, 38, color, detail_color, background, weight, direction)
        else:
            draw_circuit(draw, x, y, 38, color, detail_color, background, weight, direction)

    # 제목·구분선·설정 표기는 제공된 마감 코드입니다.
    title_font = ImageFont.load_default(size=24)
    small_font = ImageFont.load_default(size=11)
    draw.text((60, 42), "MODULAR / " + graphic_style.upper(), fill=ink, font=title_font)
    draw.text((60, 76), "FUNCTION STUDIES     /     SERIES 06", fill=ink, font=small_font)
    draw.line((60, 102, 540, 102), fill=ink, width=1)
    draw.line((60, 535, 540, 535), fill=ink, width=1)
    draw.text((60, 551), "SEED " + str(seed_number) + "   /   MODULES " + str(shape_count), fill=ink, font=small_font)
    draw.text((382, 551), "THRESHOLDS " + str(medium_threshold) + " / " + str(large_threshold), fill=ink, font=small_font)
    return image

# 배경 / 주조 / 보조 / 강조 / 글자·구분선
ARTWORK_PALETTES = {
    "terracotta": [(245, 235, 214), (45, 67, 63), (155, 156, 132), (196, 72, 44), (45, 55, 49)],
    "indigo": [(25, 32, 59), (225, 214, 189), (92, 121, 148), (239, 163, 69), (225, 214, 189)],
    "mint": [(225, 238, 225), (24, 86, 92), (126, 161, 145), (209, 67, 48), (24, 72, 77)],
}
ARTWORK_DIRECTIONS = [("arches", "terracotta"), ("weave", "indigo"), ("circuit", "mint")]
print("작품 함수 준비 완료: 아치 / 직조 / 회로")

최종 선택과 조정

작품 번호는 1 아치 · 2 직조 · 3 회로입니다. A·B·C는 이어받을 설정의 이름이고, 1·2·3은 그 설정으로 만든 모듈 표현의 번호입니다. selected_direction에 번호를 적으면 최종 원본을 크게 표시합니다. 이미 반환받은 이미지 중 하나를 선택하므로 선택만 바꿀 때 생성기를 다시 호출할 필요는 없습니다.

최종 선택 셀 · 이미지에 맞게 작성
최종 선택 셀 · 이미지에 맞게 작성
selected_direction = 1
selection_reason = "1번은 굵은 붉은 아치 사이에 얇은 곡선과 빈 자리가 남아 반복의 리듬이 잘 보여 선택했다."

시각적 판단

강조색이 먼저 보이는 구역을 찾고 그 주변의 선 굵기와 모듈 방향을 살펴봅니다. 빈 자리가 한쪽에 몰렸는지, 반복 사이에 적절하게 흩어졌는지도 확인합니다. 전체를 같은 크기로 비교한 뒤 최종 원본에서 다시 봅니다. 선택한 번호·위치·시각 요소를 함께 설명하면 자신의 의도를 근거로 보여 줄 수 있습니다.

의도에 따른 조정
원하는 변화조정할 입력재확인할 결과
빈 격자와 여백 확대C: count / 40사용한 자리 40개·빈 자리 40개
강조 모듈의 비중 축소C: threshold / 68강조색 면적과 굵기의 분포
새로운 자리와 방향B: seed_b 변경강조 구역과 모듈 방향의 리듬
같은 격자의 다른 인상최종 방향 1·2·3 선택곡선·교차·직각 경로의 차이

조정할 때는 원하는 변화에 맞는 입력 하나를 고릅니다. B·C 설정을 바꿨다면 설정 → 호출 → 작품 제작 → 최종 선택 → 저장을 다시 실행합니다. source_variant도 바꾼 안을 가리켜야 합니다. C를 40개로 바꾸고 A를 계속 선택하면 작품의 개수는 바뀌지 않습니다.

제목과 구분선을 포함한 600 × 600 포스터가 최종 원본입니다. 미리보기의 300 × 300 축소본을 저장하지 않습니다. 작품 의도와 선택 이유를 마지막 결과에 맞추고, 화면의 작품과 저장한 PNG가 같은지 확인합니다. 자동 검사는 입력·선택·저장의 일치를 확인하며 심미적 취향을 채점하지 않습니다.

비교본과 원본 저장

확인할 것: 선택한 작품과 A·B·C가 각각 최신 파일로 저장되었는가?

비교판 구성

비교판은 폭 600인 이미지 세 장을 나란히 놓기 위해 가로 1800픽셀로 만듭니다. 위쪽 제목 영역 80픽셀을 더해 높이는 680픽셀입니다. A는 (0, 80), B는 (600, 80), C는 (1200, 80)에 붙입니다. 같은 크기와 배율로 배치해야 밀도와 여백을 비교하기 쉽습니다.

저장 셀은 그대로 실행합니다. 상단 80픽셀에 실험 항목을 표시하고 A·B·C를 배치해 week06_학번_이름_generator.png를 저장합니다. A.png, B.png, C.png 원본은 각각 600 × 600입니다. 선택한 최종 작품은 별도의 week06_학번_이름_artwork.png로 저장합니다. 제출 파일은 작품 PNG와 공통 노트북입니다. 비교본과 A·B·C 원본은 보관하고 비교 출력은 노트북에 남깁니다.

화면과 파일의 불일치

B·C 설정을 바꾸면 설정 → 호출 → 작품 제작 → 최종 선택 → 저장을 순서대로 다시 실행합니다. A 설정을 바꾸었다면 2교시 기준안 셀부터 다시 실행합니다.

원본 파일 누락

저장 셀을 실행하고 Colab 파일 목록을 새로 확인합니다. 자동 검사도 세 원본이 현재 이미지와 같은지 확인합니다.

제공 저장 셀에서 읽을 네 줄 · 생성된 이미지 재사용
제공 저장 셀에서 읽을 네 줄 · 생성된 이미지 재사용
comparison_sheet.paste(poster_a, (0, 80))
comparison_sheet.paste(poster_b, (600, 80))
comparison_sheet.paste(poster_c, (1200, 80))
comparison_sheet.save(output_filename)

파일 용도와 확인
파일크기확인할 내용
generator.png1800 × 680A·B·C 순서와 실험 이름
A.png / B.png / C.png각 600 × 600제목 없는 개별 원본
artwork.png600 × 600최종 선택한 작품과 동일
공통 .ipynb노트북세 교시 코드·출력·기록과 작품 선택

함수 반환값은 아직 메모리 안의 이미지이고 save를 실행해야 파일이 생깁니다. Colab에서 파일이 만들어졌더라도 개인 컴퓨터에 자동으로 내려받아지는 것은 아닙니다. 왼쪽 파일 목록에서 최종 artwork.png를 다운로드하고, 실제로 열어 선택한 작품과 같은지 확인합니다. 비교 PNG도 보관할 수 있습니다. 노트북은 마지막 실행 결과를 포함해 내려받습니다.

전체 실행과 검사

마지막 확인: 앞 교시부터 순서대로 실행해도 같은 결과가 나오는가?

자동 검사와 관찰

자동 검사는 함수 입력 연결, 반환 이미지, 한 입력만 바꾼 설정, 파일 저장을 확인합니다. 그림의 구성 의도가 설득력 있는지와 관찰 문장이 이미지에 맞는지는 학생이 직접 확인합니다. PASS가 나와도 기록이 실제 관찰과 맞지 않으면 기록을 수정해야 합니다.

예상·관찰 기록까지 저장한 뒤 런타임 → 세션 다시 시작 → 모두 실행합니다. 공통 준비, 1교시, 2교시, 3교시의 순서로 실행됩니다. 검사는 앞 교시에서 남긴 기준·반환 이미지와 생성 함수, A 재현, 현재 비교본·개별 원본과 최종 작품의 선택·PNG 일치를 확인합니다. 새 세션 실행은 직접 확인하며 셀 실행 횟수로 판단하지 않습니다.

✅ 함수 입력 연결과 결과 반환 검사 통과
✅ B는 시드만, C는 개수 또는 큰 경계만 변경
✅ A 재현과 현재 입력의 결과 검사 통과
✅ 비교본과 원본 저장 검사 통과
✅ 생성 규칙과 예상·관찰 기록 확인
✅ 작품의 입력·선택·600 × 600 PNG 일치 확인
✅ 작품 의도와 선택 근거 확인
WEEK 06 PARAMETER GENERATOR COMPLETE

기준 이미지·반환 검사 오류

1교시 기준 이미지와 2교시 정상 반환 복구 셀을 확인합니다. 2교시의 잘못된 반환 예제를 마지막 상태로 남기지 않습니다. 수정 후 앞에서부터 순서대로 실행합니다.

관찰 기록 검사 오류

3교시 기록 셀의 안내 문장을 자신의 생성 규칙과 예상·관찰로 바꿉니다. 달라진 위치·밀도·표현을 근거로 적습니다.

FINAL CHECK의 inspect, 검증 함수와 픽셀 비교는 수업 범위 밖의 도구입니다. 검사 코드를 수정하지 않고 마지막 한글 오류가 가리키는 실습 셀을 수정합니다.

오류별 점검 순서
현상먼저 확인다시 실행할 순서
NameError앞 교시 정의·공통 준비공통 준비부터 해당 교시까지
C 입력 연결 오류키워드 오른쪽 count_c·large_c설정 → 호출 → 작품 제작 → 최종 선택 → 저장 → 검사
저장 파일이 이전 결과이미지 변경 뒤 저장 누락호출 → 작품 제작 → 최종 선택 → 저장 → 검사
작품 선택 불일치기준 설정과 최종 번호의 변경작품 제작 → 최종 선택 → 저장 → 검사
A 재현 실패기준 입력과 정의가 함께 갱신되었는지2교시 A → 3교시 순서
기록 미완성안내 문구를 자신의 문장으로 바꿨는지기록 → 검사

오류를 피하려고 검사 코드를 지우면 완료 여부를 확인할 수 없습니다. 메시지가 가리키는 작업 셀을 수정한 뒤, 마지막에는 새 세션에서 공통 준비부터 모두 실행합니다. 이것은 이전 실행에 우연히 남아 있던 변수 없이도 노트북이 완성된 작업 순서를 갖추었는지 확인하는 과정입니다.

결과물 제출

  1. 완료 문구와 1·2·3교시 출력·기록을 확인합니다.
  2. week06_학번_이름.ipynb를 다운로드합니다.
  3. 최종 작품 week06_학번_이름_artwork.png를 다운로드합니다.
  4. 두 파일을 제출하고 제출 완료를 확인하면 즉시 귀가합니다.
  5. 비교본과 A·B·C 원본도 자신의 폴더에 보관합니다. 추가 제출은 아닙니다.

선택 확장

필수 제출 후 create_artwork에 같은 표현과 다른 팔레트를 전달하거나, C에서 하지 않은 개수·경계 실험을 진행합니다. 비교할 때 다른 입력을 유지합니다. 추가 점수는 없습니다.

다음 학습: 이미지 변형

이번에 선택한 최종 작품 artwork.png를 다음 주에 사용합니다. 7주차에는 PNG를 불러와 자르기·크기 변경·회전·RGBA 합성에 적용합니다. 600 × 600 원본을 보관합니다. 제목 영역을 포함해 변형하거나 모듈 영역만 잘라 사용할 수 있습니다.

참고 자료

이 페이지의 목차