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.
Persyaratan
Kamera RealSenseUntuk mengukur jarak, kita membutuhkan Kamera RealSense D435 Kedalaman . Untuk contoh ini, tidak perlu menginstal RealSense SDK .Pustaka Pyrealsense2Semua kode, untuk kemudahan demonstrasi, kita akan menulis dalam Python 3.7 , jadi kita membutuhkan paket pyrealsense2 .pip install pyrealsense2
Pustaka OpenCVJuga, 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 :- github.com/opencv/opencv/blob/master/samples/dnn/tf_text_graph_ssd.py
- 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()
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:
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 :
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:
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])
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)

Kode lengkapimport 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])
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()
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"
)
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
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)
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.