Mengukur jarak ke objek menggunakan RealSense D435

Tugas mendeteksi objek dalam gambar saat ini adalah salah satu yang terdepan dalam bidang penglihatan mesin. Esensinya tidak hanya untuk mengklasifikasikan objek dalam gambar, tetapi juga untuk menunjukkan lokasi tepatnya.

Hasil deteksi objek dapat dilengkapi dengan informasi tentang seberapa jauh objek ini berada. Masalah pengukuran jarak dapat diselesaikan menggunakan Intel RealSense D435 Depth Camera , yang mengukur kedalaman di setiap titik.

Pada artikel ini, kita akan memecahkan masalah mengukur jarak ke suatu objek secara real time menggunakan perpustakaan OpenCV dan teknologi RealSense.

gambar

Persyaratan


Kamera RealSense

Untuk mengukur jarak, kita membutuhkan Kamera RealSense D435 Kedalaman . Untuk contoh ini, tidak perlu menginstal RealSense SDK .

Pustaka Pyrealsense2

Semua kode, untuk kemudahan demonstrasi, kita akan menulis dalam Python 3.7 , jadi kita membutuhkan paket pyrealsense2 .

pip install pyrealsense2

Pustaka OpenCV

Juga, kita membutuhkan pustaka OpenCV (versi apa pun mulai dari 3,4 cocok). Manual instalasi perpustakaan dapat dilihat di situs web resmi OpenCV .

Bersama dengan OpenCV , satu lagi perpustakaan yang diperlukan akan diinstal - numpy .

Deteksi Objek


Langkah pertama adalah memilih objek dalam video. Untuk mendeteksi objek secara real time, yang disebut model satu tahap (misalnya, Retina Net, SSD, YOLO ), yang menang dalam kecepatan operasi, sempurna .

Untuk kesederhanaan percobaan, kami akan mengambil model SSDLite Mobilenet v2 yang terlatih . Sebaliknya, model lain dapat digunakan yang mengembalikan koordinat objek dalam satu bentuk atau lainnya.
Anda dapat mengunduh arsip dengan file model di repositori TensorFlow resmi .

Arsip berisi grafik perhitungan beku dalam format biner .pb, serta berbagai konfigurasi. Tetapi untuk menggunakan model di OpenCV, Anda juga harus memiliki grafik perhitungan dalam format teks .pbtxt . Itu tidak ada dalam arsip, jadi itu harus dihasilkan secara manual.

Salin dua skrip dari repositori OpenCV :

  1. github.com/opencv/opencv/blob/master/samples/dnn/tf_text_graph_ssd.py
  2. github.com/opencv/opencv/blob/master/samples/dnn/tf_text_graph_common.py

Kemudian, jalankan perintah berikut, tentukan jalur yang diperlukan:

python tf_text_graph_ssd.py --input /path/to/model.pb --config /path/to/example.config --output /path/to/graph.pbtxt

Outputnya adalah file graph.pbtxt .

Kami menempatkan file model yang ada di folder proyek. Dalam kasus saya, ini adalah model / folder .

Pengembangan


Sekarang semuanya siap untuk dikembangkan. Mari kita mulai menulis kode.

Kami mengimpor pustaka yang diperlukan dan membuat rintisan pada metode draw_predictions () , yang akan kita perlukan nanti:

import pyrealsense2 as rs
import numpy as np
import cv2 as cv

def draw_predictions(pred_img, color_img, depth_image):
    pass

Buat objek utama:

pipeline = rs.pipeline() # <-  pipeline      
config = rs.config() # <-      
colorizer = rs.colorizer() # <-      

spatial = rs.spatial_filter()
spatial.set_option(rs.option.holes_fill, 3)

Kami menginisialisasi model ssd . Di sini, file .pbtxt yang kami buat di atas bermanfaat bagi kami :

#  
model = cv.dnn.readNetFromTensorflow(
    "models/ssdlite_mobilenet_v2_coco_2018_05_09/frozen_inference_graph.pb", 
    "models/ssdlite_mobilenet_v2_coco_2018_05_09/graph.pbtxt"
)

Kami memulai aliran kamera:

#  2 : RGB  depth
config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
profile = pipeline.start(config)

perhatikan bahwa kami menangkap aliran warna dalam format BGR , karena ini adalah format yang menggunakan OpenCV secara default.

Kami memulai siklus di mana kami akan menangkap dan memproses frame secara berurutan:

cv.namedWindow("RealSense object detection", cv.WINDOW_AUTOSIZE)
try:
    while True:
        #     ""  ""
        frames = pipeline.wait_for_frames()
        depth_frame = frames.get_depth_frame()
        color_frame = frames.get_color_frame()
        if not depth_frame or not color_frame:
            continue

Untuk pemrosesan lebih lanjut dari frame, kami mewakili mereka dalam bentuk array numpy :

        #    numpy-
        depth_image = np.asanyarray(depth_frame.get_data())
        color_image = np.asanyarray(color_frame.get_data())

Kami menggunakan model ssd untuk mendeteksi:

        #  
        model.setInput(cv.dnn.blobFromImage(color_image, size=(300, 300), swapRB=True, crop=False))
        pred = model.forward()
        draw_predictions(pred, color_image, depth_image)

Kami menggambar hasilnya di jendela:

	#     
        colorized_depth = cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET)
        #    
        images = np.hstack((color_image, colorized_depth))
        cv.imshow("RealSense object detection", images)

Kami menulis kondisi untuk keluar dari loop:

	#    'ESC'  'q'
        key = cv.waitKey(1) & 0xFF
        if (key == 27) or (key == ord('q')):
            cv.destroyWindow("RealSense object detection")
            break        

Tutup arus:

finally:
    pipeline.stop()

Dan yang terakhir. Kami mengisi metode rendering draw_predictions () yang kami buat di awal. Di dalamnya, kita akan mempertimbangkan jarak ke objek. Saya memutuskan untuk menghitung jarak sebagai berikut: ambil rata-rata semua titik jarak dalam bingkai objek yang ditemukan:

def draw_predictions(pred_img, color_img, depth_image):
    for detection in pred_img[0,0,:,:]:
        score = float(detection[2])
        #            50%
        if score > 0.5:
            left = detection[3] * color_img.shape[1]
            top = detection[4] * color_img.shape[0]
            right = detection[5] * color_img.shape[1]
            bottom = detection[6] * color_img.shape[0]
            cv.rectangle(color_img, (int(left), int(top)), (int(right), int(bottom)), (210, 230, 23), 2)
            
            #    
            depth = depth_image[int(left):int(right), int(top):int(bottom)].astype(float)
            depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
            depth = depth * depth_scale
            dist,_,_,_ = cv.mean(depth)
            dist = round(dist, 1)
            cv.putText(color_img, "dist: "+str(dist)+"m", (int(left), int(top)-5), cv.FONT_HERSHEY_PLAIN, 1, (0, 255, 0), 1)

gambar

Kode lengkap
import pyrealsense2 as rs
import numpy as np
import cv2 as cv

def draw_predictions(pred_img, color_img, depth_image): # <-        
    for detection in pred_img[0,0,:,:]:
        score = float(detection[2])
        #            50%
        if score > 0.5:
            left = detection[3] * color_img.shape[1]
            top = detection[4] * color_img.shape[0]
            right = detection[5] * color_img.shape[1]
            bottom = detection[6] * color_img.shape[0]
            cv.rectangle(color_img, (int(left), int(top)), (int(right), int(bottom)), (210, 230, 23), 2)
            
            #    
            depth = depth_image[int(left):int(right), int(top):int(bottom)].astype(float)
            depth_scale = profile.get_device().first_depth_sensor().get_depth_scale()
            depth = depth * depth_scale
            dist,_,_,_ = cv.mean(depth)
            dist = round(dist, 1)
            cv.putText(color_img, "dist: "+str(dist)+"m", (int(left), int(top)-5), cv.FONT_HERSHEY_PLAIN, 1, (0, 255, 0), 1)


pipeline = rs.pipeline() # <-  pipeline      
config = rs.config() # <-      
colorizer = rs.colorizer() # <-      

#  
model = cv.dnn.readNetFromTensorflow(
    "models/ssdlite_mobilenet_v2_coco_2018_05_09/frozen_inference_graph.pb", 
    "models/ssdlite_mobilenet_v2_coco_2018_05_09/graph.pbtxt"
)

#  2 : RGB  depth
config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
profile = pipeline.start(config)

cv.namedWindow("RealSense object detection", cv.WINDOW_AUTOSIZE)
try:
    while True:
        #     ""  ""
        frames = pipeline.wait_for_frames()
        depth_frame = frames.get_depth_frame()
        color_frame = frames.get_color_frame()
        if not depth_frame or not color_frame:
            continue

        #    numpy-
        depth_image = np.asanyarray(depth_frame.get_data())
        color_image = np.asanyarray(color_frame.get_data())
        
        #  
        model.setInput(cv.dnn.blobFromImage(color_image, size=(300, 300), swapRB=True, crop=False))
        pred = model.forward()
        draw_predictions(pred, color_image, depth_image)

        #     
        colorized_depth = cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET)
        #    
        images = np.hstack((color_image, colorized_depth))
        cv.imshow("RealSense object detection", images)
        
        #    'ESC'  'q'
        key = cv.waitKey(1) & 0xFF
        if (key == 27) or (key == ord('q')):
            cv.destroyWindow("RealSense object detection")
            break

finally:
    pipeline.stop()


Kesimpulan


Jadi, kami memiliki skrip sederhana untuk memperkirakan jarak ke objek yang dipilih. Algoritme mungkin membuat kesalahan sekitar 50 cm, tetapi secara keseluruhan bekerja dengan baik dalam jarak empat meter. Untuk meningkatkan akurasi pengukuran, Anda dapat menerapkan filter tambahan yang tertanam di pyrealsense2 ke peta kedalaman untuk meningkatkan kualitas gambar, atau memodifikasi algoritma penghitungan kedalaman itu sendiri (misalnya, menghitung rata-rata tertimbang atau mengukur jarak di satu area pusat). Seperti yang Anda lihat, tugasnya tidak sulit, tetapi menarik.

Source: https://habr.com/ru/post/undefined/


All Articles