OpenCV 使用 FreeType 给图片添加中文水印

8

title: OpenCV 使用 FreeType 给图片添加中文水印
url: opencv-freetype-add-chinese-watermark
date: 2024年04月08日
category: C++
tags:

  • OpenCV

OpenCV 使用 FreeType 给图片添加中文水印

Opencv 的 putText 函数只能添加英文,如果添加中文,会显示乱码,这里介绍一种使用 freetype 添加中文水印的方法。

下载 freetype-2.13.2.tar.gz,下载地址: https://download.savannah.gnu.org/releases/freetype/

源码中自带 VS2010 项目,VS2010 以及更新版本的 VS 都可以打开编译,项目目录 \freetype-2.13.2\builds\windows\vc2010

默认可以生成 debug 版本和 release 的动态、静态库,拷贝 include 文件夹和生成的库到 cpp 项目中。

确保本机安装了 opencv 并配置好了环境变量

#include <string>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

std::wstring string_to_wstring(const std::string& str)
{
    std::string strUtf8 = str;
    setlocale(LC_ALL, "en_US.UTF-8");
    const char* chSrc = strUtf8.c_str();
    size_t nStr = mbstowcs(NULL, chSrc, 0) + 1;
    wchar_t* wchDest = new wchar_t[nStr];
    memset(wchDest, 0, nStr);
    mbstowcs(wchDest, chSrc, nStr);
    std::wstring wStrRes = wchDest;
    delete[] wchDest;
    return wStrRes;
}


void put_zh_text(string text)
{
    // 初始化 FreeType 库 
    FT_Library library;
    if (FT_Init_FreeType(&library))
    {
        std::cerr << "Could not init freetype library\n";
        return;
    }

    // 加载字体 
    FT_Face face;
    if (FT_New_Face(library, "C:\\Users\\yinnan\\Downloads\\SimSun.ttf", 0, &face))
    {
        std::cerr << "Could not open font\n";
        return;
    }

    // 设置字体大小 
    FT_Set_Pixel_Sizes(face, 0, 32);

    cv::Mat frame = cv::imread(R"(C:\Users\yinnan\Pictures\Saved Pictures\test.png)");


    // 将图片转换为 4 通道的图像 
    cv::Mat img;
    cv::cvtColor(frame, img, cv::COLOR_BGR2BGRA);

    auto ws = string_to_wstring(text);

    // 设置水印的起始位置 
    int startX = 100; // 水印在图片上的起始 X 坐标 
    int startY = 100; // 水印在图片上的起始 Y 坐标 

    // 设置文字颜色 不透明 
    cv::Vec4b textColor(255, 255, 255, 255);

    // 遍历每个字符 
    for (auto& c : ws)
    {
        // 加载字符的字形 
        if (FT_Load_Char(face, c, FT_LOAD_RENDER))
        {
            std::wcerr << "Could not load character " << c << '\n';
            continue;
        }

        // 将字符的位图添加到图片上 
        for (int i = 0; i < face->glyph->bitmap.rows; i++)
        {
            for (int j = 0; j < face->glyph->bitmap.width; j++)
            {
                // 计算字符在图片上的位置 
                int x = startX + j + face->glyph->bitmap_left;
                int y = startY + i - face->glyph->bitmap_top;

                // 将字符的位图添加到图片上 
                if (x >= 0 && x < img.cols && y >= 0 && y < img.rows)
                {
                    // 设置文字颜色 
                    if (face->glyph->bitmap.buffer [i * face->glyph->bitmap.width + j] > 0)
                    {
                        img.at<cv::Vec4b>(y, x) = textColor;
                    }
                }
            }
        }

        // 更新起始 X 坐标,为下一个字符留出空间 
        startX += face->glyph->advance.x >> 6;
    }

    // 如果要将添加水印后的图片通过 VideoWriter 推流,需要转成 3 通道图片 
    /*Mat res;
    cv::cvtColor (img, res, cv::COLOR_BGRA2BGR, 3);*/

    cv::imwrite("zh-img.png", img);

    // 释放 FreeType 资源 
    FT_Done_Face(face);
    FT_Done_FreeType(library);

}


int main()
{
    std::cout << cv::getBuildInformation() << std::endl;
    put_zh_text(" 测试中文 & quot;);
    return 0;
}

源码下载: https://timetick.lanzout.com/iEpUu18ot3ne 密码:6sgc