Skip to content

Commit

Permalink
Updates to the drawing functions (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
JarnoRalli authored Jun 5, 2024
1 parent 00d724f commit eaa8210
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 213 deletions.
3 changes: 2 additions & 1 deletion deepstream-examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ List of examples:
* Uses a custom parser called [NvDsInferParseCustomRetinaface](src/retinaface_parser/nvdsparse_retinaface.cpp)
* Shows how a modified version of the `nvinfer` plug-in can be used for writing faces, detected by the primary
detector, to hard drive as images.
* Requires C++ code to be built, see instructions further down.

You can execute the examples either:

Expand All @@ -33,7 +34,7 @@ libraries and components in the host system.

# 2 Source Code

Some of the examples require C/C++ code to be built. You need the following to build the code:
[deepstream-retinaface](./deepstream-retinaface/README.md) requires C/C++ code to be built. You need the following to build the code:

* C++17 compatible compiler
* cmake >= 3.17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
PGIE_CLASS_ID_ROADSIGN = 3
past_tracking_meta = [0]

MetaObject = namedtuple('MetaObject', ['left', 'top', 'height', 'width', 'area', 'id', 'text', 'class_id'])
MetaObject = namedtuple("MetaObject", ["left", "top", "height", "width", "area", "bottom", "id", "text", "class_id"])
ColorObject = namedtuple('ColorObject', ['red', 'green', 'blue', 'alpha'])

ColorList = {
Expand All @@ -59,42 +59,29 @@

def osd_sink_pad_buffer_probe(pad, info, u_data):
frame_number = 0
# Initialising object counter with 0.
obj_counter = {
PGIE_CLASS_ID_VEHICLE: 0,
PGIE_CLASS_ID_PERSON: 0,
PGIE_CLASS_ID_BICYCLE: 0,
PGIE_CLASS_ID_ROADSIGN: 0
}
obj_counter = {PGIE_CLASS_ID_VEHICLE: 0, PGIE_CLASS_ID_PERSON: 0, PGIE_CLASS_ID_BICYCLE: 0, PGIE_CLASS_ID_ROADSIGN: 0}
num_rects = 0
gst_buffer = info.get_buffer()
if not gst_buffer:
print("Unable to get GstBuffer ")
return

# Retrieve batch metadata from the gst_buffer
# Note that pyds.gst_buffer_get_nvds_batch_meta() expects the
# C address of gst_buffer as input, which is obtained with hash(gst_buffer)
batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
l_frame = batch_meta.frame_meta_list
meta_list = []

while l_frame is not None:
try:
# Note that l_frame.data needs a cast to pyds.NvDsFrameMeta
# The casting is done by pyds.NvDsFrameMeta.cast()
# The casting also keeps ownership of the underlying memory
# in the C code, so the Python garbage collector will leave
# it alone.
frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
except StopIteration:
break

frame_number = frame_meta.frame_num
num_rects = frame_meta.num_obj_meta
l_obj = frame_meta.obj_meta_list

while l_obj is not None:
try:
# Casting l_obj.data to pyds.NvDsObjectMeta
obj_meta = pyds.NvDsObjectMeta.cast(l_obj.data)
except StopIteration:
break
Expand All @@ -106,116 +93,107 @@ def osd_sink_pad_buffer_probe(pad, info, u_data):
top=obj_meta.tracker_bbox_info.org_bbox_coords.top,
height=obj_meta.tracker_bbox_info.org_bbox_coords.height,
width=obj_meta.tracker_bbox_info.org_bbox_coords.width,
area=obj_meta.tracker_bbox_info.org_bbox_coords.height
* obj_meta.tracker_bbox_info.org_bbox_coords.width,
area=obj_meta.tracker_bbox_info.org_bbox_coords.height * obj_meta.tracker_bbox_info.org_bbox_coords.width,
bottom=obj_meta.tracker_bbox_info.org_bbox_coords.top + obj_meta.tracker_bbox_info.org_bbox_coords.height,
id=obj_meta.object_id,
text=pyds.get_string(obj_meta.text_params.display_text),
class_id=obj_meta.class_id
text=f"ID: {obj_meta.object_id:04d}, Class: {pyds.get_string(obj_meta.text_params.display_text)}",
class_id=obj_meta.class_id,
)
meta_list.append(obj)

# Disable default text and background
obj_meta.text_params.display_text = ""
obj_meta.text_params.set_bg_clr = 0

# Disable showing of default object bbox
obj_meta.rect_params.border_width = 0

try:
l_obj = l_obj.next
except StopIteration:
break

# Sort the meta_list so that objects further back are drawn first
meta_list_sorted = sorted(meta_list, key=attrgetter('area'))

# Acquiring a display meta object. The memory ownership remains in
# the C code so downstream plugins can still access it. Otherwise
# the garbage collector will claim it when this probe function exits.
display_meta = pyds.nvds_acquire_display_meta_from_pool(batch_meta)

# Display tracked object ID information
display_meta.num_labels = len(meta_list_sorted) + 1
for idx in range(len(meta_list_sorted)):
x = int(meta_list_sorted[idx].left)
y = int(meta_list_sorted[idx].top) - 15

# Negative values not allowed
if x < 0 or y < 0:
continue

display_meta.text_params[idx].display_text = meta_list_sorted[idx].text
display_meta.text_params[idx].x_offset = x
display_meta.text_params[idx].y_offset = y
display_meta.text_params[idx].font_params.font_name = "Serif"
display_meta.text_params[idx].font_params.font_size = 10
display_meta.text_params[idx].font_params.font_color.set(1.0, 1.0, 1.0, 1.0)
display_meta.text_params[idx].set_bg_clr = 1
display_meta.text_params[idx].text_bg_clr.set(0.45, 0.20, 0.50, 0.75)

# Display information regarding number of objects detected
idx = display_meta.num_labels - 1
display_meta.text_params[idx].display_text = f"Frame number={frame_number}, " \
f"nr objects={num_rects}, " \
f"vehicles={obj_counter[PGIE_CLASS_ID_VEHICLE]}, " \
f"bicycles={obj_counter[PGIE_CLASS_ID_BICYCLE]}, " \
f"persons={obj_counter[PGIE_CLASS_ID_PERSON]}, " \
f"roadsigns={obj_counter[PGIE_CLASS_ID_ROADSIGN]}"
display_meta.text_params[idx].x_offset = 10
display_meta.text_params[idx].y_offset = 14
display_meta.text_params[idx].font_params.font_name = "Serif"
display_meta.text_params[idx].font_params.font_size = 12
display_meta.text_params[idx].font_params.font_color.set(1.0, 1.0, 1.0, 1.0)
display_meta.text_params[idx].set_bg_clr = 1
display_meta.text_params[idx].text_bg_clr.set(0.45, 0.20, 0.50, 0.75)

# Display tracker bounding boxes
display_meta.num_rects = len(meta_list_sorted)
for idx in range(len(meta_list_sorted)):
# Extract colours, based on the class_id
red = ColorList[meta_list_sorted[idx].class_id].red
green = ColorList[meta_list_sorted[idx].class_id].green
blue = ColorList[meta_list_sorted[idx].class_id].blue
alpha = ColorList[meta_list_sorted[idx].class_id].alpha
# Draw bounding boxes
display_meta.rect_params[idx].left = meta_list_sorted[idx].left
display_meta.rect_params[idx].top = meta_list_sorted[idx].top
display_meta.rect_params[idx].width = meta_list_sorted[idx].width
display_meta.rect_params[idx].height = meta_list_sorted[idx].height
display_meta.rect_params[idx].border_width = 1
display_meta.rect_params[idx].border_color.red = red
display_meta.rect_params[idx].border_color.green = green
display_meta.rect_params[idx].border_color.blue = blue
display_meta.rect_params[idx].border_color.alpha = alpha
display_meta.rect_params[idx].has_bg_color = 0

pyds.nvds_add_display_meta_to_frame(frame_meta, display_meta)
meta_list_sorted = sorted(meta_list, key=attrgetter("bottom"))
max_labels = 10 # Define a suitable number for max_labels
num_objects = len(meta_list_sorted)
num_meta_objects = (num_objects + max_labels - 1) // max_labels

# Create a single display_meta for the frame counter and object counts
display_meta_main = pyds.nvds_acquire_display_meta_from_pool(batch_meta)
display_meta_main.num_labels = 1
py_nvosd_text_params = display_meta_main.text_params[0]
py_nvosd_text_params.display_text = (
f"Frame Number={frame_number:05d}, Number of Objects={num_rects:04d}, "
f"Vehicles={obj_counter[PGIE_CLASS_ID_VEHICLE]:04d}, "
f"Persons={obj_counter[PGIE_CLASS_ID_PERSON]:04d}, "
f"Bicycles={obj_counter[PGIE_CLASS_ID_BICYCLE]:04d}, "
f"Road Signs={obj_counter[PGIE_CLASS_ID_ROADSIGN]:04d}"
)
py_nvosd_text_params.x_offset = 10
py_nvosd_text_params.y_offset = 12
py_nvosd_text_params.font_params.font_name = "Serif"
py_nvosd_text_params.font_params.font_size = 10
py_nvosd_text_params.font_params.font_color.set(1.0, 1.0, 1.0, 1.0)
py_nvosd_text_params.set_bg_clr = 1
py_nvosd_text_params.text_bg_clr.set(0.0, 0.0, 0.0, 1.0)
pyds.nvds_add_display_meta_to_frame(frame_meta, display_meta_main)

for i in range(num_meta_objects):
display_meta = pyds.nvds_acquire_display_meta_from_pool(batch_meta)
display_meta.num_labels = 0

start_idx = i * max_labels
end_idx = min((i + 1) * max_labels, num_objects)

for j, idx in enumerate(range(start_idx, end_idx)):
x = int(meta_list_sorted[idx].left)
y = int(meta_list_sorted[idx].top) - 15

if x < 0 or y < 0:
continue

display_meta.text_params[display_meta.num_labels].display_text = meta_list_sorted[idx].text
display_meta.text_params[display_meta.num_labels].x_offset = x
display_meta.text_params[display_meta.num_labels].y_offset = y
display_meta.text_params[display_meta.num_labels].font_params.font_name = "Serif"
display_meta.text_params[display_meta.num_labels].font_params.font_size = 10
display_meta.text_params[display_meta.num_labels].font_params.font_color.set(1.0, 1.0, 1.0, 1.0)
display_meta.text_params[display_meta.num_labels].set_bg_clr = 1
display_meta.text_params[display_meta.num_labels].text_bg_clr.set(0.45, 0.20, 0.50, 0.75)
display_meta.num_labels += 1

display_meta.num_rects = end_idx - start_idx
for j, idx in enumerate(range(start_idx, end_idx)):
red = ColorList[meta_list_sorted[idx].class_id].red
green = ColorList[meta_list_sorted[idx].class_id].green
blue = ColorList[meta_list_sorted[idx].class_id].blue
alpha = ColorList[meta_list_sorted[idx].class_id].alpha

display_meta.rect_params[j].left = meta_list_sorted[idx].left
display_meta.rect_params[j].top = meta_list_sorted[idx].top
display_meta.rect_params[j].width = meta_list_sorted[idx].width
display_meta.rect_params[j].height = meta_list_sorted[idx].height
display_meta.rect_params[j].border_width = 2
display_meta.rect_params[j].border_color.red = red
display_meta.rect_params[j].border_color.green = green
display_meta.rect_params[j].border_color.blue = blue
display_meta.rect_params[j].border_color.alpha = alpha
display_meta.rect_params[j].has_bg_color = 0

pyds.nvds_add_display_meta_to_frame(frame_meta, display_meta)

try:
l_frame = l_frame.next
except StopIteration:
break

# past tracking meta data
# Past tracking meta data
if past_tracking_meta[0] == 1:
l_user = batch_meta.batch_user_meta_list
while l_user is not None:
try:
# Note that l_user.data needs a cast to pyds.NvDsUserMeta
# The casting is done by pyds.NvDsUserMeta.cast()
# The casting also keeps ownership of the underlying memory
# in the C code, so the Python garbage collector will leave
# it alone
user_meta = pyds.NvDsUserMeta.cast(l_user.data)
except StopIteration:
break
if user_meta and user_meta.base_meta.meta_type == pyds.NvDsMetaType.NVDS_TRACKER_PAST_FRAME_META:
try:
# Note that user_meta.user_meta_data needs a cast to pyds.NvDsPastFrameObjBatch
# The casting is done by pyds.NvDsPastFrameObjBatch.cast()
# The casting also keeps ownership of the underlying memory
# in the C code, so the Python garbage collector will leave
# it alone
pPastFrameObjBatch = pyds.NvDsPastFrameObjBatch.cast(user_meta.user_meta_data)
except StopIteration:
break
Expand All @@ -228,17 +206,18 @@ def osd_sink_pad_buffer_probe(pad, info, u_data):
print("classId=", pastframeobj.classId)
print("objLabel=", pastframeobj.objLabel)
for objlist in pyds.NvDsPastFrameObjList.list(pastframeobj):
print('frameNum:', objlist.frameNum)
print('tBbox.left:', objlist.tBbox.left)
print('tBbox.width:', objlist.tBbox.width)
print('tBbox.top:', objlist.tBbox.top)
print('tBbox.right:', objlist.tBbox.height)
print('confidence:', objlist.confidence)
print('age:', objlist.age)
print("frameNum:", objlist.frameNum)
print("tBbox.left:", objlist.tBbox.left)
print("tBbox.width:", objlist.tBbox.width)
print("tBbox.top:", objlist.tBbox.top)
print("tBbox.right:", objlist.tBbox.height)
print("confidence:", objlist.confidence)
print("age:", objlist.age)
try:
l_user = l_user.next
except StopIteration:
break

return Gst.PadProbeReturn.OK


Expand Down
Loading

0 comments on commit eaa8210

Please sign in to comment.