- Edited
I have implemented Depth Measuring code to know depth between camera and sand container of a truck to see depth of sand inside the container. I was expecting all different depth in each pixel because it is essentially impossible to have flat depth all around sand content because sand was just dumped into the container without flattening. But When I checked the result of depth camera image, I can only see certain depth values (uniquely only about 13 values). If I make an example of depth array, It would be like this (suppose we got only 3 unique values instead of 13)
[33, 78, 9, 9
33, 78, 9, 9
78, 33, 78, 9
78, 78, 78, 33]
But when I check depth with depthAI viewer, it shows a lot more fine-grained depth values in each pixel. So it must be the code that is wrong in capturing depth in fine-grained manner.
We are using OAK-D S2 PoE camera, and distance between the camera and the container should be roughly 7m.
Here is full code taking out irrelevant parts leaving only depth camera part.
I wish to know where I should fix to get the fine-grained depth values throughout the depth array accurately.
import sys
print(sys.prefix)
import os
import io
import time
import json
import base64
import random
import socket
import datetime
from datetime import timedelta
from multiprocessing import Process, Queue
import threading
import traceback
import statistics
import logging.handlers
import matplotlib.pyplot as plt
from PIL import Image
import timm
import torch
import numpy as np
import pandas as pd
import cv2
from torchvision import transforms
import subprocess
#### This is for depth camera
import depthai as dai
from datetime import timedelta
import pickle
sys.path.append("/home/sdt/Workspace/onvif/python-onvif-zeep/socket")
# sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
#### for MaskDINO #####
import multiprocessing as mp
# fmt: off
sys.path.insert(1, os.path.join(sys.path[0], '..'))
mp.set_start_method("spawn", force=True)
######################################################################
# Save Log #
######################################################################
logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
log_max_size = 1024000
log_file_count = 3
log_fileHandler = logging.handlers.RotatingFileHandler(
filename=f"/home/sdt/Workspace/onvif/python-onvif-zeep/socket/sam2/logs/socket_data.log",
maxBytes=log_max_size,
backupCount=log_file_count,
mode='a')
log_fileHandler.setFormatter(formatter)
logger.addHandler(log_fileHandler)
class depth_cam:
def __init__(self):
# Create pipeline
self.pipeline = dai.Pipeline()
self.device = dai.Device()
self.fps = 30
# The disparity is computed at this resolution, then upscaled to RGB resolution
#monoResolution = dai.MonoCameraProperties.SensorResolution.THE_720_P
self.monoResolution = dai.MonoCameraProperties.SensorResolution.THE_800_P
# Define sources and outputs
self.camRgb = self.pipeline.create(dai.node.ColorCamera)
self.left = self.pipeline.create(dai.node.MonoCamera)
self.right = self.pipeline.create(dai.node.MonoCamera)
self.stereo = self.pipeline.create(dai.node.StereoDepth)
try:
calibData = self.device.readCalibration2()
lensPosition = calibData.getLensPosition(dai.CameraBoardSocket.CAM_A)
if lensPosition:
self.camRgb.initialControl.setManualFocus(lensPosition)
except:
raise
#Properties
self.camRgb.setBoardSocket(dai.CameraBoardSocket.CAM_A)
self.camRgb.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P)
self.camRgb.setFps(self.fps)
self.left.setResolution(self.monoResolution)
self.left.setBoardSocket(dai.CameraBoardSocket.CAM_B)
self.left.setFps(self.fps)
self.right.setResolution(self.monoResolution)
self.right.setBoardSocket(dai.CameraBoardSocket.CAM_C)
self.right.setFps(self.fps)
self.stereo.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
# LR-check is required for depth alignment
self.stereo.setLeftRightCheck(True)
self.stereo.setDepthAlign(dai.CameraBoardSocket.CAM_A)
self.h, self.w = 1280, 720
self.stereo.setOutputSize(self.h, self.w)
##################Use this when using Sync##################
self.sync = self.pipeline.create(dai.node.Sync)
self.sync.setSyncThreshold(timedelta(milliseconds=50))
self.sync.inputs["rgb"].setQueueSize(1)
self.sync.inputs["depth"].setQueueSize(1)
self.sync.inputs["disparity"].setQueueSize(1)
# Linking
self.camRgb.isp.link(self.sync.inputs["rgb"])
self.left.out.link(self.stereo.left)
self.right.out.link(self.stereo.right)
self.stereo.depth.link(self.sync.inputs["depth"])
self.stereo.disparity.link(self.sync.inputs["disparity"])
self.sync_out = self.pipeline.createXLinkOut()
self.sync_out.setStreamName("rgbd")
self.sync.out.link(self.sync_out.input)
self.sync_out.input.setQueueSize(1)
def main_depth(q, sdt_msdb):
try:
packets = q.get()
logger.info(f"Depth queue got data")
str_data = packets[0]
logger.info(f"Depth str_data: {str_data}")
depth_frame = packets[1]
logger.info(f"depth_frame shape: {depth_frame.shape}")
rgb_frame = packets[2]
logger.info(f"rgb_frame shape: {rgb_frame.shape}")
except:
logger.error(traceback.format_exc())
if __name__ == "__main__":
# Fix Seed
# Load Camera
depth_camera = depth_cam()
print("Depth cam initialized")
logger.info(f"Depth camera initialized: {depth_camera}")
queue_depth = Queue()
with depth_camera.device:
depth_camera.device.startPipeline(depth_camera.pipeline)
for _ in range(20):
depth_camera.device.getOutputQueue("rgbd", maxSize=1, blocking=False).getAll()
logger.info("Left queue for depth camera flushed")
while True:
try:
# Connect to device and start pipeline
while True:
logger.info('Waiting for client......')
data = client_socket.recv(1024) # type: bytes
if not data:
break
#############DEPTH CAMERA START########################
time.sleep(0.6)
depth_camera.messages = depth_camera.device.getOutputQueue("rgbd", maxSize=1, blocking=False).getAll()
for message_group in depth_camera.messages:
for name, frame in message_group:
if name == 'depth':
# If the packet from RGB camera is present, we're retrieving the frame in OpenCV format using getCvFrame
depth_frame = frame.getCvFrame()##.astype(np.uint16)
depth_time = datetime.datetime.now()
logger.info(f"Depth depth img saved at : {depth_time}")
logger.info(f"Depth depth array saved at : {depth_time}")
with open(f"/home/sdt/Workspace/onvif/python-onvif-zeep/hojun/image_test/depth_depth_array/depthFrameArray_{depth_time}_{item_code}_{type_code}_{from_code}.pickle", 'wb') as f:
pickle.dump(depth_frame, f)
#=======================================
qdata_depth = [depth_frame]
queue_depth.put(qdata_depth)
sampyo_processes = [
Process(target=main_depth, args=(queue_depth))
]
for process in sampyo_processes:
process.start()
logger.info(f"[*] Disconnected connection from {client_address[0]}:{client_address[1]}")
client_socket.close()
except KeyboardInterrupt:
server_socket.close()
cv2.destroyAllWindows()
exit()
except ConnectionResetError:
logger.info(f"[*] Client Disconnected.")
except Exception as e:
logger.error(traceback.format_exc())
server_socket.close()
exit()
Thank you in advance.