#include "vp_mllm_osd_node.h" #ifdef VP_WITH_LLM namespace vp_nodes { vp_mllm_osd_node::vp_mllm_osd_node(std::string node_name, std::string font): vp_node(node_name) { ft2 = cv::freetype::createFreeType2(); ft2->loadFontData(font, 0); this->initialized(); } vp_mllm_osd_node::~vp_mllm_osd_node() { deinitialized(); } std::shared_ptr vp_mllm_osd_node::handle_frame_meta(std::shared_ptr meta) { if (meta->description.empty()) { return meta; } // operations on osd_frame if (meta->osd_frame.empty()) { // add a gap at the bottom of osd frame meta->osd_frame = cv::Mat(meta->frame.rows + gap_height + padding * 2, meta->frame.cols, meta->frame.type(), cv::Scalar(128, 128, 128)); // initialize by copying frame to osd frame auto roi = meta->osd_frame(cv::Rect(0, 0, meta->frame.cols, meta->frame.rows)); meta->frame.copyTo(roi); } auto& canvas = meta->osd_frame; //ft2->putText(canvas, meta->description, cv::Point(10, meta->frame.rows + gap_height + padding * 2), 20, cv::Scalar(255, 0, 0), cv::FILLED, cv::LINE_AA, true); draw_text_in_rect(canvas, meta->description, cv::Rect(5, meta->frame.rows + 5, meta->frame.cols - 10, gap_height + padding * 2 - 10), 20, cv::Scalar(255, 0, 0)); // log using INFO level VP_INFO(vp_utils::string_format("[%s] [%s]", node_name.c_str(), meta->description.c_str())); return meta; } std::vector vp_mllm_osd_node::utf8_split(const std::string& text) { std::vector chars; for (size_t i = 0; i < text.size();) { unsigned char c = text[i]; size_t len = 1; if ((c & 0x80) == 0x00) len = 1; // ASCII else if ((c & 0xE0) == 0xC0) len = 2; // 2bytes else if ((c & 0xF0) == 0xE0) len = 3; // 3bytes else if ((c & 0xF8) == 0xF0) len = 4; // 4bytes chars.push_back(text.substr(i, len)); i += len; } return chars; } void vp_mllm_osd_node::draw_text_in_rect(cv::Mat& img, const std::string& text, const cv::Rect& rect, int fontHeight, cv::Scalar color) { std::vector chars = utf8_split(text); std::string currentLine; int baseline = 0; int y = rect.y; for (size_t i = 0; i < chars.size(); i++) { std::string tempLine = currentLine + chars[i]; cv::Size textSize = ft2->getTextSize(tempLine, fontHeight, -1, &baseline); if (textSize.width > rect.width && !currentLine.empty()) { int drawY = y + textSize.height; if (drawY > rect.y + rect.height) break; ft2->putText(img, currentLine, cv::Point(rect.x, drawY), fontHeight, color, -1, 8, true); y += textSize.height + 5; currentLine.clear(); } currentLine += chars[i]; } if (!currentLine.empty()) { int drawY = y + ft2->getTextSize(currentLine, fontHeight, -1, &baseline).height; if (drawY <= rect.y + rect.height) { ft2->putText(img, currentLine, cv::Point(rect.x, drawY), fontHeight, color, -1, 8, true); } } } } #endif