Skip to content

Commit 2b9f875

Browse files
authored
PR #13967 from AviaAv: improve depth test
2 parents 0ea07d0 + 564f325 commit 2b9f875

File tree

1 file changed

+57
-88
lines changed

1 file changed

+57
-88
lines changed

unit-tests/live/frames/test-depth.py

Lines changed: 57 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
import pyrealsense2 as rs
77
from rspy import test, log
88
from rspy import tests_wrapper as tw
9+
import numpy as np
910
import os
10-
import math
11+
import time
1112

1213
# Start depth + color streams and go through the frame to make sure it is showing a depth image
1314
# Color stream is only used to display the way the camera is facing
@@ -31,31 +32,35 @@
3132
cfg.enable_stream(rs.stream.color, rs.format.bgr8, 30)
3233

3334

34-
def display_image(img):
35-
"""
36-
Display a given image and exits when the x button or esc key are pressed
37-
"""
38-
import cv2
35+
pipeline = rs.pipeline(ctx)
36+
pipeline_profile = pipeline.start(cfg)
37+
pipeline.wait_for_frames()
38+
time.sleep(2)
3939

40-
window_title = "Output Stream"
41-
cv2.imshow(window_title, img)
42-
while cv2.getWindowProperty(window_title, cv2.WND_PROP_VISIBLE) > 0:
43-
k = cv2.waitKey(33)
44-
if k == 27: # Esc key to stop
45-
cv2.destroyAllWindows()
46-
break
47-
elif k == -1: # normally -1 returned
48-
pass
49-
50-
51-
def frames_to_image(depth, color, save, display, laser_enabled):
40+
def frames_to_image(depth, color, save, display):
5241
"""
5342
This function gets depth and color frames, transforms them to an image (numpy array)
5443
and then save and/or display
5544
5645
If color frame is given, it will also concatenate it with the depth frame before doing the given action
5746
"""
58-
import numpy as np
47+
48+
def display_image(img):
49+
"""
50+
Display a given image and exits when the x button or esc key are pressed
51+
"""
52+
import cv2
53+
54+
window_title = "Output Stream"
55+
cv2.imshow(window_title, img)
56+
while cv2.getWindowProperty(window_title, cv2.WND_PROP_VISIBLE) > 0:
57+
k = cv2.waitKey(33)
58+
if k == 27: # Esc key to stop
59+
cv2.destroyAllWindows()
60+
break
61+
elif k == -1: # normally -1 returned
62+
pass
63+
5964
import cv2
6065

6166
colorizer = rs.colorizer()
@@ -75,81 +80,43 @@ def frames_to_image(depth, color, save, display, laser_enabled):
7580
img = np.concatenate((depth_image, color_image), axis=1)
7681

7782
if save:
78-
file_name = f"output_stream{'_laser_on' if laser_enabled else '_laser_off'}.png"
83+
file_name = f"output_stream.png"
7984
log.i("Saved image in", os.getcwd() + "\\" + file_name)
8085
cv2.imwrite(file_name, img)
8186
if display:
8287
display_image(img)
8388

8489

85-
def get_frames(config, laser_enabled):
86-
pipeline = rs.pipeline(ctx)
87-
pipeline_profile = pipeline.start(config)
88-
89-
sensor = pipeline_profile.get_device().first_depth_sensor()
90-
if laser_enabled and sensor.supports(rs.option.laser_power):
91-
sensor.set_option(rs.option.laser_power, sensor.get_option_range(rs.option.laser_power).max)
92-
sensor.set_option(rs.option.emitter_enabled, 1 if laser_enabled else 0)
93-
94-
# to get a proper image, we sometimes need to wait a few frames, like when the camera is facing a light source
95-
frames = pipeline.wait_for_frames()
96-
for i in range(30):
97-
frames = pipeline.wait_for_frames()
98-
depth = frames.get_depth_frame()
99-
color = frames.get_color_frame()
100-
pipeline.stop()
101-
return depth, color
102-
90+
def get_distances(depth_frame):
91+
MAX_METERS = 10 # max distance that can be detected, in meters
10392

104-
def round_to_units(num):
105-
"""
106-
Input: Distance of a certain point, in meters
107-
Output: Distance according to the given detail level, in cm
108-
"""
109-
in_cm = round(num, 2) * 100 # convert to cm
110-
return math.floor(in_cm / DETAIL_LEVEL) * DETAIL_LEVEL # rounds the distance according to the given unit
93+
depth_m = np.asanyarray(depth_frame.get_data()).astype(np.float32) * depth_frame.get_units()
11194

95+
valid_mask = (depth_m < MAX_METERS)
96+
valid_depths = depth_m[valid_mask] # ignore invalid pixels
11297

113-
def sort_dict(my_dict):
114-
my_keys = list(my_dict.keys())
115-
my_keys.sort()
116-
sorted_dict = {i: my_dict[i] for i in my_keys}
117-
return sorted_dict
98+
# convert to cm and round according to DETAIL_LEVEL
99+
rounded_depths = (np.floor(valid_depths * 100.0 / DETAIL_LEVEL) * DETAIL_LEVEL).astype(np.int32)
118100

101+
unique_vals, counts = np.unique(rounded_depths, return_counts=True)
102+
103+
dists = dict(zip(unique_vals.tolist(), counts.tolist()))
104+
total = valid_depths.size
119105

120-
def get_distances(depth):
121-
MAX_METERS = 10 # max distance that can be detected, in meters
122-
dists = {}
123-
total = 0
124-
for y in range(depth.get_height()):
125-
for x in range(depth.get_width()):
126-
dist = depth.get_distance(x, y)
127-
if dist >= MAX_METERS: # out of bounds, assuming it is a junk value
128-
continue
129-
130-
dist = round_to_units(dist) # round according to DETAIL_LEVEL
131-
132-
if dists.get(dist) is not None:
133-
dists[dist] += 1
134-
else:
135-
dists[dist] = 1
136-
total += 1
137-
138-
dists = sort_dict(dists) # for debug convenience
139106
log.d("Distances detected in frame are:", dists)
140107
return dists, total
141108

142109

143-
def is_depth_meaningful(config, laser_enabled=True, save_image=False, show_image=False):
110+
def is_depth_meaningful(save_image=False, show_image=False):
144111
"""
145112
Checks if the camera is showing a frame with a meaningful depth.
146113
DETAIL_LEVEL is setting how close distances need to be, to be considered the same
147114
148115
returns true if frame shows meaningful depth
149116
"""
150-
151-
depth, color = get_frames(config, laser_enabled)
152-
117+
frames = pipeline.wait_for_frames()
118+
depth = frames.get_depth_frame()
119+
color = frames.get_color_frame()
153120
if not depth:
154121
log.f("Error getting depth frame")
155122
return False
@@ -160,32 +127,34 @@ def is_depth_meaningful(config, laser_enabled=True, save_image=False, show_image
160127

161128
# save or display image (only possible through manual debugging)
162129
if save_image or show_image:
163-
frames_to_image(depth, color, save_image, show_image, laser_enabled)
164-
165-
# Goes over the distances found, and checks if any distance is the same on more than 90% of the pixels
166-
meaningful_depth = True
167-
for key in dists:
168-
if dists[key] > total*0.9:
169-
meaningful_depth = False
170-
break
130+
frames_to_image(depth, color, save_image, show_image)
131+
132+
# If any distance is the same on more than 90% of the pixels, there is no meaningful depth
133+
meaningful_depth = not any(v > total * 0.9 for v in dists.values())
171134
num_blank_pixels = dists[0]
172135
return meaningful_depth, num_blank_pixels
173136

174137

175138
################################################################################################
176139

177140
test.start("Testing depth frame - laser ON -", dev.get_info(rs.camera_info.name))
178-
is_there_depth = False
179-
max_black_pixels = float('inf')
141+
# enable laser
142+
sensor = pipeline_profile.get_device().first_depth_sensor()
143+
if sensor.supports(rs.option.laser_power):
144+
sensor.set_option(rs.option.laser_power, sensor.get_option_range(rs.option.laser_power).max)
145+
sensor.set_option(rs.option.emitter_enabled, 1) # should be set to 0 for laser off
146+
147+
has_depth = False
180148

181-
# we perform the check on a few different frames to make sure we get the best indication if we have depth
149+
# we check a few different frames to try and detect depth
182150
for frame_num in range(FRAMES_TO_CHECK):
183-
result, laser_black_pixels = is_depth_meaningful(cfg, laser_enabled=True, save_image=DEBUG_MODE, show_image=DEBUG_MODE)
184-
is_there_depth = is_there_depth or result # we check if we found depth at any frame checked
185-
max_black_pixels = min(max_black_pixels, laser_black_pixels)
151+
has_depth, laser_black_pixels = is_depth_meaningful(save_image=DEBUG_MODE, show_image=DEBUG_MODE)
152+
if has_depth:
153+
break
186154

187-
test.check(is_there_depth is True)
155+
test.check(has_depth is True)
188156
test.finish()
189157

158+
pipeline.stop()
190159
tw.stop_wrapper( dev )
191160
test.print_results_and_exit()

0 commit comments

Comments
 (0)