You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV中cv::putText不支持中日文字符叠加图片,求可行解决方案

OpenCV cv::putText显示中文/日文的解决办法

OpenCV自带的cv::putText仅支持ASCII字符,无法正确渲染中文、日文等Unicode字符,会出现??????这类乱码。以下是几种可行的解决办法:

方案1:使用FreeType库实现Unicode文本渲染

通过FreeType库加载系统中的中文字体(如SimSun、Noto Sans CJK SC等),自定义文本渲染逻辑,直接将Unicode字符绘制到OpenCV图像上。

实现步骤与代码示例

  1. 确保项目链接FreeType库(需提前安装FreeType开发包)
  2. 编写自定义渲染函数:
#include <opencv2/opencv.hpp>
#include <ft2build.h>
#include FT_FREETYPE_H

void putTextUnicode(cv::Mat& img, const std::wstring& text, cv::Point pos, 
                    const std::string& fontPath, double fontSize, cv::Scalar color) {
    FT_Library ft;
    if (FT_Init_FreeType(&ft)) {
        std::cerr << "FreeType初始化失败" << std::endl;
        return;
    }

    FT_Face face;
    if (FT_New_Face(ft, fontPath.c_str(), 0, &face)) {
        std::cerr << "加载字体文件失败,请检查路径是否正确" << std::endl;
        FT_Done_FreeType(ft);
        return;
    }

    // 设置字体像素大小,数值需根据fontSize调整
    FT_Set_Pixel_Sizes(face, 0, static_cast<int>(fontSize * 20));

    int currX = pos.x;
    int currY = pos.y;

    for (const wchar_t c : text) {
        if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
            std::cerr << "字符渲染失败: " << c << std::endl;
            continue;
        }

        FT_GlyphSlot slot = face->glyph;
        // 将FreeType生成的灰度位图转为OpenCV Mat
        cv::Mat glyphMat(cv::Size(slot->bitmap.width, slot->bitmap.rows), CV_8UC1, slot->bitmap.buffer);

        // 调整绘制位置(FreeType原点在字符左下角,OpenCV在图像左上角)
        cv::Point glyphPos(currX, currY - slot->bitmap_top);
        // 检查是否超出图像边界
        if (glyphPos.y < 0 || glyphPos.y + glyphMat.rows > img.rows ||
            glyphPos.x < 0 || glyphPos.x + glyphMat.cols > img.cols) {
            currX += slot->advance.x >> 6; // 移动到下一个字符位置(单位:1/64像素)
            continue;
        }

        // 将灰度位图叠加到彩色图像上,保留透明度
        for (int i = 0; i < glyphMat.rows; ++i) {
            for (int j = 0; j < glyphMat.cols; ++j) {
                uchar alpha = glyphMat.at<uchar>(i, j);
                if (alpha > 0) {
                    img.at<cv::Vec3b>(glyphPos.y + i, glyphPos.x + j) = 
                        cv::Vec3b(color[0], color[1], color[2]);
                }
            }
        }

        currX += slot->advance.x >> 6;
    }

    FT_Done_Face(face);
    FT_Done_FreeType(ft);
}

// 使用示例
int main() {
    cv::Mat img = cv::Mat::zeros(400, 600, CV_8UC3);
    // 宽字符串存储Unicode文本
    std::wstring text = L"你好世界 こんにちは";
    // 替换为你的系统字体路径(Windows下通常为C:/Windows/Fonts/simsun.ttc)
    putTextUnicode(img, text, cv::Point(20, 200), "simsun.ttc", 1.5, cv::Scalar(118, 185, 0));
    
    cv::imshow("Unicode Text Render", img);
    cv::waitKey(0);
    return 0;
}

方案2:借助Qt框架完成文本渲染

如果项目已集成Qt,可以将OpenCV的Mat转换为Qt的QImage,利用QPainter的成熟文本渲染能力绘制Unicode字符,再转回Mat格式。

代码示例

#include <opencv2/opencv.hpp>
#include <QImage>
#include <QPainter>
#include <QFont>

cv::Mat putTextWithQt(cv::Mat& srcImg, const QString& text, cv::Point pos, 
                      const QString& fontName, double fontSize, cv::Scalar color) {
    // 将OpenCV BGR格式转为Qt的BGR888格式
    QImage qImg(srcImg.data, srcImg.cols, srcImg.rows, srcImg.step, QImage::Format_BGR888);
    QPainter painter(&qImg);

    // 设置字体参数
    QFont font(fontName);
    font.setPointSizeF(fontSize * 12);
    painter.setFont(font);
    painter.setPen(QColor(color[0], color[1], color[2]));

    // 绘制文本(Qt的drawText原点在字符基线,需注意位置调整)
    painter.drawText(pos.x, pos.y, text);

    // 将QImage转回OpenCV Mat
    cv::Mat result(srcImg.rows, srcImg.cols, CV_8UC3, qImg.bits(), qImg.bytesPerLine());
    return result.clone();
}

// 使用示例
int main() {
    cv::Mat img = cv::Mat::zeros(400, 600, CV_8UC3);
    QString text = "你好世界 こんにちは";
    cv::Mat imgWithText = putTextWithQt(img, text, cv::Point(20, 200), "SimSun", 1.5, cv::Scalar(118, 185, 0));
    
    cv::imshow("Qt Text Render", imgWithText);
    cv::waitKey(0);
    return 0;
}

方案3:预渲染文本为图像再叠加

对于固定文本场景,可先用第三方工具(如系统绘图软件)将需要显示的中文/日文保存为图像,再通过OpenCV的cv::imread读取图像,用cv::copyTo或cv::addWeighted叠加到目标图像上。这种方式无需额外依赖库,但灵活性较低,仅适合文本固定的场景。

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:54:53