Skip to content

Commit 53f82a6

Browse files
jimmy-rubin-workJimmy Rubinisak-jacobsson
authored andcommitted
object-detection*: Make use of the new larod functions from 12.7
Co-authored-by: Jimmy Rubin <jimmyrn@axis.com> Co-authored-by: Isak Jakobsson <isakj@axis.com>
1 parent 11ba0a8 commit 53f82a6

26 files changed

Lines changed: 2265 additions & 2031 deletions

object-detection-yolov5/README.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ object-detection-yolov5
2828
├── app
2929
│ ├── argparse.c
3030
│ ├── argparse.h
31-
│ ├── imgprovider.c
32-
│ ├── imgprovider.h
31+
│ ├── channel_util.c
32+
│ ├── channel_util.h
33+
│ ├── img_util.c
34+
│ ├── img_util.h
3335
│ ├── labelparse.c
3436
│ ├── labelparse.h
3537
│ ├── LICENSE
@@ -39,6 +41,8 @@ object-detection-yolov5
3941
│ ├── manifest.json.cpu
4042
│ ├── model.c
4143
│ ├── model.h
44+
│ ├── model_preprocessing.c
45+
│ ├── model_preprocessing.h
4246
│ ├── object_detection_yolov5.c
4347
│ ├── panic.c
4448
│ ├── panic.h
@@ -48,7 +52,8 @@ object-detection-yolov5
4852
```
4953

5054
- **app/argparse.c/h** - Program argument parser.
51-
- **app/imgprovider.c/h** - Implementation of VDO parts.
55+
- **app/channel-util.c/h** - Utility function for wrapping VdoChannel.
56+
- **app/img-util.c/h** - Handle the update of framerate dependent on inference and post processing time..
5257
- **app/labelparse.c/h** - Parse file of labels.
5358
- **app/LICENSE** - Text file which lists all open source licensed source code distributed with the
5459
application.
@@ -61,7 +66,8 @@ ARTPEC-8 DLPU with TensorFlow Lite.
6166
- **app/manifest.json.cpu** - Defines the application and its configuration when building for
6267
CPU with TensorFlow Lite.
6368
- **app/object_detection_yolov5.c** - Application source code in C.
64-
- **app/model.c/h** - Implementation of Larod parts.
69+
- **app/model.c/h** - Handle most of the larod functionality.
70+
- **app/model_preproessing.c/h** - Wrapper for the preprocessing part of larod.
6571
- **app/panic.c/h** - Utility for exiting the program on error.
6672
- **app/parameter_finder.py** - Python script to create `model_params.h`, containing model specific
6773
parameters.
@@ -108,7 +114,7 @@ that has the same aspect ratio as the native aspect ratio.
108114
1. Fetch image data from VDO.
109115
2. Convert image data to the correct format with the Larod pre-processing job, if needed.
110116
3. Run inference with the Larod model inference job.
111-
4. Measure the total inference time (preprocessing and inference time) and adjust the framerate of the vdo stream if needed.
117+
4. Measure the total inference time (preprocessing, inference time, and parsing time) and adjust the framerate of the vdo stream if needed.
112118
5. Perform YOLOv5-specific parsing of the output.
113119
6. Draw bounding boxes and log details about the detected objects.
114120

object-detection-yolov5/app/Makefile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PROG1 = $(shell jq -r '.acapPackageConf.setup.appName' manifest.json)
2-
OBJS1 = $(PROG1).c argparse.c imgprovider.c model.c panic.c labelparse.c
2+
OBJS1 = $(PROG1).c argparse.c channel_util.c img_util.c labelparse.c model.c model_preprocessing.c panic.c
33
PROGS = $(PROG1)
44
DEBUG_DIR = debug
55

@@ -9,8 +9,6 @@ CFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --cflags $(PKGS)
99
LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs $(PKGS))
1010
LDLIBS += -lm
1111

12-
CFLAGS += -DLAROD_API_VERSION_3
13-
1412
CFLAGS += -Wall \
1513
-Wextra \
1614
-Wformat=2 \
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/**
2+
* Copyright (C) 2025, Axis Communications AB, Lund, Sweden
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* This file handles the vdo channel part of the application.
19+
*/
20+
21+
#include "channel_util.h"
22+
23+
#include <assert.h>
24+
#include <errno.h>
25+
#include <glib-object.h>
26+
#include <gmodule.h>
27+
#include <math.h>
28+
#include <poll.h>
29+
#include <syslog.h>
30+
31+
#include "panic.h"
32+
#include "vdo-map.h"
33+
#include <vdo-channel.h>
34+
#include <vdo-error.h>
35+
36+
G_DEFINE_AUTOPTR_CLEANUP_FUNC(VdoResolutionSet, g_free);
37+
38+
bool channel_util_choose_stream_resolution(unsigned int channel_id,
39+
VdoResolution req_res,
40+
VdoResolution* chosen_req,
41+
unsigned int rotation,
42+
VdoFormat* chosen_format) {
43+
g_autoptr(VdoResolutionSet) set = NULL;
44+
g_autoptr(VdoChannel) channel = NULL;
45+
g_autoptr(GError) error = NULL;
46+
g_autoptr(VdoMap) resolution_filter = vdo_map_new();
47+
48+
assert(chosen_format);
49+
assert(chosen_req);
50+
51+
channel = vdo_channel_get(channel_id, &error);
52+
if (!channel) {
53+
panic("%s: Failed vdo_channel_get(): %s", __func__, error->message);
54+
}
55+
56+
*chosen_req = req_res;
57+
58+
if (rotation == 90 || rotation == 270) {
59+
// To be able to get the wanted resolution the resolution
60+
// needs to be unrotated then vdo will supply frames that have
61+
// the resolution img_info->width x img_info->height
62+
unsigned int tmp_width = req_res.width;
63+
chosen_req->width = req_res.height;
64+
chosen_req->height = tmp_width;
65+
}
66+
67+
// Start to see if the supplied image format is available on this
68+
// product. If not default to yuv
69+
vdo_map_set_uint32(resolution_filter, "format", *chosen_format);
70+
vdo_map_set_string(resolution_filter, "select", "all");
71+
vdo_map_set_string(resolution_filter, "aspect_ratio", "native");
72+
73+
set = vdo_channel_get_resolutions(channel, resolution_filter, &error);
74+
if (!set || set->count == 0) {
75+
// The supplied format is not supported, default to YUV
76+
if (set) {
77+
free(set);
78+
}
79+
if (*chosen_format == VDO_FORMAT_YUV) {
80+
panic("%s: Not possible to get any resolution from vdo for %u",
81+
__func__,
82+
*chosen_format);
83+
}
84+
*chosen_format = VDO_FORMAT_YUV;
85+
vdo_map_set_uint32(resolution_filter, "format", *chosen_format);
86+
set = vdo_channel_get_resolutions(channel, resolution_filter, &error);
87+
if (!set || set->count == 0) {
88+
panic("%s: Not possible to get any resolution from vdo for %u",
89+
__func__,
90+
*chosen_format);
91+
}
92+
}
93+
94+
// Find smallest VDO stream resolution that fits the requested size.
95+
ssize_t best_resolution_idx = -1;
96+
unsigned int best_resolution_area = UINT_MAX;
97+
for (ssize_t i = 0; i < (ssize_t)set->count; ++i) {
98+
VdoResolution* res = &set->resolutions[i];
99+
if ((res->width >= chosen_req->width) && (res->height >= chosen_req->height)) {
100+
unsigned int area = res->width * res->height;
101+
if (area < best_resolution_area) {
102+
best_resolution_idx = i;
103+
best_resolution_area = area;
104+
}
105+
}
106+
}
107+
108+
// If we got a reasonable w/h from the VDO channel info we use that
109+
// for creating the stream. If that info for some reason was empty we
110+
// fall back to trying to create a stream with client-supplied w/h.
111+
if (best_resolution_idx >= 0) {
112+
chosen_req->width = set->resolutions[best_resolution_idx].width;
113+
chosen_req->height = set->resolutions[best_resolution_idx].height;
114+
} else {
115+
syslog(LOG_WARNING,
116+
"%s: VDO channel info contains no reslution info. Fallback "
117+
"to client-requested stream resolution.",
118+
__func__);
119+
}
120+
const char* format_str = "rgb interleaved";
121+
switch (*chosen_format) {
122+
case VDO_FORMAT_YUV:
123+
format_str = "yuv";
124+
break;
125+
case VDO_FORMAT_PLANAR_RGB:
126+
format_str = "planar rgb";
127+
break;
128+
case VDO_FORMAT_RGB:
129+
format_str = "rgb interleaved";
130+
break;
131+
default:
132+
panic("%s Unknown format %u", __func__, *chosen_format);
133+
}
134+
syslog(LOG_INFO,
135+
"%s: We select stream w/h=%u x %u with format %s based on VDO channel info.\n",
136+
__func__,
137+
chosen_req->width,
138+
chosen_req->height,
139+
format_str);
140+
141+
return true;
142+
}
143+
144+
unsigned int channel_util_get_image_rotation(unsigned int channel_id) {
145+
g_autoptr(VdoChannel) channel = NULL;
146+
g_autoptr(GError) error = NULL;
147+
148+
channel = vdo_channel_get(channel_id, &error);
149+
if (!channel) {
150+
panic("%s: Failed vdo_channel_get() for %u: %s", __func__, channel_id, error->message);
151+
}
152+
g_autoptr(VdoMap) info = vdo_channel_get_info(channel, &error);
153+
if (!info) {
154+
panic("%s: Failed vdo_channel_get_info(): %s", __func__, error->message);
155+
}
156+
return vdo_map_get_uint32(info, "rotation", 0);
157+
}
158+
159+
unsigned int channel_util_get_first_input_channel(void) {
160+
g_autoptr(VdoChannel) channel = NULL;
161+
g_autoptr(GError) error = NULL;
162+
g_autoptr(VdoMap) ch_desc = vdo_map_new();
163+
164+
// Take the first input channel
165+
vdo_map_set_uint32(ch_desc, "input", 1);
166+
channel = vdo_channel_get_ex(ch_desc, &error);
167+
if (!channel) {
168+
panic("%s: Failed vdo_channel_get(): %s", __func__, error->message);
169+
}
170+
g_autoptr(VdoMap) info = vdo_channel_get_info(channel, &error);
171+
if (!info) {
172+
panic("%s: Failed vdo_channel_get_info(): %s", __func__, error->message);
173+
}
174+
return vdo_map_get_uint32(info, "id", 1);
175+
}
176+
177+
VdoPair32u channel_util_get_aspect_ratio(unsigned int channel_id) {
178+
g_autoptr(VdoChannel) channel = NULL;
179+
g_autoptr(GError) error = NULL;
180+
VdoPair32u aspect_ratio_def = {.w = 0u, .h = 0u};
181+
182+
// Take the first input channel
183+
channel = vdo_channel_get(channel_id, &error);
184+
if (!channel) {
185+
panic("%s: Failed vdo_channel_get(): %s", __func__, error->message);
186+
}
187+
g_autoptr(VdoMap) info = vdo_channel_get_info(channel, &error);
188+
if (!info) {
189+
panic("%s: Failed vdo_channel_get_info(): %s", __func__, error->message);
190+
}
191+
return vdo_map_get_pair32u(info, "aspect_ratio", aspect_ratio_def);
192+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Copyright (C) 2025, Axis Communications AB, Lund, Sweden
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* This header file handles the vdo part of the application.
19+
*/
20+
21+
#pragma once
22+
23+
#include <stdbool.h>
24+
#include <stdint.h>
25+
26+
#include "vdo-error.h"
27+
#include "vdo-stream.h"
28+
#include "vdo-types.h"
29+
30+
bool channel_util_choose_stream_resolution(unsigned int channel,
31+
VdoResolution req_res,
32+
VdoResolution* chosen_req,
33+
unsigned int rotation,
34+
VdoFormat* chosen_format);
35+
36+
unsigned int channel_util_get_image_rotation(unsigned int input_channel);
37+
unsigned int channel_util_get_first_input_channel(void);
38+
VdoPair32u channel_util_get_aspect_ratio(unsigned int channel_id);

0 commit comments

Comments
 (0)