#include "common/utils.hpp" #include "nodes/base/base.hpp" #include "nodes/draw/drawNode.hpp" #include "nodes/draw/position.hpp" #include #include #include namespace GNode { const std::vector> 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 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 hsv2bgr(float h, float s, float v) { const int h_i = static_cast(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(b * 255), static_cast(g * 255), static_cast(r * 255)); } static std::tuple 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_data) { cv::Mat image = meta_data->image.clone(); int image_width = image.cols; int image_height = image.rows; PositionManager 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 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; } }