123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #include "common/utils.hpp"
- #include "nodes/base/base.hpp"
- #include "nodes/draw/drawNode.hpp"
- #include "nodes/draw/position.hpp"
- #include <opencv2/opencv.hpp>
- #include <chrono>
- #include <tuple>
- namespace GNode
- {
- const std::vector<std::pair<int, int>> coco_pairs = {
- {0, 1}, {0, 2}, {0, 11}, {0, 12}, {1, 3}, {2, 4},
- {5, 6}, {5, 7}, {7, 9}, {6, 8}, {8, 10},
- {11, 12}, {5, 11}, {6, 12},
- {11, 13}, {13, 15}, {12, 14}, {14, 16}
- };
- static std::tuple<int, int, int> getFontSize(const std::string& text)
- {
- int baseline = 0;
- cv::Size textSize = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 1.0, 2, &baseline);
- // std::cout << textSize << std::endl;
- return std::make_tuple(textSize.width, textSize.height, baseline);
- }
- static void overlay_mask(
- cv::Mat& image, const cv::Mat& smallMask,
- int roiX, int roiY,
- const cv::Scalar& color, double alpha)
- {
- if (image.empty() || smallMask.empty() ||
- image.type() != CV_8UC3 || smallMask.type() != CV_8UC1) {
- return;
- }
- alpha = std::max(0.0, std::min(1.0, alpha));
-
- cv::Rect roiRect(roiX, roiY, smallMask.cols, smallMask.rows);
-
- cv::Rect imageRect(0, 0, image.cols, image.rows);
- cv::Rect intersectionRect = roiRect & imageRect; // 使用 & 操作符计算交集
-
- if (intersectionRect.width <= 0 || intersectionRect.height <= 0) {
- return;
- }
-
- cv::Mat originalROI = image(intersectionRect); // ROI 指向 image 的数据
-
- int maskStartX = intersectionRect.x - roiX;
- int maskStartY = intersectionRect.y - roiY;
- cv::Rect maskIntersectionRect(maskStartX, maskStartY, intersectionRect.width, intersectionRect.height);
- cv::Mat smallMaskROI = smallMask(maskIntersectionRect);
-
- cv::Mat colorPatchROI(intersectionRect.size(), image.type(), color);
-
- cv::Mat tempColoredROI = originalROI.clone(); // 需要一个临时区域进行覆盖
- colorPatchROI.copyTo(tempColoredROI, smallMaskROI);
-
- cv::addWeighted(originalROI, 1.0 - alpha, tempColoredROI, alpha, 0.0, originalROI);
- }
- static std::tuple<uint8_t, uint8_t, uint8_t> hsv2bgr(float h, float s, float v)
- {
- const int h_i = static_cast<int>(h * 6);
- const float f = h * 6 - h_i;
- const float p = v * (1 - s);
- const float q = v * (1 - f * s);
- const float t = v * (1 - (1 - f) * s);
- float r, g, b;
- switch (h_i) {
- case 0:
- r = v, g = t, b = p;
- break;
- case 1:
- r = q, g = v, b = p;
- break;
- case 2:
- r = p, g = v, b = t;
- break;
- case 3:
- r = p, g = q, b = v;
- break;
- case 4:
- r = t, g = p, b = v;
- break;
- case 5:
- r = v, g = p, b = q;
- break;
- default:
- r = 1, g = 1, b = 1;
- break;
- }
- return std::make_tuple(static_cast<uint8_t>(b * 255), static_cast<uint8_t>(g * 255),
- static_cast<uint8_t>(r * 255));
- }
- static std::tuple<uint8_t, uint8_t, uint8_t> random_color(int id)
- {
- float h_plane = ((((unsigned int)id << 2) ^ 0x937151) % 100) / 100.0f;
- float s_plane = ((((unsigned int)id << 3) ^ 0x315793) % 100) / 100.0f;
- return hsv2bgr(h_plane, s_plane, 1);
- }
- void DrawNode::handle_data(std::shared_ptr<meta::MetaData>& meta_data)
- {
- cv::Mat image = meta_data->image.clone();
- int image_width = image.cols;
- int image_height = image.rows;
- PositionManager<float> pm(getFontSize);
- for (auto& box : meta_data->boxes)
- {
- uint8_t b, g, r;
- std::tie(b, g, r) = random_color(box.class_id);
- cv::rectangle(image, cv::Point(box.left, box.top), cv::Point(box.right, box.bottom), cv::Scalar(b, g, r), 2);
- std::tuple<int, int, int, int> pbox = std::make_tuple(box.left, box.top, box.right, box.bottom);
- int x, y;
- std::string text;
- if (box.class_id != -1)
- {
- text = str_format("%s %.2f id=%d", box.label.c_str(), box.score, box.class_id);
- }
- else
- {
- text = str_format("%s %.2f", box.label.c_str(), box.score);
- }
- std::tie(x, y) = pm.selectOptimalPosition(pbox, image_width, image_height, text);
-
- cv::putText(image, text, cv::Point(x, y), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(b, g, r), 2);
- if (!box.seg_mask.empty())
- {
- overlay_mask(image, box.seg_mask, box.left, box.top, cv::Scalar(b, g, r), 0.6);
- }
- if (!box.keypoints.empty())
- {
- for (const auto& point : box.keypoints)
- {
- std::tie(b, g, r) = random_color(box.class_id);
- cv::circle(image, cv::Point(point.x, point.y), 5, cv::Scalar(b, g, r), -1);
- }
- for (const auto& pair : coco_pairs)
- {
- int startIdx = pair.first;
- int endIdx = pair.second;
- if (startIdx < obj.keypoints.size() && endIdx < obj.keypoints.size())
- {
- int x1 = (int)obj.keypoints[startIdx].x;
- int y1 = (int)obj.keypoints[startIdx].y;
- int x2 = (int)obj.keypoints[endIdx].x;
- int y2 = (int)obj.keypoints[endIdx].y;
- cv::line(image, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 0, 0), 2);
- }
- }
- }
- }
- meta_data->draw_image = image;
- }
- }
|