12 #include <opencv2/core/core.hpp>
18 explicit GridMat(
const std::vector<cv::Size>& sizes,
const cv::Size maxDisp = cv::Size{1920, 1080}) {
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));
25 if (0 == maxWidth || 0 == maxHeight) {
26 throw std::invalid_argument(
"Input resolution must not be zero.");
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);
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));
38 cellSize.width =
static_cast<int>(maxWidth * scaleFactor);
39 cellSize.height =
static_cast<int>(maxHeight * scaleFactor);
41 for (
size_t i = 0; i < sizes.size(); i++) {
43 p.x = cellSize.width * (i % nGridCols);
44 p.y = cellSize.height * (i / nGridCols);
48 outimg.create(cellSize.height * nGridRows, cellSize.width * nGridCols, CV_8UC3);
53 cv::Size getCellSize() {
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");
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));
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)));
70 cv::resize(frames[i], cell, cellSize);
73 unupdatedSourceIDs.clear();
76 void update(
const cv::Mat& frame,
const size_t sourceID) {
77 const cv::Mat& cell = outimg(cv::Rect(points[sourceID], cellSize));
79 if ((cellSize.width == frame.cols) && (cellSize.height == frame.rows)) {
81 }
else if ((cellSize.width > frame.cols) && (cellSize.height > frame.rows)) {
82 frame.copyTo(cell(cv::Rect(0, 0, frame.cols, frame.rows)));
84 cv::resize(frame, cell, cellSize);
86 unupdatedSourceIDs.erase(unupdatedSourceIDs.find(sourceID));
89 bool isFilled()
const noexcept {
90 return unupdatedSourceIDs.empty();
94 std::generate_n(std::inserter(unupdatedSourceIDs, unupdatedSourceIDs.end()), points.size(), [&counter]{return counter++;});
96 std::set<size_t> getUnupdatedSourceIDs()
const noexcept {
97 return unupdatedSourceIDs;
99 cv::Mat getMat()
const noexcept {
105 std::set<size_t> unupdatedSourceIDs;
106 std::vector<cv::Point> points;
109 void fillROIColor(cv::Mat& displayImage, cv::Rect roi, cv::Scalar color,
double opacity) {
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);
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) {
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)),
126 cv::putText(displayImage, str, p, font, fontScale, color, thickness);
Definition: grid_mat.hpp:14