Hello,
I need some assistance to run an example inference application on the Hailo8.
I’m trying to use the license plate detection network with the infer_pipeline_example.
I see that even though the in-out buffers are setup no data is written/read from it, so no actual inference is performed.
The network requires a 416x416x3 image as input, so I provided one in the form of a txt file, where the bytes of the image are represented as characters.
At this point I need to read out the bounding box informations. I used the little information that I could find online regarding yolo v4 output structure, but the result is still wrong. I attached below my code, any guidance would be appreciated.
void manualDrawBox(
std::vector<uint8_t> &image_data,
int width,
int height,
const std::vector<uint8_t> ¢ers,
const std::vector<uint8_t> &obj,
const std::vector<uint8_t> &probs,
const std::vector<uint8_t> &scales,
float confidence_threshold,
float obj_threshold, int r, int g, int b)
{
int channels = 3; // Assuming RGB channels
size_t num_boxes = obj.size(); // Assuming obj vector length represents the number of boxes
for (size_t i = 0; i < num_boxes; ++i)
{
float objectness = static_cast<float>(obj[i]) / 255.0f;
if (objectness > 0.5)
{
cout << "found a good box" << endl;
// Extract the center and scale information
int center_x = static_cast<int>((static_cast<float>(centers[i * 2]) / 255.0f) * width);
int center_y = static_cast<int>((static_cast<float>(centers[i * 2 + 1]) / 255.0f) * height);
int box_width = static_cast<int>((static_cast<float>(scales[i * 2]) / 255.0f) * width);
int box_height = static_cast<int>((static_cast<float>(scales[i * 2 + 1]) / 255.0f) * height);
// center = output + offset of relative cell
cout << "[" << center_x << " - " << center_y << "]" << "w: " << box_width << "h: " << box_height << endl;
// Calculate top-left and bottom-right corners
int top_left_x = std::max(center_x - box_width / 2, 0);
int top_left_y = std::max(center_y - box_height / 2, 0);
int bottom_right_x = std::min(center_x + box_width / 2, width - 1);
int bottom_right_y = std::min(center_y + box_height / 2, height - 1);
// Draw top and bottom horizontal lines of the bounding box
for (int x = top_left_x; x <= bottom_right_x; ++x)
{
// Top border
int top_index = (top_left_y * width + x) * channels;
image_data[top_index] = r; // Blue
image_data[top_index + 1] = g; // Green
image_data[top_index + 2] = b; // Red
// Bottom border
int bottom_index = (bottom_right_y * width + x) * channels;
image_data[bottom_index] = r; // Blue
image_data[bottom_index + 1] = g; // Green
image_data[bottom_index + 2] = b; // Red
}
// Draw left and right vertical lines of the bounding box
for (int y = top_left_y; y <= bottom_right_y; ++y)
{
// Left border
int left_index = (y * width + top_left_x) * channels;
image_data[left_index] = r; // Blue
image_data[left_index + 1] = g; // Green
image_data[left_index + 2] = b; // Red
// Right border
int right_index = (y * width + bottom_right_x) * channels;
image_data[right_index] = r; // Blue
image_data[right_index + 1] = g; // Green
image_data[right_index + 2] = b; // Red
}
}
}
}
hailo_status infer(InferVStreams &pipeline)
{
const size_t frames_count = 1;
std::vector<uint8_t> image_data = read_image_from_file("image.txt");
// Set input buffers and MemoryView
std::map<std::string, std::vector<uint8_t>> input_data;
auto input_vstreams = pipeline.get_input_vstreams();
for (const auto &input_vstream : input_vstreams)
{
input_data.emplace(input_vstream.get().name(), std::vector<uint8_t>(input_vstream.get().get_frame_size() * frames_count));
}
for (const auto &input_vstream : input_vstreams)
{
auto &input_buffer = input_data[input_vstream.get().name()];
for (size_t i = 0; i < image_data.size(); ++i)
{
input_buffer[i] = static_cast<uint8_t>(image_data[i] + 128);
}
}
std::map<std::string, MemoryView> input_data_mem_views;
for (const auto &input_vstream : input_vstreams)
{
auto &input_buffer = input_data[input_vstream.get().name()];
input_data_mem_views.emplace(input_vstream.get().name(), MemoryView(input_buffer.data(), input_buffer.size()));
}
// Set output buffers and MemoryView
std::map<std::string, std::vector<uint8_t>> output_data;
auto output_vstreams = pipeline.get_output_vstreams();
for (const auto &output_vstream : output_vstreams)
{
output_data.emplace(output_vstream.get().name(), std::vector<uint8_t>(output_vstream.get().get_frame_size() * frames_count));
}
std::map<std::string, MemoryView> output_data_mem_views;
for (const auto &output_vstream : output_vstreams)
{
auto &output_buffer = output_data[output_vstream.get().name()];
output_data_mem_views.emplace(output_vstream.get().name(), MemoryView(output_buffer.data(), output_buffer.size()));
}
// Inference
hailo_status status = pipeline.infer(input_data_mem_views, output_data_mem_views, frames_count);
if (status != HAILO_SUCCESS)
{
return status;
}
// Read output
vector<uint8_t> centers_19;
vector<uint8_t> obj_19;
vector<uint8_t> probs_19;
vector<uint8_t> scales_19;
vector<uint8_t> centers_21;
vector<uint8_t> obj_21;
vector<uint8_t> probs_21;
vector<uint8_t> scales_21;
string s;
// Process output
std::vector<std::pair<std::string, std::vector<float>>> processed_output;
for (const auto &output_vstream : output_vstreams)
{
s = output_vstream.get().name();
if (s == "tiny_yolov4_license_plates/conv19_centers")
{
centers_19 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
if (s == "tiny_yolov4_license_plates/conv19_obj")
{
obj_19 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
if (s == "tiny_yolov4_license_plates/conv19_probs")
{
probs_19 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
if (s == "tiny_yolov4_license_plates/conv19_scales")
{
scales_19 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
if (s == "tiny_yolov4_license_plates/conv21_centers")
{
centers_21 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
if (s == "tiny_yolov4_license_plates/conv21_obj")
{
obj_21 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
if (s == "tiny_yolov4_license_plates/conv21_probs")
{
probs_21 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
if (s == "tiny_yolov4_license_plates/conv21_scales")
{
scales_21 = output_data[s];
cout << s << " - " << output_vstream.get().get_frame_size() << endl;
}
}
manualDrawBox(image_data, 416, 416, centers_19, obj_19, probs_19, scales_19, 0.1, 0.1, 255, 0, 0);
manualDrawBox(image_data, 416, 416, centers_21, obj_21, probs_21, scales_21, 0.1, 0.1, 0, 0, 255);
// write image to file etc
return HAILO_SUCCESS;
}