OpenCV에서 이미지 좌표계 이해하기: (x, y)와 행/열 혼동 줄이기

대상: OpenCV로 이미지 처리나 ROI(관심영역) 지정, 픽셀 좌표 계산을 자주 하는 개발자
환경: Ubuntu 20.04 / 22.04, Python 3.x 또는 C++ 기반 OpenCV 프로젝트


1. 문제/주제 요약

OpenCV를 사용하다 보면 (x, y) 좌표와 (row, col) 인덱스 개념이 자주 헷갈린다.
특히 cv::circle(), cv::rectangle(), img[y][x] 접근 등이 혼용되어 있을 때, 좌표가 뒤집히거나 픽셀이 엉뚱한 위치에 표시되는 문제가 발생한다.
이 글에서는 OpenCV의 좌표계 기준과 행렬 인덱싱의 차이를 명확히 정리한다.


2. 원인/배경 설명

OpenCV의 이미지는 행렬(Mat) 형태로 저장되며, 행(row)열(col) 의 개념을 가진다.
하지만 그래픽 함수(cv2.line, cv2.circle)는 수학적 좌표계(x, y) 를 사용한다.

즉, 다음 두 개념이 서로 다르다:

구분개념의미OpenCV에서 주로 쓰이는 곳
행렬 인덱스(row, col)이미지 배열의 위치img[row][col], img[y][x]
좌표계(x, y)수평/수직 거리 (픽셀 좌표)cv2.circle(img, (x, y)), cv2.putText()

즉,

  • 행렬(row, col)y가 먼저, x가 나중
  • 좌표(x, y)x가 먼저, y가 나중

3. 실제 예시로 비교하기

(1) 이미지 픽셀 접근

import cv2

img = cv2.imread('image.jpg')

# 행렬 접근 방식
b, g, r = img[100, 200]  # (row=100, col=200)

# 여기서 100은 y좌표, 200은 x좌표와 대응된다.
print(f"픽셀 위치: (x={200}, y={100}), 색상={r,g,b}")

즉, img[y, x] 로 접근해야 원하는 픽셀을 가져올 수 있다.


(2) OpenCV 도형 함수

도형을 그릴 때는 (x, y) 순서로 입력한다.

cv2.circle(img, (200, 100), 5, (0, 0, 255), -1)
cv2.putText(img, "Point (200,100)", (200, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))

주의: cv2.circle()(x, y) 좌표,
하지만 img[y, x] 는 행렬 접근이므로 순서가 반대다.


(3) ROI(Region of Interest) 지정

# ROI: y축(세로), x축(가로)
roi = img[100:200, 150:300]  # y:100~199, x:150~299

→ 즉, ROI의 첫 번째 인덱스는 세로(y), 두 번째 인덱스는 가로(x)


(4) 좌표계를 시각적으로 정리하면:

(0,0) ----------------------> x (col)
 |
 |
 |
 v
 y (row)

즉,

  • x는 오른쪽으로 증가
  • y는 아래쪽으로 증가
  • OpenCV의 원점(0,0)은 왼쪽 상단

4. 추가 팁 / 자주 하는 실수

실수잘못된 예올바른 예
점 표시가 엉뚱한 위치에 그려짐cv2.circle(img, (y, x), 5, ...)cv2.circle(img, (x, y), 5, ...)
ROI 범위를 반대로 설정img[x1:x2, y1:y2]img[y1:y2, x1:x2]
픽셀 접근 시 좌표계 기준 혼동img[x, y]img[y, x]

💡 :

  • 이미지 배열(img[][]) 접근 시: (y, x)
  • 도형, 텍스트, 좌표 기반 함수 사용 시: (x, y)
  • numpy 기반 연산을 할 때는 항상 img.shape = (height, width, channels) 로 생각하자.

5. 정리

  • OpenCV는 행렬 기반 구조(Mat) 이므로 인덱싱은 (row, col)(y, x) 순서다.
  • 하지만 그래픽 함수와 좌표계는 (x, y) 로 사용한다.
  • 헷갈릴 때는 항상 img.shapecv2.circle 의 인자 순서를 비교해보면 혼동을 줄일 수 있다.

댓글 남기기