1장. AI 비전과 OpenCV 개발환경
프로젝트 1 — 수업 전 실습 PC 점검 스크립트
강사는 수업 전에 실습실 PC 마다 OpenCV 가 제대로 깔렸는지, 수강생에게 나눠 준 그림 파일이 모두 열리는지 확인하고 싶습니다. PC 가 여러 대라 손으로 하나씩 열어 보기는 번거롭습니다. 실행하면 한 번에 점검표를 찍어 주는 스크립트를 만들어 보세요.
점검할 폴더는 ch01_samples/ 입니다. 이 폴더의 파일은 연습용으로 만든 가상 파일입니다.
| 파일 | 내용 |
|---|---|
parcel_box.png | 택배 상자 그림 (컬러) |
road_sign.jpg | 둥근 교통 표지 그림 (컬러, jpg) |
gear_gray.png | 공장 부품(톱니바퀴) 그림 (흑백) |
broken.png | 이름만 png 이고 속은 그림이 아닌 파일 (내려받다 끊긴 파일을 흉내 냄) |
요구사항
- OpenCV, NumPy, Matplotlib 의 버전을 찍습니다.
ch01_samples/의 파일을 모두 읽어, 파일마다 이름, 가로, 세로, 채널 수, 파일 크기(KB), 상태(정상 또는 읽기 실패)를 표로 찍습니다.- 흑백 그림은 흑백 그대로 읽어 채널 수가 1로 나오게 합니다.
- 읽기 실패한 파일의 개수와 이름을 따로 알려 줍니다.
- 정상인 그림을 높이를 맞춰 가로로 이어 붙인 미리보기를
out_ch01_contact.png로 저장하고 화면에 띄웁니다.
힌트
- 폴더의 파일 목록은
sorted(os.listdir("ch01_samples"))로 얻습니다. cv2.imread(경로, cv2.IMREAD_UNCHANGED)로 읽으면 흑백 그림은 (세로, 가로) 모양으로 읽힙니다.img.ndim(차원 수)이 2면 채널 1개입니다.- 읽은 결과가
None이면 상태를 "읽기 실패"로 적고 다음 파일로 넘어갑니다. - 표는 사전의 목록을
pandas.DataFrame으로 바꿔to_string(index=False)로 찍으면 깔끔합니다. - 이어 붙이려면 높이와 채널이 같아야 합니다. 흑백은
cv2.COLOR_GRAY2BGR로 채널을 셋으로 맞추고,cv2.resize로 높이를 맞춘 뒤cv2.hconcat으로 붙입니다.
채점 기준
| 항목 | 기준 | 점수 |
|---|---|---|
| 버전 점검 | 세 패키지의 버전을 찍는다 | 15 |
| 점검표 | 파일마다 여섯 칸을 빠짐없이 찍는다 | 30 |
| 흑백 처리 | 흑백 그림의 채널이 1로 나온다 | 15 |
| 실패 처리 | 깨진 파일에서 멈추지 않고 실패로 적고, 개수와 이름을 알린다 | 20 |
| 미리보기 | 정상 그림만 높이를 맞춰 이어 붙여 저장하고 띄운다 | 20 |
코드의 흐름
그림의 다섯 단계를 예시 풀이의 단계와 같은 순서로 짰습니다. 셋째 단계에서 읽기에 실패한 파일은 점검표에만 적고 넷째·다섯째 단계의 미리보기에서는 뺍니다.
실제 데이터로 해 보려면
실습실에서 쓸 실제 그림은 수업에서 쓸 공개 데이터를 내려받아 같은 방법으로 점검합니다. 예를 들어 AI Hub(aihub.or.kr)에는 제조 부품, 농산물, 교통 표지 같은 이미지 데이터가 공개돼 있습니다. 내려받기 전에 데이터마다 이용 약관(상업적 이용 가능 여부, 재배포 금지 등)을 확인하고, 사람의 얼굴이나 차량 번호가 찍힌 사진은 개인정보 처리 기준을 먼저 확인합니다. 폴더 이름만 바꾸면 이 스크립트를 그대로 쓸 수 있습니다.
결과 보기 (예시 풀이)
1단계. 버전 찍기
import os
import cv2
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
plt.rcParams["font.family"] = "Malgun Gothic"
plt.rcParams["axes.unicode_minus"] = False
# 요구사항 1: 세 패키지의 버전
print("[환경 점검]")
for name, module in [("OpenCV", cv2), ("NumPy", np), ("Matplotlib", matplotlib)]:
print(f" {name:11}{module.__version__}")[환경 점검]
OpenCV 5.0.0
NumPy 2.5.4
Matplotlib 3.11.22단계. 파일을 하나씩 읽어 점검표 만들기
folder = "ch01_samples"
rows, images, failed = [], [], []
for name in sorted(os.listdir(folder)):
path = os.path.join(folder, name) # "ch01_samples/파일 이름" 꼴의 경로
size_kb = round(os.path.getsize(path) / 1024, 1)
# IMREAD_UNCHANGED: 저장된 그대로 읽는다. 흑백 그림은 채널 없이 (세로, 가로) 로 읽힌다
img = cv2.imread(path, cv2.IMREAD_UNCHANGED)
if img is None:
# 요구사항 4: 실패한 파일은 표에 적고 다음 파일로 넘어간다
rows.append({"파일": name, "가로": "-", "세로": "-", "채널": "-", "KB": size_kb, "상태": "읽기 실패"})
failed.append(name)
continue
h, w = img.shape[:2]
channels = 1 if img.ndim == 2 else img.shape[2] # 요구사항 3: 2차원이면 흑백(채널 1)
rows.append({"파일": name, "가로": w, "세로": h, "채널": channels, "KB": size_kb, "상태": "정상"})
images.append((name, img))
# 요구사항 2: 사전 목록을 표로 바꿔 찍는다
print("[파일 점검표]")
print(pd.DataFrame(rows).to_string(index=False))[파일 점검표]
파일 가로 세로 채널 KB 상태
broken.png - - - 0.1 읽기 실패
gear_gray.png 160 160 1 2.4 정상
parcel_box.png 200 160 3 2.8 정상
road_sign.jpg 180 180 3 5.2 정상3단계. 실패한 파일 알리기
# 요구사항 4: 실패 개수와 이름
print(f"정상 {len(images)}개 · 읽기 실패 {len(failed)}개")
for name in failed:
print(" 확인할 파일:", name)정상 3개 · 읽기 실패 1개
확인할 파일: broken.png4단계. 높이를 맞춰 이어 붙이고 저장하기
target_h = 160 # 미리보기에서 맞출 높이(칸)
tiles = []
for name, img in images:
if img.ndim == 2:
# 흑백(채널 1)을 컬러(채널 3)로: 세 채널에 같은 밝기를 넣어 이어 붙일 수 있게 한다
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
h, w = img.shape[:2]
new_w = round(w * target_h / h) # 가로세로 비율을 지키며 높이를 160 에 맞춘다
# cv2.resize(그림, (새 가로, 새 세로)): 크기를 바꾼다. 크기는 (가로, 세로) 순서로 준다
tiles.append(cv2.resize(img, (new_w, target_h)))
# cv2.hconcat: horizontal concatenate. 높이와 채널이 같은 그림들을 가로로 붙인다
sheet = cv2.hconcat(tiles)
print("미리보기 모양:", sheet.shape)
print("저장:", cv2.imwrite("out_ch01_contact.png", sheet))미리보기 모양: (160, 520, 3)
저장: True5단계. 화면에 띄우기
plt.figure(figsize=(9, 2.8))
plt.imshow(cv2.cvtColor(sheet, cv2.COLOR_BGR2RGB)) # 띄울 때는 RGB 로 바꾼다
plt.title("정상으로 읽힌 그림 " + " · ".join(name for name, _ in images))
plt.axis("off")
plt.show()
점검표를 보면 네 파일 가운데 broken.png 하나만 읽기 실패입니다. 크기가 0.1KB 로 다른 그림보다 훨씬 작은 것도 이상하다는 신호입니다. 스크립트는 이 파일에서 멈추지 않고 실패로 적은 뒤 다음 파일로 넘어갔습니다. gear_gray.png 는 IMREAD_UNCHANGED 로 읽어 채널이 1로 나왔고, 미리보기에서는 COLOR_GRAY2BGR 로 채널을 셋으로 맞춰 붙였습니다. 세 그림의 높이를 160 으로 맞추면 가로는 톱니바퀴 160, 택배 상자 200, 교통 표지 160 이 되어, 미리보기의 모양은 (160, 520, 3) 입니다. 실습실 PC 마다 이 스크립트를 한 번 돌리면 버전과 파일 상태를 한눈에 확인할 수 있습니다.