[연구 자동화] 파이썬 OpenCV로 수백 장의 실험 이미지(SEM/세포) 분석 및 치수 측정 자동화하기
신소재공학, 생명공학, 혹은 나노 기술을 연구하는 분들이라면 SEM(주사전자현미경), TEM, 혹은 광학 현미경으로 촬영한 수백 장의 이미지 파일을 마주하게 됩니다. 연구의 핵심 데이터를 얻기 위해 우리는 이미지 안의 나노 입자 크기를 재거나, 세포의 개수를 세고, 특정 구조의 면적을 계산해야 합니다. 하지만 ImageJ와 같은 프로그램을 띄워놓고 마우스로 일일이 선을 그어가며 치수를 측정하는 작업은 눈의 피로도를 높일 뿐만 아니라, 측정하는 사람의 주관에 따라 오차가 발생할 위험이 큽니다. 만약 분석해야 할 사진이 500장이라면 어떨까요? 아마 며칠 밤을 꼬박 새워야 할지도 모릅니다. 이번 포스팅에서는 파이썬의 강력한 컴퓨터 비전 라이브러리인 **OpenCV**를 활용하여, 수백 장의 실험 이미지에서 입자의 크기와 개수를 1초 만에 자동으로 추출하는 '이미지 프로세싱 자동화' 기법을 소개합니다.
1. 왜 ImageJ 대신 파이썬 OpenCV인가?
연구 현장에서 가장 널리 쓰이는 ImageJ는 훌륭한 도구이지만, 대량의 파일을 처리하는 '배치 프로세싱(Batch Processing)'에서는 파이썬 스크립트의 유연함을 따라오지 못합니다. 파이썬 OpenCV를 사용하면 이미지의 밝기 조절(Thresholding), 노이즈 제거(Filtering), 윤곽선 검출(Contour Detection) 과정을 하나의 파이프라인으로 묶어 수천 장의 사진에 동일한 잣대를 적용할 수 있습니다.
이는 연구의 **객관성**과 **재현성**을 확보하는 데 결정적인 역할을 합니다. 사람이 측정할 때 생길 수 있는 편향(Bias)을 제거하고, "모든 입자는 동일한 이진화 알고리즘에 의해 판별되었다"는 논리적인 근거를 논문에 제시할 수 있기 때문입니다.
2. 이미지 분석 자동화의 핵심: 이진화(Thresholding)와 윤곽선 추출
실험 이미지 분석의 첫 단추는 배경과 분석 대상을 분리하는 '이진화' 작업입니다. 흑백 이미지에서 특정 밝기 값 이상의 픽셀은 흰색(대상), 나머지는 검은색(배경)으로 바꾸는 과정입니다. OpenCV의 cv2.adaptiveThreshold 기능을 사용하면, 조명이 불균일한 사진에서도 주변 픽셀과의 밝기 차이를 계산하여 아주 정밀하게 물체를 떼어낼 수 있습니다.
대상이 분리되었다면 cv2.findContours 함수를 통해 물체의 외곽선을 찾습니다. 이 외곽선 정보를 바탕으로 각 입자의 면적, 둘레, 장축과 단축의 길이 등을 수학적으로 계산해낼 수 있습니다.
3. 실전 파이썬 코드: 폴더 내 모든 이미지의 입자 크기 자동 측정
아래의 코드는 특정 폴더 내의 이미지 파일들을 읽어 입자의 개수를 세고, 각 입자의 면적을 계산하여 엑셀(CSV) 파일로 정리해 주는 실전 스크립트입니다. (터미널에서 pip install opencv-python pandas를 먼저 실행하세요.)
import cv2
import pandas as pd
import glob
import os
# 1. 이미지 폴더 경로 설정
image_path = './exp_images/*.jpg'
image_files = glob.glob(image_path)
results = []
for img_file in image_files:
# 2. 이미지 로드 및 그레이스케일 변환
img = cv2.imread(img_file)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 3. 가우시안 블러로 노이즈 제거 후 이진화(Otsu 알고리즘)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
ret, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 4. 윤곽선(Contour) 찾기
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 5. 각 윤곽선의 면적 계산 (너무 작은 노이즈는 제외)
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 100: # 최소 면적 기준 설정
results.append({
'File': os.path.basename(img_file),
'Particle_Area': area
})
# 6. 결과를 Pandas 데이터프레임으로 변환 후 CSV 저장
df = pd.DataFrame(results)
df.to_csv('particle_analysis_results.csv', index=False)
print(f"분석 완료! 총 {len(image_files)}장의 이미지에서 데이터를 추출했습니다.")
결론: 눈보다 정확한 코드로 데이터의 격을 높이세요
오늘 소개한 OpenCV 자동화 기법은 단순한 시간 절약을 넘어 여러분의 실험 결과에 '수학적 엄밀함'을 더해줍니다. 수작업으로 잰 100개의 샘플보다, 자동화 코드로 분석한 10,000개의 샘플이 통계적으로 훨씬 강력한 설득력을 가집니다. 이제 지루한 치수 측정 작업은 파이썬에게 맡기고, 여러분은 도출된 입자 크기 분포가 실험 조건에 따라 어떻게 변하는지, 그 물리적 의미를 고찰하는 연구의 핵심 본질에 더 집중하시기 바랍니다.