OpenCV 使用 FreeType 给图片添加中文水印
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