source with everything the analysis found drawn on it: element boxes (yellow) and contours (cyan), track arrows from previous to current position (green tracked, red lost) with their bounds and centroid (white), keypoints (magenta) with their bounds.
671{
672 const glm::vec4 yellow { 1.0F, 1.0F, 0.0F, 1.0F };
673 const glm::vec4 cyan { 0.0F, 1.0F, 1.0F, 1.0F };
674 const glm::vec4 green { 0.0F, 1.0F, 0.0F, 1.0F };
675 const glm::vec4 red { 1.0F, 0.0F, 0.0F, 1.0F };
676 const glm::vec4 white { 1.0F, 1.0F, 1.0F, 1.0F };
677 const glm::vec4 magenta { 1.0F, 0.0F, 1.0F, 1.0F };
678
679 const glm::vec2 half { 3.0F / static_cast<float>(source_w), 3.0F / static_cast<float>(source_h) };
680
681 std::vector<float> segments;
682
683 if (analysis.find_elements) {
684 for (const auto& box : analysis.find_elements->boxes)
685 add_rect(segments, box, yellow);
686 for (const auto& contour : analysis.find_elements->contours) {
687 const auto n = contour.points.size();
688 for (size_t i = 0; n > 1 && i < n; ++i)
689 add_line(segments, contour.points[i], contour.points[(i + 1) % n], cyan);
690 }
691 }
692
693 if (analysis.track_objects && !analysis.track_objects->tracks.empty()) {
694 for (const auto& t : analysis.track_objects->tracks) {
695 add_line(segments, t.previous, t.position, t.tracked ? green : red);
696 add_cross(segments, t.position, half, t.tracked ? green : red);
697 }
698 add_rect(segments, analysis.track_objects->bounds, white);
699 add_cross(segments, analysis.track_objects->centroid, half, white);
700 }
701
702 if (analysis.detect_features && !analysis.detect_features->keypoints.empty()) {
703 for (const auto& k : analysis.detect_features->keypoints)
704 add_cross(segments, k.
position, half, magenta);
705 add_rect(segments, analysis.detect_features->bounds, white);
706 }
707
708 const auto count =
static_cast<uint32_t
>(segments.size() / 8);
709 if (segments.empty())
710 segments.assign(8, 0.0F);
711
713 use_shader(ctx, "vision_crop.comp.spv", k_wg_image, sizeof(CropPC));
714 ctx.stage_image(source);
715 ctx.set_binding_data(3, std::span<const float>(segments));
716 ctx.set_push_constants(CropPC {
717 .src_x = 0.0F, .src_y = 0.0F, .src_w = 1.0F, .src_h = 1.0F,
718 .out_w = source_w, .out_h = source_h });
719 auto image = dispatch_image(ctx, source_w, source_h);
720
723
724 ctx.swap_shader({
725 .shader_path = "overlay_segments.comp.spv",
726 .workgroup_size = k_wg_image,
727 .push_constant_size = sizeof(SegmentsPC),
728 });
729 ctx.set_push_constants(SegmentsPC { .count =
count, .width = source_w, .height = source_h });
730 ctx.set_output_dimensions(source_w, source_h);
731 dispatch_and_wait(ctx);
732
733 return ctx.get_output_image(0);
734}
std::optional< glm::vec3 > position