image profile 측정
설명
이미지를 y축 방향으로 전체 높이의 1/10 간격 구간으로 나누고, 구간마다 평균한 x방향 Contrast profile을 보여준다
필요 데이터
이미지 파일 1개(png/jpg/bmp/tif, 실행 중 선택) — df는 사용하지 않음
출력
구간 경계를 표시한 이미지 + 구간별 평균 profile 그래프
태그
visualization
작성자
메이커-4e07 | MDS 1.0
이미지를 y축 방향으로 전체 높이의 1/10 간격 구간으로 나누고, 구간마다 평균한 x방향 Contrast profile을 보여준다
README
이미지를 y축 방향으로 전체 높이의 1/10 간격 구간으로 나누고, 구간마다 평균한 x방향 Contrast profile을 보여준다
이미지 파일 1개(png/jpg/bmp/tif, 실행 중 선택) — df는 사용하지 않음
구간 경계를 표시한 이미지 + 구간별 평균 profile 그래프
visualization
메이커-4e07 | MDS 1.0
# MDS_DESC: 이미지를 y축 방향으로 전체 높이의 1/10 간격 구간으로 나누고, 구간마다 평균한 x방향 Contrast profile을 보여준다
# MDS_TAGS: visualization
# MDS_INPUT: 이미지 파일 1개(png/jpg/bmp/tif, 실행 중 선택) — df는 사용하지 않음
# MDS_OUTPUT: 구간 경계를 표시한 이미지 + 구간별 평균 profile 그래프
from PIL import Image
N_BANDS = 10 # y축 간격 = 전체 높이의 1/10
def load_gray_image(path: str) -> np.ndarray:
with Image.open(path) as img:
arr = np.array(img)
if arr.ndim == 3:
arr = arr[..., :3].astype(np.float32) @ np.array([0.299, 0.587, 0.114], dtype=np.float32)
return arr.astype(np.float32)
def band_profiles(gray: np.ndarray, n_bands: int) -> tuple[np.ndarray, np.ndarray]:
height = gray.shape[0]
n_bands = max(1, min(n_bands, height))
edges = np.linspace(0, height, n_bands + 1).astype(int)
profiles = np.stack([gray[edges[i]:edges[i + 1], :].mean(axis=0) for i in range(n_bands)])
return profiles, edges
def michelson_contrast(profile: np.ndarray) -> float:
p_max, p_min = float(profile.max()), float(profile.min())
denom = p_max + p_min
return (p_max - p_min) / denom if denom > 0 else 0.0
def plot_profiles(gray: np.ndarray, profiles: np.ndarray, edges: np.ndarray, title: str) -> None:
plt.rcParams['font.family'] = 'Malgun Gothic'
plt.rcParams['axes.unicode_minus'] = False
fig, (ax_img, ax_prof) = plt.subplots(1, 2, figsize=(12, 5))
colors = plt.cm.viridis(np.linspace(0, 1, len(profiles)))
ax_img.imshow(gray, cmap="gray", aspect="auto")
for i, y in enumerate(edges[1:-1]):
ax_img.axhline(y, color=colors[i + 1], linewidth=0.8)
ax_img.set_title(title)
ax_img.set_xlabel("x (pixel)")
ax_img.set_ylabel("y (pixel)")
x = np.arange(profiles.shape[1])
for i, prof in enumerate(profiles):
label = f"y {edges[i]}–{edges[i + 1]} (C={michelson_contrast(prof):.3f})"
ax_prof.plot(x, prof, color=colors[i], linewidth=1.0, label=label)
ax_prof.set_title("y 구간별 평균 profile")
ax_prof.set_xlabel("x (pixel)")
ax_prof.set_ylabel("평균 강도")
ax_prof.grid(True, alpha=0.3)
ax_prof.legend(fontsize=7, loc="best")
plt.tight_layout()
plt.show()
plt.close(fig)
def run(df: pd.DataFrame) -> str:
path = mIO.open_file_single(
dialog_title="이미지 파일 선택",
file_filter="Images (*.png *.jpg *.jpeg *.bmp *.tif *.tiff)",
initial_dir=None,
)
if not path:
return "사용자가 취소했습니다."
gray = load_gray_image(path)
profiles, edges = band_profiles(gray, N_BANDS)
plot_profiles(gray, profiles, edges, title=os.path.basename(path))
return f"{gray.shape[1]}×{gray.shape[0]} 이미지, {len(profiles)}개 구간 profile 생성"
import os
result = run(df)댓글