23#include <mediapipe/framework/port/status_macros.h>
24#include <mediapipe/framework/port/opencv_core_inc.h>
25#include <mediapipe/framework/port/opencv_imgproc_inc.h>
26#include <physiology/graph/stream_and_packet_names.h>
27#include <physiology/modules/messages/metrics.h>
29#include "preprocessing_foreground_container.hpp"
30#include "preprocessing_stream_and_packet_names.hpp"
31#include <smartspectra/container/packet_helpers.hpp>
36namespace presage::smartspectra::lab {
37namespace c = container;
38namespace poller = container::output_stream_poller_wrapper;
39namespace pe = physiology::edge;
40namespace pg = preprocessing_graph;
41namespace ph = container::packet_helpers;
45 platform_independence::DeviceType TDeviceType,
46 c::settings::OperationMode TOperationMode,
47 c::settings::IntegrationMode TIntegrationMode
52 MP_RETURN_IF_ERROR(this->preprocessed_data_poller.Initialize(this->graph, pg::output_streams::kPreprocessedData));
56 (void)this->points_chest_poller.Initialize(this->graph, pg::output_streams::kPointsChest);
57 (void)this->points_abdomen_poller.Initialize(this->graph, pg::output_streams::kPointsAbdomen);
58 (void)this->points_glutes_poller.Initialize(this->graph, pg::output_streams::kPointsGlutes);
59 (void)this->points_knees_poller.Initialize(this->graph, pg::output_streams::kPointsKnees);
60 (void)this->transformed_size_poller.Initialize(this->graph, pg::output_streams::kTransformedSize);
61 return absl::OkStatus();
64template<platform_independence::DeviceType TDeviceType, container::settings::OperationMode TOperationMode, container::settings::IntegrationMode TIntegrationMode>
65PreprocessingForegroundContainer<TDeviceType, TOperationMode, TIntegrationMode>::PreprocessingForegroundContainer(
66 PreprocessingForegroundContainer::SettingsType settings
70 platform_independence::DeviceType TDeviceType,
71 c::settings::OperationMode TOperationMode,
72 c::settings::IntegrationMode TIntegrationMode
74absl::Status PreprocessingForegroundContainer<TDeviceType,
77 bool got_metrics_output;
78 nlohmann::json preprocessed_data;
79 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
80 preprocessed_data, got_metrics_output, preprocessed_data_poller.Get(), pg::output_streams::kPreprocessedData,
81 this->settings.verbosity_level > 1
83 if (got_metrics_output) {
84 MP_RETURN_IF_ERROR(this->OnPreprocessedDataOutput(preprocessed_data, frame_timestamp));
85 if (TOperationMode == c::settings::OperationMode::Spot) {
87 this->recording =
false;
88 if (this->load_video) {
89 this->keep_grabbing_frames =
false;
90 }
else if (this->settings.video_source.auto_lock &&
91 this->video_source->SupportsExposureControls()) {
92 MP_RETURN_IF_ERROR(this->video_source->TurnOnAutoExposure());
96 return absl::OkStatus();
100 platform_independence::DeviceType TDeviceType,
101 container::settings::OperationMode TOperationMode,
102 container::settings::IntegrationMode TIntegrationMode
106 return c::settings::IntegrationModeTraits<TIntegrationMode>::kPreprocessingDataFormat;
110 platform_independence::DeviceType TDeviceType,
111 container::settings::OperationMode TOperationMode,
112 container::settings::IntegrationMode TIntegrationMode
115 return "preprocessing";
119 platform_independence::DeviceType TDeviceType,
120 c::settings::OperationMode TOperationMode,
121 c::settings::IntegrationMode TIntegrationMode
125 TIntegrationMode>::DrawDebugOverlays(cv::Mat& output_frame_bgr) {
126 using ::presage::physiology::Landmarks;
131 const bool verbose = this->Base::settings.verbosity_level > 3;
132 if (!this->transformed_size.has_value()) {
133 std::pair<int, int> ts;
135 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
136 ts, size_available, this->transformed_size_poller.Get(), pg::output_streams::kTransformedSize, verbose
138 if (size_available) {
139 this->transformed_size = cv::Size(ts.first, ts.second);
143 double scale_x = 1.0, scale_y = 1.0;
144 if (this->transformed_size.has_value() && output_frame_bgr.data &&
145 this->transformed_size->width > 0 && this->transformed_size->height > 0) {
146 scale_x =
static_cast<double>(output_frame_bgr.cols) /
static_cast<double>(this->transformed_size->width);
147 scale_y =
static_cast<double>(output_frame_bgr.rows) /
static_cast<double>(this->transformed_size->height);
150 auto draw_region = [&,
this](
const Landmarks& landmarks,
const cv::Scalar& color,
const std::string& label,
double alpha) {
151 if (!output_frame_bgr.data || landmarks.value_size() == 0)
return;
152 std::vector<cv::Point> points;
153 points.reserve(landmarks.value_size());
154 for (
int i = 0; i < landmarks.value_size(); ++i) {
156 if (landmarks.value(i).x() != 0.0f){
157 int x = cvRound(landmarks.value(i).x() * scale_x);
158 int y = cvRound(landmarks.value(i).y() * scale_y);
159 points.emplace_back(cv::Point(x, y));
162 for (
const auto& point : points) {
163 cv::circle(output_frame_bgr, point, 3, color, cv::FILLED);
165 if (points.size() >= 3) {
166 std::vector<cv::Point> hull;
167 cv::convexHull(points, hull);
168 cv::Mat mask = cv::Mat::zeros(output_frame_bgr.size(), CV_8UC1);
169 std::vector<std::vector<cv::Point>> hulls = {hull};
170 cv::fillPoly(mask, hulls, cv::Scalar(255));
172 cv::cvtColor(mask, color_mask, cv::COLOR_GRAY2BGR);
173 color_mask.setTo(color, mask);
174 cv::addWeighted(color_mask, alpha, output_frame_bgr, 1.0 - alpha, 0, output_frame_bgr);
176 const int thickness = 2;
177 cv::polylines(output_frame_bgr, hulls,
true, color, thickness);
179 cv::Point2d centroid(0, 0);
181 if (hull.size() > 0){
182 for(
const auto& point : hull){
183 centroid.x += point.x;
184 centroid.y += point.y;
186 centroid.x /=
static_cast<double>(hull.size());
187 centroid.y /=
static_cast<double>(hull.size());
189 cv::putText(output_frame_bgr, label, cv::Point(
static_cast<int>(centroid.x),
static_cast<int>(centroid.y)),
190 cv::FONT_HERSHEY_SIMPLEX, 0.5, color, 1, cv::LINE_AA);
194 auto draw_if_available = [&](
auto& poller,
195 const char* stream_name,
197 const cv::Scalar& color,
198 double alpha) -> absl::Status {
199 Landmarks region_points;
201 MP_RETURN_IF_ERROR(ph::GetPacketContentsIfAny(
202 region_points, available, poller.Get(), stream_name, verbose
204 if (available) draw_region(region_points, color, label, alpha);
205 return absl::OkStatus();
208 MP_RETURN_IF_ERROR(draw_if_available(this->points_chest_poller, pg::output_streams::kPointsChest,
"chest", cv::Scalar(0, 0, 255), 0.30));
209 MP_RETURN_IF_ERROR(draw_if_available(this->points_abdomen_poller, pg::output_streams::kPointsAbdomen,
"abdomen", cv::Scalar(0, 255, 0), 0.25));
210 MP_RETURN_IF_ERROR(draw_if_available(this->points_glutes_poller, pg::output_streams::kPointsGlutes,
"glutes", cv::Scalar(255, 0, 0), 0.20));
211 MP_RETURN_IF_ERROR(draw_if_available(this->points_knees_poller, pg::output_streams::kPointsKnees,
"knees", cv::Scalar(0, 255, 255), 0.20));
213 return absl::OkStatus();
Definition preprocessing_foreground_container.hpp:38
absl::Status HandleOutputData(int64_t frame_timestamp) override
Definition preprocessing_foreground_container_impl.hpp:76
std::string GetGraphFilePrefix() const override
Definition preprocessing_foreground_container_impl.hpp:114
std::string GetThirdGraphFileSuffix() const override
Definition preprocessing_foreground_container_impl.hpp:104
absl::Status InitializeOutputDataPollers() override
Definition preprocessing_foreground_container_impl.hpp:51
Definition background_container.cpp:10