К содержимому
  1. Главная
  2. Документация
  3. Камеры для NVIDIA Jetson
  4. Arducam ToF Camera SDK для Jetson

Arducam ToF Camera SDK для Jetson

Документация Arducam · перевод arducam-russia.ru

Arducam ToF Camera SDK для Jetson

Что такое SDK

Комплект средств разработки (SDK) — набор инструментов для разработки ПО в одном устанавливаемом пакете. Он упрощает создание приложений: в него входят компилятор, отладчик, а иногда и программный фреймворк. Обычно SDK привязан к конкретному сочетанию аппаратной платформы и операционной системы.

Программный стек ToF-камеры Arducam

Arducam ToF SDK — динамическая библиотека на C++ для ToF-камер (время пролёта). В ней три класса: Camera, Frame и Sensor. Camera управляет захватом изображения с камеры и вычислениями, Frame — памятью, в которой хранятся данные камеры, а Sensor — конкретная реализация обращения к камере. Sensor входит в класс Camera как объект-член, и пользователю обычно не нужно работать с ним напрямую.

Структура программного стека Arducam ToF SDK

Работа с Arducam ToF Camera SDK

Установка SDK

SDK устанавливается вместе с драйвером камеры и нужными зависимостями, когда вы выполните шаги ниже. Это тот же набор команд, что и в шагах 1, 2 и 3 основной инструкции.

Выполните по очереди команды каждого шага.

Шаг 1. Скачайте репозиторий

git clone https://github.com/ArduCAM/Arducam_tof_camera.git

Шаг 2. Перейдите в папку Arducam_tof_camera

cd Arducam_tof_camera

Шаг 3. Установка (драйвер, зависимости, SDK, OpenCV)

./Install_dependencies_jetson.sh

Когда появится запрос на перезагрузку, введите y.

Запуск примеров

Примеры на C

Порядок работы с SDK

  1. Создайте экземпляр камеры.
  2. Запустите камеру.
  3. Запросите кадр.
  4. Получите данные кадра.
  5. Освободите память кадра.
  6. Остановите камеру.

Пример

#include "ArduCamDepthCamera.h"
#include <stdlib.h>
#include <stdio.h>

void getPreview(uint8_t *preview_ptr, float *phase_image_ptr, float *amplitude_image_ptr)
{
    unsigned long int len = 240 * 180;
    for (unsigned long int i = 0; i < len; i++)
    {
        uint8_t amplitude = *(amplitude_image_ptr + i) > 30 ? 254 : 0;
        float phase = ((1 - (*(phase_image_ptr + i) / 2)) * 255);
        uint8_t depth = phase > 255 ? 255 : phase;
        *(preview_ptr + i) = depth & amplitude;
    }
}

int main()
{
    ArducamDepthCamera tof = createArducamDepthCamera();
    FrameBuffer frame;
    if (init(tof,CSI,DEPTH_TYPE,0))
        exit(-1);
    if (start(tof))
        exit(-1);
    uint8_t *preview_ptr = malloc(180*240*sizeof(uint8_t)) ;
    float* depth_ptr = 0;
    int16_t *raw_ptr = 0;
    float *amplitude_ptr = 0;
    FrameFormat format;
    if ((frame = requestFrame(tof,200)) != 0x00){
        format = getFormat(frame,DEPTH_FRAME);
    }
    for (;;)
    {
        if ((frame = requestFrame(tof,200)) != 0x00)
        {
            depth_ptr = (float*)getDepthData(frame);
            printf("Center distance:%.2f.\n",depth_ptr[21600]);
            amplitude_ptr = (float*)getAmplitudeData(frame);
            getPreview(preview_ptr,depth_ptr,amplitude_ptr);
            releaseFrame(tof,frame);  
        }
    }

    if (stop(tof))
        exit(-1);
    return 0;
}

Содержимое CMakeList.txt

 cmake_minimum_required(VERSION 3.4)
SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")  
project(example_tof)
include_directories(BEFORE /usr/include/c  /usr/include/cpp)
add_executable( example_tof your_filename.c )
target_link_libraries( example_tof ArducamDepthCamera_c pthread)

Сборка и запуск

mkdir build && cd build
cmake ..
make

Результат

Примеры на C++

Порядок работы с SDK

  1. Создайте экземпляр камеры.
  2. Инициализируйте экземпляр камеры.
  3. Запустите камеру.
  4. Запросите кадр.
  5. Получите данные кадра.
  6. Освободите память кадра.
  7. Остановите камеру.

Пример

#include "ArduCamTOFCamera.hpp"
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <chrono>
#include <iostream>

// MAX_DISTANCE value modifiable  is 2 or 4
#define MAX_DISTANCE 4

void display_fps(void)
{
    static int count = 0;
    ++count;
    static std::chrono::high_resolution_clock::time_point time_beg = std::chrono::high_resolution_clock::now();
    std::chrono::high_resolution_clock::time_point time_end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double, std::ratio<1, 1>> duration_s = time_end - time_beg;
    if (duration_s.count() >= 1)
    {
        std::cout << "fps:" << count << std::endl;
        count = 0;
        time_beg = time_end;
    }
}

void getPreview(uint8_t *preview_ptr, float *phase_image_ptr, float *amplitude_image_ptr)
{
    auto len = 240 * 180;
    for (auto i = 0; i < len; i++)
    {
        uint8_t mask = *(amplitude_image_ptr + i) > 30 ? 254 : 0;
        float depth = ((1 - (*(phase_image_ptr + i) / MAX_DISTANCE)) * 255);
        uint8_t pixel = depth > 255 ? 255 : depth;
        *(preview_ptr + i) = pixel & mask;
    }
}
cv::Rect seletRect(0, 0, 0, 0);
cv::Rect followRect(0, 0, 0, 0);
void onMouse(int event, int x, int y, int flags, void *param)
{
    if (x < 4 || x > 251 || y < 4 || y > 251)
        return;
    switch (event)
    {
    case cv::EVENT_LBUTTONDOWN:

        break;

    case cv::EVENT_LBUTTONUP:
        seletRect.x = x - 4 ? x - 4 : 0;
        seletRect.y = y - 4 ? y - 4 : 0;
        seletRect.width = 8;
        seletRect.height = 8;
        break;
    default:
        followRect.x = x - 4 ? x - 4 : 0;
        followRect.y = y - 4 ? y - 4 : 0;
        followRect.width = 8;
        followRect.height = 8;
        break;
    }
}

int main()
{
    ArduCam::ArduCamTOFCamera tof;
    ArduCam::FrameBuffer *frame;
    if (tof.init(ArduCam::CSI,ArduCam::DEPTH_TYPE)){
        std::cerr<<"initialization failed"<<std::endl;
        exit(-1);
    }

    if (tof.start()){
        std::cerr<<"Failed to start camera"<<std::endl;
        exit(-1);
    }
    //  Modify the range also to modify the MAX_DISTANCE
    tof.setControl(ArduCam::RANGE,MAX_DISTANCE);
    ArduCam::CameraInfo tofFormat = tof.getCameraInfo();

    float *depth_ptr;
    float *amplitude_ptr;
    uint8_t *preview_ptr = new uint8_t[tofFormat.height * tofFormat.width];
    cv::namedWindow("preview", cv::WINDOW_AUTOSIZE);
    cv::setMouseCallback("preview", onMouse);

    for (;;)
    {
        frame = tof.requestFrame(200);
        if (frame != nullptr)
        {
            depth_ptr = (float *)frame->getData(ArduCam::DEPTH_FRAME);
            amplitude_ptr = (float *)frame->getData(ArduCam::AMPLITUDE_FRAME);
            getPreview(preview_ptr, depth_ptr, amplitude_ptr);

            cv::Mat result_frame(tofFormat.height, tofFormat.width, CV_8U, preview_ptr);
            cv::Mat depth_frame(tofFormat.height, tofFormat.width, CV_32F, depth_ptr);
            cv::Mat amplitude_frame(tofFormat.height, tofFormat.width, CV_32F, amplitude_ptr);

            cv::applyColorMap(result_frame, result_frame, cv::COLORMAP_JET);
            amplitude_frame.convertTo(amplitude_frame, CV_8U,255.0/1024,0);
            cv::imshow("amplitude", amplitude_frame);
            cv::rectangle(result_frame, seletRect, cv::Scalar(0, 0, 0), 2);
            cv::rectangle(result_frame, followRect, cv::Scalar(255, 255, 255), 1);

            std::cout << "select Rect distance: " << cv::mean(depth_frame(seletRect)).val[0] << std::endl;

            cv::imshow("preview", result_frame);

            if (cv::waitKey(1) == 27)
                break;
            display_fps();
        }
        tof.releaseFrame(frame);
    }

    if (tof.stop())
        exit(-1);
    return 0;
}

Содержимое CMakeList.txt

cmake_minimum_required(VERSION 3.4)
SET(CMAKE_BUILD_TYPE "Debug")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")  
project(example_tof)
include_directories(BEFORE /usr/include/c  /usr/include/cpp)
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable(example_tof your_filename.cpp )
target_link_libraries( example_tof ArducamDepthCamera ${OpenCV_LIBS} )

Сборка и запуск

mkdir build && cd build
cmake ..
make 

Результат

Пример на Python

Порядок работы с SDK

  1. Создайте экземпляр камеры.
  2. Инициализируйте экземпляр камеры.
  3. Запустите камеру.
  4. Запросите кадр.
  5. Получите данные кадра.
  6. Освободите память кадра.
  7. Остановите камеру.

Пример

import sys
import cv2
import numpy as np
import ArduCamDepthCamera as ac

dir(ac)
def process_frame(depth_buf: np.ndarray, amplitude_buf: np.ndarray) -> np.ndarray:

    depth_buf = np.nan_to_num(depth_buf)

    amplitude_buf[amplitude_buf<=30] = 0
    amplitude_buf[amplitude_buf>30] = 255

    depth_buf = (1 - (depth_buf/2)) * 255
    depth_buf = np.clip(depth_buf, 0, 255)
    result_frame = depth_buf.astype(np.uint8)  & amplitude_buf.astype(np.uint8)
    return result_frame 

selectRect_x1 = 0
selectRect_y1 = 0
selectRect_x2 = 0
selectRect_y2 = 0

followRect_x1 = 0
followRect_y1 = 0
followRect_x2 = 0
followRect_y2 = 0

def on_mouse(event, x, y, flags, param):
    global followRect_x1,followRect_y1,followRect_x2,followRect_y2
    global selectRect_x1,selectRect_y1,selectRect_x2,selectRect_y2
    # if (x < 4 or x > 251 or y < 4 or y > 251):
    #     return
    if event == cv2.EVENT_LBUTTONDOWN:
        pass

    elif event == cv2.EVENT_LBUTTONUP:
        selectRect_x1 = x - 4 if x - 4 > 0 else 0
        selectRect_y1 = y - 4 if y - 4 > 0 else 0
        selectRect_x2 = x + 4 if x + 4 < 240 else 240
        selectRect_y2=  y + 4 if y + 4 < 180 else 180
    else:
        followRect_x1 = x - 4 if x - 4 > 0 else 0
        followRect_y1 = y - 4 if y - 4 > 0 else 0
        followRect_x2 = x + 4 if x + 4 < 240 else 240
        followRect_y2 = y + 4 if y + 4 < 180 else 180


if __name__ == "__main__":
    cam = ac.ArducamCamera()
    if cam.init(ac.TOFConnect.CSI,ac.TOFOutput.DEPTH,0) != 0 :
        print("initialization failed")
    if cam.start() != 0 :
        print("Failed to start camera")
    cv2.namedWindow("preview", cv2.WINDOW_AUTOSIZE)
    cv2.setMouseCallback("preview",on_mouse)
    while True:
        frame = cam.requestFrame(200)
        if frame != None:
            depth_buf = frame.getDepthData()
            amplitude_buf = frame.getAmplitudeData()
            amplitude_buf[amplitude_buf<0] = 0
            amplitude_buf[amplitude_buf>255] = 255
            cam.releaseFrame(frame)

            cv2.imshow("preview_amplitude", amplitude_buf.astype(np.uint8))

            result_image = process_frame(depth_buf,amplitude_buf)
            result_image = cv2.applyColorMap(result_image, cv2.COLORMAP_JET)
            cv2.rectangle(result_image,(selectRect_x1,selectRect_y1),(selectRect_x2,selectRect_y2),(128,128,128), 1)
            cv2.rectangle(result_image,(followRect_x1,followRect_y1),(followRect_x2,followRect_y2),(255,255,255), 1)
            print("select Rect distance:",np.mean(depth_buf[selectRect_x1:selectRect_x2,selectRect_y1:selectRect_y2]))
            cv2.imshow("preview",result_image)

            key = cv2.waitKey(1)
            if key == ord("q"):
                exit_ = True
                cam.stop()
                sys.exit(0)

Запуск

python3 your_filename.py

Результат (будет добавлен позже)

Справочник по API для C

Справочник по API для C — по ссылке.

Справочник по API для C++

Справочник по API для C++ — по ссылке.

Запросить цену

Укажите количество — пришлём коммерческое предложение.