OpenCV 비전 실무16장 · AI 데이터 정제와 데이터 증강7 / 21← 이전목차다음 →MetaContents

16장. AI 데이터 정제와 데이터 증강

같은 사진 찾기

도서관 사서가 같은 책이 두 권 꽂혔는지 찾는다고 해 봅시다. 바코드가 똑같으면 같은 판의 같은 책입니다. 그런데 표지만 새로 입힌 개정판은 바코드가 다릅니다. 이럴 때는 표지 그림을 흘끗 보고 "거의 같은 책"이라고 알아봅니다. 같은 사진을 찾는 방법도 이 둘입니다. 파일의 바이트로 만든 지문(바코드)과 그림의 생김새로 만든 지문(표지)입니다.

파일 지문 MD5 와 그림 지문 평균 해시를 견준 비교 그림

왼쪽 상자의 MD5(Message Digest 5)는 파일의 바이트로 계산합니다. 한 바이트만 달라도 지문이 완전히 달라지므로, 바이트까지 같은 복사본만 찾습니다. 오른쪽 상자의 평균 해시는 그림을 8×8 로 줄인 밝기로 계산합니다. 조금 밝게 하거나 jpg 로 다시 저장해도 지문이 거의 같아서, 다시 저장한 비슷한 사진까지 찾습니다. 여기서 바코드가 MD5, 표지 그림이 평균 해시입니다.

두 귤 사진과 다른 귤 사진을 8×8 로 줄이고 평균보다 밝은 칸을 1 로 적어 견준 그림

위 두 줄은 tangerine_03.png 와, 그것을 조금 밝게 해서 jpg 로 다시 저장한 tangerine_11.jpg 입니다. 8×8 로 줄인 평균 밝기는 159 와 165 로 다르지만, 칸마다 "평균보다 밝은가"를 적은 지문 64칸은 하나도 다르지 않습니다(다른 칸 0). 셋째 줄의 다른 귤 사진은 64칸 가운데 41칸이 다릅니다. 다른 칸의 수가 해밍 거리입니다.

두 지문 견주기

견줄 것MD5 (파일 지문)평균 해시 (그림 지문)
무엇으로 계산파일의 바이트 전부8×8 로 줄인 흑백 밝기
지문의 꼴32글자(16진수)0·1 64칸
같다고 보는 기준32글자가 모두 같다해밍 거리가 작다(이 장은 5 이하)
찾는 것이름만 바꾼 복사본다시 저장하거나 조금 고친 사진까지
놓치는 것한 바이트라도 다르면 못 찾는다뒤집거나 크게 자른 사진은 못 찾는다
쓰는 도구파이썬의 hashlibOpenCV 의 resize 와 NumPy

짧은 예시

Python
import hashlib
import cv2

def md5_of(path):
    """파일을 바이트로 읽어 MD5 지문(32글자)을 돌려준다."""
    with open(path, "rb") as f:                   # rb = read binary(바이트로 읽기)
        return hashlib.md5(f.read()).hexdigest()  # hexdigest: 16진수 글자로 된 요약

# 글자 하나만 달라도 지문은 완전히 다르다
print(hashlib.md5(b"apple").hexdigest()[:8], hashlib.md5(b"appld").hexdigest()[:8])

# 이름만 바꾼 복사본은 지문이 같고, 다시 저장한 사진은 다르다
print(md5_of("ch16_raw/apple_02.png") == md5_of("ch16_raw/apple_10.png"))        # 결과: True
print(md5_of("ch16_raw/tangerine_03.png") == md5_of("ch16_raw/tangerine_11.jpg"))  # 결과: False

def ahash(img):
    """8×8 로 줄인 흑백에서 평균보다 밝은 칸을 1 로 적은 64칸 지문."""
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    small = cv2.resize(gray, (8, 8), interpolation=cv2.INTER_AREA)   # 넓이 평균으로 줄인다(14차시)
    return (small > small.mean()).flatten()        # flatten: 8×8 을 64칸 한 줄로 편다

a = ahash(cv2.imread("ch16_raw/tangerine_03.png"))
b = ahash(cv2.imread("ch16_raw/tangerine_11.jpg"))
print(int((a != b).sum()))     # 해밍 거리. 결과: 0

hashlib 은 파이썬에 처음부터 들어 있는 해시 도구 모음입니다. 첫 줄의 결과는 1f3870be 2e5c8d22 처럼 앞 8글자부터 전혀 다릅니다. INTER_AREA 로 줄이면 칸마다 덮는 넓이의 평균을 내므로 작은 무늬가 지워지고 큰 생김새만 남습니다.

주의할 점

  • 같은 사진이 학습용과 시험용에 갈라 들어가면, 모델은 시험에서 이미 본 사진을 맞히게 됩니다. 실력보다 점수가 높게 나오므로, 중복은 나누기 전에 지웁니다.
  • 평균 해시의 기준(5 이하)은 이 묶음에서 정한 값입니다. 서로 다른 사진의 거리가 가장 작게는 몇인지 실습 3에서 직접 보고 정합니다. 배경이 비슷한 사진이 많으면 다른 사진도 거리가 작게 나올 수 있습니다.
← 이전 절16장 · 흐린 사진 찾기다음 절 →16장 · 크기와 형식 맞추기