plugin  0.1.0
grid_mat.hpp
1 // Copyright (C) 2018-2024 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 
5 #pragma once
6 
7 #include <algorithm>
8 #include <set>
9 #include <string>
10 #include <vector>
11 
12 #include <opencv2/core/core.hpp>
13 
14 class GridMat {
15 public:
16  cv::Mat outimg;
17 
18  explicit GridMat(const std::vector<cv::Size>& sizes, const cv::Size maxDisp = cv::Size{1920, 1080}) {
19  size_t maxWidth = 0;
20  size_t maxHeight = 0;
21  for (size_t i = 0; i < sizes.size(); i++) {
22  maxWidth = std::max(maxWidth, static_cast<size_t>(sizes[i].width));
23  maxHeight = std::max(maxHeight, static_cast<size_t>(sizes[i].height));
24  }
25  if (0 == maxWidth || 0 == maxHeight) {
26  throw std::invalid_argument("Input resolution must not be zero.");
27  }
28 
29  size_t nGridCols = static_cast<size_t>(ceil(sqrt(static_cast<float>(sizes.size()))));
30  size_t nGridRows = (sizes.size() - 1) / nGridCols + 1;
31  size_t gridMaxWidth = static_cast<size_t>(maxDisp.width/nGridCols);
32  size_t gridMaxHeight = static_cast<size_t>(maxDisp.height/nGridRows);
33 
34  float scaleWidth = static_cast<float>(gridMaxWidth) / maxWidth;
35  float scaleHeight = static_cast<float>(gridMaxHeight) / maxHeight;
36  float scaleFactor = std::min(1.f, std::min(scaleWidth, scaleHeight));
37 
38  cellSize.width = static_cast<int>(maxWidth * scaleFactor);
39  cellSize.height = static_cast<int>(maxHeight * scaleFactor);
40 
41  for (size_t i = 0; i < sizes.size(); i++) {
42  cv::Point p;
43  p.x = cellSize.width * (i % nGridCols);
44  p.y = cellSize.height * (i / nGridCols);
45  points.push_back(p);
46  }
47 
48  outimg.create(cellSize.height * nGridRows, cellSize.width * nGridCols, CV_8UC3);
49  outimg.setTo(0);
50  clear();
51  }
52 
53  cv::Size getCellSize() {
54  return cellSize;
55  }
56 
57  void fill(std::vector<cv::Mat>& frames) {
58  if (frames.size() > points.size()) {
59  throw std::logic_error("Cannot display " + std::to_string(frames.size()) + " channels in a grid with " + std::to_string(points.size()) + " cells");
60  }
61 
62  for (size_t i = 0; i < frames.size(); i++) {
63  cv::Mat cell = outimg(cv::Rect(points[i].x, points[i].y, cellSize.width, cellSize.height));
64 
65  if ((cellSize.width == frames[i].cols) && (cellSize.height == frames[i].rows)) {
66  frames[i].copyTo(cell);
67  } else if ((cellSize.width > frames[i].cols) && (cellSize.height > frames[i].rows)) {
68  frames[i].copyTo(cell(cv::Rect(0, 0, frames[i].cols, frames[i].rows)));
69  } else {
70  cv::resize(frames[i], cell, cellSize);
71  }
72  }
73  unupdatedSourceIDs.clear();
74  }
75 
76  void update(const cv::Mat& frame, const size_t sourceID) {
77  const cv::Mat& cell = outimg(cv::Rect(points[sourceID], cellSize));
78 
79  if ((cellSize.width == frame.cols) && (cellSize.height == frame.rows)) {
80  frame.copyTo(cell);
81  } else if ((cellSize.width > frame.cols) && (cellSize.height > frame.rows)) {
82  frame.copyTo(cell(cv::Rect(0, 0, frame.cols, frame.rows)));
83  } else {
84  cv::resize(frame, cell, cellSize);
85  }
86  unupdatedSourceIDs.erase(unupdatedSourceIDs.find(sourceID));
87  }
88 
89  bool isFilled() const noexcept {
90  return unupdatedSourceIDs.empty();
91  }
92  void clear() {
93  size_t counter = 0;
94  std::generate_n(std::inserter(unupdatedSourceIDs, unupdatedSourceIDs.end()), points.size(), [&counter]{return counter++;});
95  }
96  std::set<size_t> getUnupdatedSourceIDs() const noexcept {
97  return unupdatedSourceIDs;
98  }
99  cv::Mat getMat() const noexcept {
100  return outimg;
101  }
102 
103 private:
104  cv::Size cellSize;
105  std::set<size_t> unupdatedSourceIDs;
106  std::vector<cv::Point> points;
107 };
108 
109 void fillROIColor(cv::Mat& displayImage, cv::Rect roi, cv::Scalar color, double opacity) {
110  if (opacity > 0) {
111  roi = roi & cv::Rect(0, 0, displayImage.cols, displayImage.rows);
112  cv::Mat textROI = displayImage(roi);
113  cv::addWeighted(color, opacity, textROI, 1.0 - opacity , 0.0, textROI);
114  }
115 }
116 
117 void putTextOnImage(cv::Mat& displayImage, std::string str, cv::Point p,
118  cv::HersheyFonts font, double fontScale, cv::Scalar color,
119  int thickness = 1, cv::Scalar bgcolor = cv::Scalar(),
120  double opacity = 0) {
121  int baseline = 0;
122  cv::Size textSize = cv::getTextSize(str, font, 0.5, 1, &baseline);
123  fillROIColor(displayImage, cv::Rect(cv::Point(p.x, p.y + baseline),
124  cv::Point(p.x + textSize.width, p.y - textSize.height)),
125  bgcolor, opacity);
126  cv::putText(displayImage, str, p, font, fontScale, color, thickness);
127 }
Definition: grid_mat.hpp:14