거리 변환(Distance Transform)이란? AI에서 픽셀마다 가장 가까운 배경까지의 거리를 구하는 방법
TL;DR
거리 변환(Distance Transform)은 이진 이미지의 각 전경 픽셀을 가장 가까운 배경 픽셀까지의 거리로 바꾸는 영상 처리 방법입니다. 대상의 안쪽이 배경에서 얼마나 떨어져 있는지 수치 지도로 표현합니다. 분할의 시작점 후보를 고르거나 모양을 살필 때 쓰지만 거리값은 물체 이름이나 정답 확률이 아닙니다. 전경·배경 방향, 거리 종류, 픽셀 간격과 정확·근사 계산을 함께 확인합니다.
핵심 3줄 요약
- 핵심 1
거리의 기준은 가장 가까운 배경입니다. 이 글에서는 0을 배경으로 두며 전경마다 여러 배경 후보 중 최소 거리를 기록합니다. - 핵심 2
같은 마스크도 거리 규칙에 따라 달라집니다. 직선 거리, 상하좌우 이동 거리와 대각선을 허용한 거리는 같은 숫자가 아닙니다. - 핵심 3
거리 지도와 물체 분리는 별도 단계입니다. 높은 거리에서 시작점 후보를 고를 수 있지만 최종 개수와 경계는 추가 검증이 필요합니다.
이 글에서 다룰 내용
- 거리 변환의 한 문장 정의
- 다섯 칸짜리 마스크로 이해하는 거리 지도
- AI 영상 처리에서 쓰는 이유와 계산 순서
- 유클리드·택시·체스판 거리와 주요 설정
- 형태학적 연산·CCL·이미지 분할과의 차이
- 시작점 후보 선택과 실전 체크리스트
- 반전·해상도·경계·정규화에서 주의할 점
거리 변환을 한 문장으로 정의하면 무엇인가요?
거리 변환은 정한 거리 척도 아래에서 각 전경 위치와 가장 가까운 배경 위치 사이의 최소 거리를 계산해 입력과 위치가 대응하는 수치 배열을 만드는 방법입니다.
영문명은 Distance Transform이며 결과를 거리 지도나 거리 맵이라고 부릅니다. 이 글은 0이 배경이고 0이 아닌 값이 전경인 이진 영상의 기본 변환을 다룹니다. 유클리드 거리를 정확히 계산하는 경우에는 EDT라는 이름도 씁니다. 색 사진만 넣는다고 물체와 배경이 자동으로 정해지는 것은 아닙니다.
SciPy 공식 EDT 문서는 각 비영 원소를 가장 가까운 0 원소까지의 거리로 바꾼다고 설명합니다. 따라서 배경 위치의 거리는 0입니다. 안쪽 전경의 값은 양수가 되지만 같은 물체 안에서도 가까운 배경의 위치에 따라 달라집니다. 밝기값이 큰 전경이라고 거리도 큰 것은 아닙니다.
한 줄 정리: 어떤 픽셀에 속하는지 정한 뒤 그 픽셀이 배경에서 얼마나 떨어져 있는지를 계산합니다. 대상의 의미를 새로 학습하는 단계는 아닙니다.
쉬운 예시로 이해해 볼까요?
감자나라ai님이 한 줄짜리 마스크
[0, 1, 1, 1, 0]
를 살핀다고 가정해 보겠습니다. 양끝 0은 배경이고 가운데 세 칸은 전경입니다. 이웃한 칸의 간격은 1이며 배열 안에 표시한 0만 거리의 기준으로 씁니다.
첫 전경은 왼쪽 배경까지 1, 가운데 전경은 어느 쪽 배경까지나 2, 마지막 전경은 오른쪽 배경까지 1만큼 떨어져 있습니다. 따라서 유클리드 거리 지도는
[0, 1, 2, 1, 0]
입니다. 모든 배경까지의 거리를 더하거나 전경의 중심 한 곳까지 재는 계산은 아닙니다.
같은 줄에서 거리
D > 1
인 칸을 고르면 가운데 한 칸만 남습니다. 원본 마스크와 이 선택 결과는 따로 보관합니다. 이 값 2는 해당 격자의 배경 픽셀까지의 거리이며 실제 부품의 반지름이나 폭을 그대로 측정한 수치는 아닙니다.
두 좌표가 행과 열 방향으로 각각 2칸 떨어져 있다면 직선 거리는 약 2.828, 상하좌우만 이동한 택시 거리는 4, 대각선 이동도 한 칸으로 세는 체스판 거리는 2입니다. 이 숫자는 가장 가까운 배경이 그 한 위치라고 정했을 때의 설명용 계산입니다.
이 글의 작은 배열과 거리값은 Python 표준 라이브러리의 직접 계산으로 확인했습니다. SciPy·OpenCV의 함수를 실행한 결과나 실제 영상의 분리 성능은 아닙니다. 원리 확인과 라이브러리별 설정 검증을 구분합니다.
쉬운 예시: 거리 지도에서 큰 값은 정한 배경에서 먼 전경 위치를 뜻합니다. 더 중요한 물체이거나 모델이 더 확신한 위치라는 뜻으로 읽지 않습니다.
왜 AI에서 거리 변환이 중요한가요?
이진 마스크의 안쪽 구조를 수치로 읽습니다
이진 마스크는 대상 여부만 표시하지만 거리 지도는 배경에 가까운 곳과 깊이 들어간 곳을 구별합니다. 같은 전경 안에서 좁은 연결부와 넓은 부분을 살피는 보조 자료가 됩니다. 다만 구멍이나 잘못 분류한 배경도 계산 기준에 들어가므로 입력 오류의 영향을 받습니다.
붙은 대상의 분할 시작점 후보를 만듭니다
scikit-image 공식 워터셰드 예제는 겹친 원의 배경 거리에서 국소 최대 위치를 고르고 이를 시작점으로 사용합니다. 이후 음의 거리 지도에 워터셰드를 적용해 영역을 나눕니다. 거리 계산만 끝냈다고 붙은 물체가 이미 분리된 것은 아닙니다.
학습 모델과 후처리의 역할을 나눕니다
분할 모델이 만든 마스크 뒤에 거리 계산을 붙이면 입력 마스크의 문제와 시작점 선택의 문제를 따로 조사합니다. 학습 없이 조정하는 단계지만 매끈한 거리 그림만으로 개선을 판정하지 않습니다. 실제 대상의 누락·합쳐짐·과도한 쪼개짐을 함께 봅니다.
핵심 인사이트: 거리 지도는 다음 처리에 쓸 기하 정보를 담습니다. 실제 물체 수나 최종 분할의 정확성은 원본과 정답을 대조해 별도로 확인합니다.
거리 변환은 어떤 순서로 작동하나요?
1. 전경과 거리의 기준을 정합니다
관심 대상을 비영 값으로, 기준 배경을 0으로 표시합니다. 어두운 글자나 검은 부품을 처리할 때 화면의 흰색을 무조건 전경으로 보지 않습니다. 여러 클래스 번호가 있는 지도라면 필요한 클래스만 선택합니다. 서로 다른 비영 번호가 그대로 개별 대상으로 유지된다고 가정하지 않습니다.
2. 거리 척도와 격자 간격을 선택합니다
유클리드 거리는 축별 좌표 차이를 제곱해 더한 뒤 제곱근을 취합니다. 택시 거리는 축별 절댓값 차이를 더하고 체스판 거리는 가장 큰 축 차이를 씁니다. 2차원의 단위 격자를 설명하는 규칙이며 축 간격이 다르면 실제 길이를 반영한 계산을 따로 설정합니다.
3. 최소 거리를 기록하고 후속 작업에 넘깁니다
정의상 각 전경에서 배경 후보까지의 거리 중 최솟값을 기록합니다. 그렇다고 실제의 빠른 구현이 모든 픽셀 쌍을 반드시 하나씩 비교하는 것은 아닙니다. OpenCV는 정확 계산과 작은 이동 마스크를 사용하는 근사 계산을 구분합니다. 출력 배열은 입력의 각 위치와 대응하도록 유지합니다.
거리값에서 높은 위치나 일정 거리보다 안쪽인 구역을 고르는 일은 별도 처리입니다. OpenCV 공식 거리 변환 튜토리얼도 이진화, 거리 계산, 표시용 정규화, 시작점 생성, 워터셰드를 구분해 실행합니다. 예제의 임계값을 다른 촬영 영상의 정답 기준으로 옮기지 않습니다.
실전 팁: 원본·입력 마스크·원래 거리 배열·표시용 그림을 분리해 저장하세요. 정규화된 그림만 남기면 원래 거리 단위를 잃기 쉽습니다.
주요 설정과 결과는 어떻게 읽나요?
SciPy의 EDT는 축별 간격을 받습니다
distance_transform_edt
의
sampling
은 배열의 각 축 간격입니다. 생략하면 모든 축의 간격을 1로 봅니다. 2차원 행·열 배열에
sampling=[2, 1]
을 주면 행 방향 한 칸은 2단위, 열 방향 한 칸은 1단위입니다. 화면의 가로·세로 이름만 보고 순서를 바꾸지 않습니다.
return_indices=True
는 가장 가까운 배경 원소의 좌표도 받는 설정입니다. 거리의 기본 반환은 입력과 같은 모양의 실수 배열이며 좌표 결과는 축마다 별도 배열을 둡니다. 좌표는 의미 클래스나 대상 번호가 아닙니다. 배경 후보가 동점인 위치의 좌표를 영구 식별자로 쓰지도 않습니다.
택시·체스판 거리와 유클리드 거리를 구분합니다
SciPy의 CDT 문서에서
distance_transform_cdt
는 기본
metric="chessboard"
를 쓰며
metric="taxicab"
도 지원합니다. 이름이 비슷한 거리 함수라고 EDT와 같은 결과를 기대하면 안 됩니다. 비교 실험에서는 거리 종류를 반드시 함께 기록합니다.
OpenCV의 정확 계산과 레이블 반환은 같은 경로가 아닙니다
OpenCV 공식 distanceTransform 문서의 입력은 8비트 단일 채널 이진 영상입니다.
DIST_L2
에서 3×3·5×5 이동 마스크는 근사 계산이며 정확 유클리드 경로는
DIST_MASK_PRECISE
로 구분합니다. 작은 마스크 크기는 물체별 영역을 자르는 크기가 아닙니다.
distanceTransformWithLabels
는 가까운 0 픽셀 또는 0의 연결 성분에 따른 레이블을 추가로 돌려줍니다. 확인한 문서에서 이 레이블 반환 경로는
DIST_MASK_PRECISE
를 지원하지 않습니다. 거리만 정확히 계산하는 호출의 옵션을 그대로 옮기지 않습니다.
한 줄 정리: 함수 이름, 거리 종류, 정확·근사 여부, 간격과 반환 배열의 의미를 함께 읽습니다. 거리의 숫자와 배경의 식별 번호는 다릅니다.
거리 변환과 헷갈리는 용어는 무엇이 다른가요?
형태학적 연산·연결 성분 레이블링과의 차이
형태학적 연산은 구조 요소로 픽셀 영역이나 밝기를 바꿉니다. 거리 변환은 준비한 마스크에서 배경까지의 거리를 구합니다. 연결 성분 레이블링(CCL)은 연결 덩어리에 번호를 붙입니다. 마스크의 수정, 거리 계산, 영역 식별은 서로 다른 결과를 냅니다.
이미지 분할·워터셰드와의 차이
이미지 분할은 픽셀을 영역이나 대상에 할당하는 넓은 작업입니다. 워터셰드는 시작점과 지형처럼 해석한 값으로 영역을 확장하는 분할 방법입니다. 거리 지도는 그 시작점이나 지형을 만드는 자료로 쓰일 수 있으며 최종 정수 영역 지도와 같지 않습니다.
깊이 지도·특징 거리 학습과의 차이
깊이 지도는 카메라와 장면 지점 사이의 거리를 표현하는 데 쓰입니다. 여기서의 거리 변환은 같은 마스크의 배경까지 재므로 촬영 거리를 복원하지 않습니다. 이웃 성분 분석(NCA)의 거리 학습도 표본 특징의 표현을 배우는 문제로 이진 격자의 배경 거리와 구분합니다.
비교 정리: 입력이 같은 이미지여도 출력의 뜻을 확인하세요. 전경 여부, 연결 번호, 배경까지의 거리와 카메라 깊이는 서로 바꿔 읽을 수 없습니다.
실전에서는 어디에 쓰이나요?
겹친 대상의 분할 후보를 준비합니다
단순한 둥근 대상들이 붙어 있는 영상에서는 거리 지도의 높은 위치가 개별 대상의 시작점 후보가 될 수 있습니다. 공식 원 예제처럼 마커를 정하고 분할 결과와 원본을 대조합니다. 길쭉하거나 굴곡진 한 물체에 여러 봉우리가 생기면 하나가 여러 개로 나뉠 수도 있습니다.
마스크 내부의 여유와 형태를 살핍니다
선택한 배경에서 일정 거리 이상 떨어진 전경을 검토 구역으로 고르는 방식에 쓸 수 있습니다. 원래 거리 배열에 조건을 적용한 뒤 얇은 부분이 빠졌는지 봅니다. 배경 픽셀 중심까지의 격자 거리를 실제 물체의 연속 윤곽까지 잰 정밀 치수로 소개하지 않습니다.
거리 변환을 적용할 때 어떤 순서로 확인하나요?
1. 작은 입력에서 방향과 단위를 확인합니다
배경이 있는 작은 마스크로 0의 출력이 0인지, 안쪽 전경의 거리가 기대와 맞는지 확인합니다. 전부 배경인 입력과 배경이 없는 입력도 따로 점검합니다. 계산 기준이 될 0이 없다면 의미 있는 최근접 배경 측정으로 취급하지 말고 입력·경계 규칙을 먼저 정합니다.
2. 원래 거리와 표시용 정규화를 분리합니다
보기 편하게 각 영상을 0부터 1까지 맞추면 원래 최대 거리가 서로 달라도 같은 흰색으로 보일 수 있습니다. 임계값을 원래 단위로 줄지 영상별 비율로 줄지 명확히 적습니다. OpenCV 예제의 정규화 뒤 임계값은 모든 영상에서 같은 픽셀 거리를 뜻하지 않습니다.
3. 다음 단계의 오류와 비용을 비교합니다
시작점 수, 최종 영역 수, 여러 대상의 합쳐짐과 한 대상의 쪼개짐을 나눠 기록합니다. 설정을 고른 자료와 최종 평가 자료를 분리하고 같은 마스크에서 거리 척도와 근사 옵션을 비교합니다. 실제 해상도에서 시간·메모리와 라이브러리 버전도 남깁니다.
체크리스트: 전경 정의, 기준 배경, 축 간격, 거리 종류, 정확·근사 옵션, 원래 수치 배열과 최종 작업 결과가 함께 남아 있는지 확인하세요.
사용할 때 무엇을 주의해야 하나요?
첫째, 전경과 배경을 뒤집지 않습니다. 흰 배경의 검은 글자를 그대로 넣으면 기대한 대상의 안쪽이 아닌 다른 곳을 잴 수 있습니다. 관심 영역을 명시적으로 마스크로 만든 뒤 거리의 기준인 0 위치를 눈으로 확인합니다.
둘째, 가장자리와 내부 구멍도 입력의 일부입니다. 잘라낸 화면 밖을 자동으로 배경이라 가정하지 않습니다. 필요해 배경 테두리를 추가한다면 그 조건을 기록합니다. 내부의 작은 0 구멍도 가까운 배경이 되어 주변 거리값을 낮출 수 있습니다.
셋째, 픽셀 거리를 실제 길이로 바로 읽지 않습니다. 해상도·촬영 배율·축 간격을 맞추고 좌표 기준을 확인합니다. 크기를 줄인 마스크의 결과와 원본 결과는 같은 단위의 수치가 아닐 수 있습니다. 보정 전의 값을 밀리미터라고 부르지 않습니다.
넷째, 봉우리 개수를 물체 개수로 확정하지 않습니다. 잡음과 구멍, 굴곡, 시작점 간격에 따라 후보가 늘거나 사라집니다. 하나의 물체에 여러 시작점이 생기거나 붙은 두 물체에 하나만 생기는 사례를 각각 확인합니다.
주의: 정확한 유클리드 계산이라는 말은 입력 격자에서의 거리 계산을 가리킵니다. 마스크의 정답, 실제 치수와 물체 분리까지 정확하다는 보증이 아닙니다.
자주 묻는 질문
Q1. 거리 변환은 AI 모델을 학습하는 방법인가요?
이 글의 기본 거리 변환은 정한 마스크와 거리 규칙으로 계산합니다. 영상 AI의 전처리나 후처리에 쓸 수 있지만 물체 이름이나 특징의 가중치를 이 단계에서 학습하지 않습니다.
Q2. 회색조 사진을 넣으면 밝기 차이의 거리가 나오나요?
여기서 설명한 입력은 대상과 배경을 구분한 마스크입니다. SciPy EDT는 참인 값을 전경으로 처리합니다. 밝기 차이의 크기를 재려면 다른 정의와 처리가 필요하며 전경값 1과 255를 거리 크기로 읽지 않습니다.
Q3. 값이 가장 큰 픽셀이 항상 물체의 중심인가요?
가장 가까운 배경에서 멀리 떨어진 위치입니다. 모양에 따라 여러 최대 위치나 같은 값의 평평한 구역이 생길 수 있으며 면적 중심과 같다는 약속은 없습니다. 중심 후보를 쓰려면 선택 규칙을 따로 정합니다.
Q4. 마스크를 반전하면 같은 거리 지도가 나오나요?
기준이 되는 0 위치가 달라지므로 같은 측정이 아닙니다. 대상 안에서 배경까지 재는 것과 배경 쪽에서 대상까지 재는 것을 구분합니다. 거리값에 안팎의 부호를 붙이는 지도 역시 별도 정의가 필요합니다.
Q5. 정확 계산을 쓰면 붙은 물체가 자동으로 분리되나요?
아닙니다. 정확 계산은 선택한 격자 거리의 문제입니다. 시작점 선택과 분할은 별도 단계이며 모양과 입력 오류에 따라 결과가 달라집니다. 실제 대상별 정답과 합쳐짐·쪼개짐을 비교해야 합니다.
출처
마무리
거리 변환은 전경의 각 위치에서 가장 가까운 배경까지의 거리를 수치 지도로 나타냅니다. 이진 마스크의 안쪽 구조를 살피고 분할 시작점 후보를 만드는 데 쓰입니다. 같은 입력이라도 거리 척도, 축 간격과 정확·근사 계산을 맞춰야 숫자를 비교할 수 있습니다.
처음 적용한다면 0이 무엇인지와 한 칸의 길이부터 확인하세요. 작은 배열로 기대 거리를 확인한 뒤 원래 수치 배열과 표시용 그림을 나눠 보관합니다. 그다음 시작점과 최종 분할을 따로 점검하면 보기 좋은 거리 그림과 실제 업무에 맞는 결과를 구별하기 쉽습니다.
