2 분 소요

OpenCV에서 애를 먹고 있다..

컴퓨터비전의 5번째 과제를 수행중이다(과제 개많네..ㅜㅜ)

과제의 주제는 비주얼 오도메트리와 카메라모션의 이해이고,

이를 수행하는 목적은 두장 이상의 이미지로부터 카메라의 모션을 추정하고 피쳐 포인트들의 3차원 구조를 계산해보기 위함인 것 같다.

이를 위해 총 4개의 미션을 수행해야 한다.(아이고ㅜ)

  1. Aruco Marker Detection 과 ID판단하기
  2. 두 카메라 사이의 카메라모션 추정하기 (2D-2D)
  3. 월드좌표계에 대한 카메라 위치 추정(3D-2D, PnP)
  4. Structure from motion(비주얼 오도메트리)

4번 미션의 경우에는 VisualSFM프로그램과 CloudCompare프로그램을 활용하는 미션인 것 같다. 재미있을 것 같기는 하나, 그만한 고통도 따라올것 같다.

시작!

1.Aruco Marker Detection 과 ID판단하기

교수님이 준 참고자료를 보았을떄는 이렇게 되어 있었는데,

brave_mn7CXNM6BK

이를 참고하여 이렇게 코드를 짜보았다.

import cv2
import matplotlib.pyplot as plt

# ArUco 마커 딕셔너리 정의
aruco_dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
parameters = cv2.aruco.DetectorParameters_create()

# 이미지를 로드
image_path = 'path_to_your_image.jpg'  # 이미지 파일 경로를 입력하세요
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# ArUco 마커 탐지
corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=parameters)

# 마커가 탐지된 경우 이미지에 마커를 그리기
if ids is not None:
    image_with_markers = cv2.aruco.drawDetectedMarkers(image.copy(), corners, ids)
else:
    image_with_markers = image.copy()

# matplotlib를 사용하여 이미지 표시
plt.figure(figsize=(10, 10))
plt.imshow(cv2.cvtColor(image_with_markers, cv2.COLOR_BGR2RGB))
plt.title('Detected ArUco Markers')
plt.axis('off')
plt.show()

근데 이런 문제가 발생했다.

result>

Code_UzBaL5mpNU

어허….

brave_GPS8huCwDG

지금 내 기분이 딱 이렇다…

그래서 구글링을 해보았을때는, 라이브러리 버전을 낮춰봐라. 파이썬 sdk 버전을 낮춰봐라.

별에별 소리들이 있었는데, 결론은 실패…

그래서 내가 싫어하는 공식doc를 보기로 했다.

다행히 아루코마커에 대한 예제들이 잘 있었다(링크)

한가지 특이점이라면, 이 문서에서도 Aruco 마커 딕셔너리를 정의하는 부분이 있었는데,

쓰는 함수가 다르더라,,(이때 한번더 빡침;;;)

잘은 모르겠는데, 아마 opencv 개발하는 아재들이 Dictionary_get()을 없애버린 것 같다.

(좀더 찾아보니, DetectorParameters_create()도 없더라ㅋㅋㅋㅋ)

그래서 아래와 같이 코드를 수정했다.

import cv2
import matplotlib.pyplot as plt

# ArUco 마커 딕셔너리 정의
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
parameters = cv2.aruco.DetectorParameters()

# 이미지를 로드
image_path = './assets/images/report5/m1.jpg'  # 이미지 파일 경로를 입력하세요
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# ArUco 마커 탐지
corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=parameters)

# 마커가 탐지된 경우 이미지에 마커를 그리기
if ids is not None:
    image_with_markers = cv2.aruco.drawDetectedMarkers(image.copy(), corners, ids)
else:
    image_with_markers = image.copy()

# matplotlib를 사용하여 이미지 표시
plt.figure(figsize=(10, 10))
plt.imshow(cv2.cvtColor(image_with_markers, cv2.COLOR_BGR2RGB))
plt.title('Detected ArUco Markers')
plt.axis('off')
plt.show()

결과는 깔쌈하게 나왔다.

result>

POWERPNT_EEiCBz3Juw

코드에 대해 살짝 설명을 덧붙이자면,

detectMarkers 함수를 통해 이미지에서 아루코 마커를 탐지하고,

drawDetectMarkers 함수를 통해 탐지된 마커를 이미지에 그리는 것이다.

그리고 이를 maplotlib.pyplot 패키지 파일을 가져와 시각화시켜준 것이다.

이번에는 내가 찍은 총11개의 이미지 모두를 이렇게 탐지하고 ID값을 표시해 보았다.

import numpy as np
import cv2 as cv
import glob
import matplotlib.pyplot as plt

# ArUco 마커 딕셔너리 정의
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
parameters = cv2.aruco.DetectorParameters()

# 매개변수 설정
frameSize = (320, 240)

# 이미지 파일 읽기
images = glob.glob('./../../assets/images/report5/*.jpg')

# 최대 11장의 이미지를 출력하도록 설정
max_images = 11
images = images[:max_images]

# Matplotlib으로 이미지 출력 (6행 2열)
fig, axes = plt.subplots(6, 2, figsize=(10, 20))

for idx, image in enumerate(images):
    img = cv.imread(image)
    _img = cv.resize(img, dsize=frameSize, interpolation=cv.INTER_AREA)
    gray = cv.cvtColor(_img, cv.COLOR_BGR2GRAY)
    
    # ArUco 마커 탐지
    corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=parameters)
    # 마커가 탐지된 경우 이미지에 마커를 그리기
    if ids is not None:
        image_with_markers = cv2.aruco.drawDetectedMarkers(_img.copy(), corners, ids)
    else:
        image_with_markers = _img.copy()
    
    ax = axes[idx // 2, idx % 2]  # 6행 2열에 맞추어 인덱스 설정
    ax.imshow(cv.cvtColor(image_with_markers, cv.COLOR_BGR2RGB))
    ax.set_title(f'Image {idx + 1}')
    ax.axis('off')

# 남은 서브플롯 숨기기
for idx in range(len(images), 12):
    ax = axes[idx // 2, idx % 2]
    ax.axis('off')

plt.show()

result>

brave_4OtFlnIxhb

brave_8OHHDPvdYc

음.. 뭔가 아쉽다. 좀다 사진을 크게 하고, 중심점에 빨간색 원이 생기게 하고, 초록색테두리도 좀더 가시화되게 하자.

import numpy as np
import cv2 as cv
import glob
import matplotlib.pyplot as plt

# ArUco 마커 딕셔너리 정의
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
parameters = cv2.aruco.DetectorParameters()

# 매개변수 설정
frameSize = (960, 640)

# 이미지 파일 읽기
images = glob.glob('./../../assets/images/report5/*.jpg')

# 최대 11장의 이미지를 출력하도록 설정
max_images = 11
images = images[:max_images]

# Matplotlib으로 이미지 출력 (6행 2열)
fig, axes = plt.subplots(6, 2, figsize=(30, 60))

for idx, image in enumerate(images):
    img = cv.imread(image)
    _img = cv.resize(img, dsize=frameSize, interpolation=cv.INTER_AREA)
    gray = cv.cvtColor(_img, cv.COLOR_BGR2GRAY)
    
    # ArUco 마커 탐지
    corners, ids, rejectedImgPoints = cv2.aruco.detectMarkers(gray, aruco_dict, parameters=parameters)

     # 마커가 탐지된 경우 이미지에 마커를 그리기
    if ids is not None:
        image_with_markers = cv2.aruco.drawDetectedMarkers(_img.copy(), corners, ids)
        # 각 마커의 중앙에 빨간색 원 그리기
        for corner in corners:
            center = np.mean(corner[0], axis=0).astype(int)
            cv.circle(image_with_markers, tuple(center), 6, (0, 0, 255), -1)
    else:
        image_with_markers = _img.copy()
    
    ax = axes[idx // 2, idx % 2]  # 6행 2열에 맞추어 인덱스 설정
    ax.imshow(cv.cvtColor(image_with_markers, cv.COLOR_BGR2RGB))
    ax.set_title(f'Image {idx + 1}')
    ax.axis('off')

# 남은 서브플롯 숨기기
for idx in range(len(images), 12):
    ax = axes[idx // 2, idx % 2]
    ax.axis('off')

plt.show()

result>

brave_2JJqjGkTAh

brave_Ynd6Fr56FX

brave_YMcGhaKVoL

brave_9SXFet7OXC

brave_yGe0KJMkUh

brave_TLWsqkD5Nt

2. 두 카메라 사이의 카메라 모션 추정 (2D-2D)

  • 5-point algorithm을 이용한 Essential matrix 구하기

3. 월드좌표계에 대한 카메라의 위치 추정 (3D-2D, PnP)

4. Structure from motion (Visual Odometry)

댓글남기기