OAK-D 및 DepthAI 소개

Depth(OAK-D)가 포함된 OpenCV AI Kit 프로그래밍에 대한 첫 번째 게시물입니다. 그리고 OpenCV AI Kit:  Depth Lite(OAK-D-Lite)도 고려 되어있습니다. OAK-D-Lite는 OAK-D의 동생 정도로 생각하시면 됩니다.

OAK-D와 OAK-D Lite는 모두 Spatial AI 카메라입니다.

Spatial AI란?

Spatial AI는 비전(시각) AI 시스템이 아래 두 가지를 기반으로 결정을 내리는 능력입니다.

  1. 시각적 인식: AI가 주변을 시각적으로 “보고” “해석”하는 능력입니다. 예를 들어, 물체 감지를 위해 neural network을 실행하는 프로세서에 연결된 카메라가 카메라가 보고 있는 장면에서 고양이, 사람 또는 자동차를 감지할 수 있는 시스템입니다.
  2. Depth 인식 : 이것은 물체가 얼마나 멀리 있는 지를 이해하는 AI의 능력입니다. 컴퓨터 비전 전문 용어에서 “깊이”는 단순히 “얼마나 멀리”를 의미합니다.

Spatial AI의 아이디어는 인간의 시각에서 영감을 받았습니다. 사람은 눈을 사용하여 주변 환경을 해석합니다. 또한 두 눈(즉, 스테레오 비전)을 사용하여 사물이 우리에게서 얼마나 멀리 있는지 인식합니다.

SPATIAL AI 카메라 OAK-D와 OAK-D-Lite

OAK-D와 OAK-D-Lite는 다음과 같은 중요한 구성 요소로 구성됩니다.

  1. 4K RGB 카메라 : 중앙에 위치한 RGB 카메라는 초고해상도 4k 영상을 촬영할 수 있습니다. 일반적으로 이 카메라는 시각적 인식에 사용됩니다.
  2. 스테레오 페어: 깊이(Depth) 인식에 사용되는 두 대의 카메라(“스테레오”라는 단어는 두 개를 의미함)의 시스템입니다.
  3. Intel® Myriad™ X VPU(Visual Processing Unit): 이것은 OAK의 “두뇌”입니다. 시각적 인식을 위해 최신 Neural Networks을 실행하는 동시에 실시간으로 스테레오 페어의 이미지에서 깊이(Depth) 맵을 생성할 수 있는 강력한 프로세서입니다.

OAK-D 및 OAK-D-Lite의 응용

OAK-D는 다양한 영역에서 응용 프로그램을 개발하는 데 사용되고 있습니다. OpenCV AI Competition 2021은 이러한 많은 애플리케이션을 선보입니다.

교육, 어린이 돌봄, 장애인 보조 기술, AR/VR, 드론을 사용한 창고 검사, 로봇 공학, 농업, 스포츠 분석, 소매 및 광고 분야의 응용 프로그램을 볼 수 있습니다.

OAK-D 및 OAK-D-Lite를 사용하여 구축된 더 많은 놀라운 애플리케이션을 보려면 리얼리에듀테크  블로그 페이지를 확인하세요..

이제 이 멋진 장치에 프로그래밍을 해보도록 하겠습니다. 고~~ 고~~

목차

  1. OAK-D Vs OAK-D Lite
  2. Depth AI 설치
  3. 왼쪽 모노 카메라에 액세스하는 Depth AI 파이프라인
  4. 스테레오 비전을 위한 완벽한 파이프라인
  5. 코드 다운로드
  6. 데모

OAK-D Vs OAK-D Lite

기능면에서 두 장치는 거의 동일합니다. OAK-D-Lite를 사용해도 OAK-D가 할 수 있는 거의 모든 작업을 수행할 수 있습니다. 그래서 초보자는 큰 차이를 느끼지 못할 것입니다. 그러나 아래 테이블과 같이 두 장치를 구분하는 몇 가지 사양이 있습니다. OAK-D Lite는 날렵하고 가볍고 저렴하며 전력을 덜 사용합니다. 반면에 OAK-D는 약간 더 높은 성능을 원하시는 고객이 선호 합니다.

OAK-D Vs OAK-D Lite 비교

특징/스펙OAK-DOAK-D-Lite
RGB 카메라12 Megapixel, 4k, up to 60 fps12 Megapixel, 4k, up to 60 fps
모노 카메라1280x800p, 120 fps, 글로벌 셔터640x480p, 120 fps, 글로벌 셔터
IMU(Inertial Measurement Unit)YesNo
USB-C, 파워 잭Yes, YesYes, No
VPUMyriad-X, 4 trillion ops/sMyriad-X, 4 trillion ops/s

설치

OAK-D 또는 OAK-D Lite를 사용하는 가장 좋은 점은 외부 하드웨어 또는 소프트웨어 종속성이 없다는 것입니다. 하드웨어, 펌웨어 및 소프트웨어가 통합되어 있어 쉬우면서도 빠르게 경험 할 수 있게 모든 것을 제공합니다. Depth-AI는 OAK-D를 프로그래밍하는 API(응용 프로그래밍 인터페이스)입니다. 크로스 플랫폼이므로 어떤 OS를 사용하는지 걱정할 필요가 없습니다. 이제 터미널이나 Powershell을 실행하여 API를 설치해 보겠습니다. 인터넷 연결 상태가 좋은 경우 약 30초가 소요됩니다.

#git clone https://github.com/luxonis/depthai.git 
#cd depthai
#python3 install_requirements.py
#python3 depthai_demo.py

여기에서 Luxonis의 DepthAI 문서를 확인할 수도 있습니다.

Depth-AI 파이프라인

파이프라인은 노드의 모음이고 노드는 입력과 출력이 있는 단위입니다. Depth-AI 파이프라인을 이해하기 위해 다음 그림을 살펴보겠습니다. 그림에서 주어진 명령이 실행될 때 카메라 내부에서 일어나는 일을 보여주고 있습니다. 왼쪽 모노 카메라에서 프레임을 캡처하는 매우 간단한 파이프라인입니다.

1. 파이프라인 생성

여기에서 파이프라인 객체를 인스턴스화합니다.

import depthai as dai 
pipeline = dai.Pipeline()

2. 카메라 노드 생성

아래 명령에 따라 모노 카메라 노드를 만듭니다. 시각적으로 아무것도 하지 않습니다. 모노 카메라만 인식합니다.

mono = pipeline.createMonoCamera()

3.  카메라 선택

카메라에 액세스하려면 이 경우 왼쪽 카메라를 선택해야 합니다. 이것은 setBoardSocket 메소드에 의해 수행됩니다. 내부적으로는 입력 노드인 X-LinkIn도 생성합니다. X-Link는 카메라가 호스트(컴퓨터)와 통신하는 데 사용하는 메커니즘입니다.

mono.setBoardSocket(dai.CameraBoardSocket.LEFT)

4.  XLinkOut 노드 생성 및 프레임 획득

출력을 얻으려면 X-Link 출력 노드를 만들어야 합니다. 카메라는 몇 가지 다른 출력을 가질 수 있습니다. 예를 들어 오른쪽 모노 카메라나 RGB 카메라의 다른 스트림 또는 현재로서는 걱정할 필요가 없는 다른 출력이 있습니다. 따라서 다른 사람과 충돌하지 않도록 “Left”으로 명명되었습니다. 마지막으로 X-LinkOut 노드에 입력으로 넣어 모노 카메라의 출력을 연결합니다.

xout = pipeline.createXLinkOut() 
xout.setStreamName("left")
mono.out.link(xout.input)

이전 코드까지는 장치 준비 까지 완료한 상태입니다. 따라서 실제로는 아무 것도 처리하지는 않았습니다. 모든 명령은 호스트 컴퓨터 내부에서 실행되었습니다.  따라서 전처리 단계라고 생각하시면 됩니다. 다음 코드 사용하여 파이프라인을 호스트 컴퓨터에서 카메라로 전송합니다.

이제 X-LinkOut 노드에서 출력 프레임을 얻을 수 있습니다. X-LinkOut 노드의 출력은 단일 프레임이 아닙니다. 실제로 여러 프레임을 저장할 수 있는 큐(Queue)를 만듭니다. 여러 프레임이 필요한 특정 응용 프로그램에 유용할 수 있습니다. 비디오 인코딩이 그러한 예입니다. 그러나 우리의 경우 여러 프레임이 필요하지 않습니다. 따라서 지금은 기본 단일 프레임으로 유지하겠습니다. 아래 코드를 보시다시피 큐(Queue)은 스트림을 지정하는 getOutputQueue 메서드를 사용하여 가져옵니다.

다음으로 프레임을 추출하기 위해 큐(Queue)에 쿼리합니다. 이 시점에서 프레임은 장치에서 호스트 컴퓨터로 전송됩니다. 프레임은 여러 유형을 가질 수 있는 depthai.ImgFrame 클래스입니다. OpenCV에서 쉽게 사용하게 만들기 위해 이미지를 numpy 배열로 반환하는 getCvFrame 함수를 사용합니다. 이것으로 기본 파이프라인을 마칩니다.

with dai.Device(pipeline) as device:

    queue = device.getOutputQueue(name="left")

    frame = queue.get()

    imOut = frame.getCvFrame()

이제 왼쪽 및 오른쪽 카메라 모두를 위한 완전한 파이프라인을 구축해 보겠습니다. 모노 카메라의 출력을 사용하여 별도 보기와 병합 보기를 표시합니다. 본격 적으로 시작하기 위해 다음 링크를 사용하여 전체 코드를 다운로드하세요.

이 튜토리얼을 쉽게 따라 하려면 아래 버튼을 클릭하여 코드를 다운로드하세요.

스테레오 비전을 위한 파이프라인

Depth-AI 라이브러리는 Python 및 C++ API 를 모두 지원하지만, C++ API는 아직 안정적인 릴리스가 아닙니다. 따라서 이 블로그 게시물에서는 파이썬 코드에 초점을 맞추고 있습니다.

라이브러리 가져오기
import cv2 
import depthai as dai
import numpy as np
프레임 추출 기능

큐(Queue)에서 프레임을 쿼리하고, 호스트로 전송하고, 프레임을 numpy 배열로 변환합니다.

def getFrame(queue): 
    # Get frame from queue
   frame = queue.get()

    # Convert frame to OpenCV format and return
   return frame.getCvFrame()
모노 카메라 선택 기능

여기에서 파이프라인에 대한 카메라 노드가 생성됩니다. 그런 다음 setResolution 메서드를 사용하여 카메라 해상도를 설정합니다. sensorResolution 클래스에는 선택할 수 있는 다음 속성이 있습니다.

  • THE_700_P          (1280x720p)
  • THE_800_P          (1280x800p)
  • THE_400_P            (640x400p)
  • THE_480_P            (640x480p)

우리의 경우 해상도를 640x400p로 설정합니다. 보드 소켓은 isLeft 부울을 사용하여 왼쪽 또는 오른쪽 모노 카메라로 설정됩니다.

def getMonoCamera(pipeline, isLeft):
  # Configure mono camera
  mono = pipeline.createMonoCamera()

  # Set Camera Resolution
    mono.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
  if isLeft:
      # Get left camera
      mono.setBoardSocket(dai.CameraBoardSocket.LEFT)
  else :
      # Get right camera
      mono.setBoardSocket(dai.CameraBoardSocket.RIGHT)
  return mono

메인 기능

파이프라인 및 카메라 설정

먼저 파이프라인을 만들고 왼쪽 및 오른쪽 모노 카메라를 설정합니다. 미리 정의된 함수 getMonoCamera는 내부적으로 X-LinkIn 노드를 생성하고 모노 카메라 출력을 반환합니다. 그런 다음 카메라의 출력이 X-LinkOut 노드에 연결됩니다.

if __name__ == '__main__':
    pipeline = dai.Pipeline()

    # Set up left and right cameras
    monoLeft = getMonoCamera(pipeline, isLeft = True)
    monoRight = getMonoCamera(pipeline, isLeft = False)

    # Set output Xlink for left camera
    xoutLeft = pipeline.createXLinkOut()
    xoutLeft.setStreamName("left")

    # Set output Xlink for right camera
    xoutRight = pipeline.createXLinkOut()
    xoutRight.setStreamName("right")
 
    # Attach cameras to output Xlink
    monoLeft.out.link(xoutLeft.input)
    monoRight.out.link(xoutRight.input)
파이프라인을 디바이스로 전송

설정이 준비되면 파이프라인을 디바이스(카메라)로 전송합니다. 왼쪽 및 오른쪽 카메라 출력에 대한 큐(Queue)은 각각의 이름으로 정의됩니다. 프레임 보유 용량은 maxSize 인수로 설정되며 이 경우에는 단일 프레임으로 설정합니다. 나중에 출력을 표시하는 데 사용할 명명된 윈도우(Stereo Pair)도 생성됩니다. sideBySide 변수는 카메라 보기(나란히 보기 또는 중첩 보기)를 전환하기 위한 부울 값입니다.

with dai.Device(pipeline) as device:
    # Get output queues. 
    leftQueue = device.getOutputQueue(name="left", maxSize=1)
    rightQueue = device.getOutputQueue(name="right", maxSize=1)

    # Set display window name
    cv2.namedWindow("Stereo Pair")
    # Variable used to toggle between side by side view and one 
    frame view. 
    sideBySide = True

메인 loop

지금까지 파이프라인을 만들고 카메라 출력을 X-LinkOut 노드에 연결하고큐(Queue)을 얻었습니다. 이제 미리 정의된 getFrame 함수를 사용하여 프레임을 쿼리하고 OpenCV 친화적인 numpy 배열 형식으로 변환할 시간입니다. 나란히 보기의 경우 프레임이 numpy hstack(수평 스택) 기능을 사용하여 수평으로 연결됩니다. 중첩 출력의 경우 강도(intensity)를 2배로 줄여 프레임을 추가하기만 하면 됩니다.

키보드 입력 q는 루프를 종료하고, t는 디스플레이를 토글합니다(나란히 보기 및 정면 보기).

while True:
    # Get left frame
    leftFrame = getFrame(leftQueue)
    # Get right frame 
    rightFrame = getFrame(rightQueue)

    if sideBySide:
        # Show side by side view
        imOut = np.hstack((leftFrame, rightFrame))
    else : 
        # Show overlapping frames
        imOut = np.uint8(leftFrame/2 + rightFrame/2)

    # Display output image
    cv2.imshow("Stereo Pair", imOut)
    
    # Check for keyboard input
    key = cv2.waitKey(1)
    if key == ord('q'):
        # Quit when q is pressed
        break
    elif key == ord('t'):
        # Toggle display when t is pressed
        sideBySide = not sideBySide

결과

그림: 나란히 보기

그림: 중첩 출력

결론

이것으로 Depth가 포함된 OpenCV AI Kit 소개를 마칩니다. 가볍게 읽고 OAK-D 설정에 대한 아이디어를 얻으셨기를 바랍니다. 다음 블로그 게시물에서는 OAK-D에서 Depth  맵을 가져오는 파이프라인을 다룰 것입니다.

Leave a Comment

Your email address will not be published.