OpenCV 中文汉字显示

本文介绍了一个用于OpenCV的汉字输出接口——CvxText类。该类利用FreeType库支持中文显示,提供了设置字体、输出文字等功能。示例展示了如何使用CvxText在图像上输出中文。
//====================================================================
//====================================================================
//
// 文件: CvxText.h
//
// 说明: OpenCV汉字输出
//
// 时间:
//
// 作者: 柴树杉
//       chaishushan#gmail.com
//       chaishushan.googlepages.com
//
//====================================================================
//====================================================================

#ifndef OPENCV_CVX_TEXT_2007_08_31_H
#define OPENCV_CVX_TEXT_2007_08_31_H

/**
* \file CvxText.h
* \brief OpenCV汉字输出接口
*
* 实现了汉字输出功能。
*/

#include <ft2build.h>
#include FT_FREETYPE_H

#include <cv.h>
#include <highgui.h>

/**
* \class CvxText
* \brief OpenCV中输出汉字
*
* OpenCV中输出汉字。字库提取采用了开源的FreeFype库。由于FreeFype是
* GPL版权发布的库,和OpenCV版权并不一致,因此目前还没有合并到OpenCV
* 扩展库中。
*
* 显示汉字的时候需要一个汉字字库文件,字库文件系统一般都自带了。
* 这里采用的是一个开源的字库:“文泉驿正黑体”。
*
* 关于"OpenCV扩展库"的细节请访问
* http://code.google.com/p/opencv-extension-library/
*
* 关于FreeType的细节请访问
* http://www.freetype.org/
*
* 例子:
*
* \code
int main(int argc, char *argv[])
{
   // 定义CvxApplication对象

   CvxApplication app(argc, argv);

   // 打开一个影象

   IplImage *img = cvLoadImage("test.jpg", 1);

   // 输出汉字

   {
      // "wqy-zenhei.ttf"为文泉驿正黑体

      CvText text("wqy-zenhei.ttf");

      const char *msg = "在OpenCV中输出汉字!";

      float p = 0.5;
      text.setFont(NULL, NULL, NULL, &p);   // 透明处理

      text.putText(img, msg, cvPoint(100, 150), CV_RGB(255,0,0));
   }
   // 定义窗口,并显示影象

   CvxWindow myWin("myWin");
   myWin.showImage(img);

   // 进入消息循环

   return app.exec();
}
* \endcode
*/

class CvxText
{
   // 禁止copy

   CvxText& operator=(const CvxText&);

   //================================================================
   //================================================================

public:

   /**
    * 装载字库文件
    */

   CvxText(const char *freeType);
   virtual ~CvxText();

   //================================================================
   //================================================================

   /**
    * 获取字体。目前有些参数尚不支持。
    *
    * \param font        字体类型, 目前不支持
    * \param size        字体大小/空白比例/间隔比例/旋转角度
    * \param underline   下画线
    * \param diaphaneity 透明度
    *
    * \sa setFont, restoreFont
    */

   void getFont(int *type,
      CvScalar *size=NULL, bool *underline=NULL, float *diaphaneity=NULL);

   /**
    * 设置字体。目前有些参数尚不支持。
    *
    * \param font        字体类型, 目前不支持
    * \param size        字体大小/空白比例/间隔比例/旋转角度
    * \param underline   下画线
    * \param diaphaneity 透明度
    *
    * \sa getFont, restoreFont
    */

   void setFont(int *type,
      CvScalar *size=NULL, bool *underline=NULL, float *diaphaneity=NULL);

   /**
    * 恢复原始的字体设置。
    *
    * \sa getFont, setFont
    */

   void restoreFont();

   //================================================================
   //================================================================

   /**
    * 输出汉字(颜色默认为黑色)。遇到不能输出的字符将停止。
    *
    * \param img  输出的影象
    * \param text 文本内容
    * \param pos  文本位置
    *
    * \return 返回成功输出的字符长度,失败返回-1。
    */

   int putText(IplImage *img, const char    *text, CvPoint pos);

   /**
    * 输出汉字(颜色默认为黑色)。遇到不能输出的字符将停止。
    *
    * \param img  输出的影象
    * \param text 文本内容
    * \param pos  文本位置
    *
    * \return 返回成功输出的字符长度,失败返回-1。
    */

   int putText(IplImage *img, const wchar_t *text, CvPoint pos);

   /**
    * 输出汉字。遇到不能输出的字符将停止。
    *
    * \param img   输出的影象
    * \param text  文本内容
    * \param pos   文本位置
    * \param color 文本颜色
    *
    * \return 返回成功输出的字符长度,失败返回-1。
    */

   int putText(IplImage *img, const char    *text, CvPoint pos, CvScalar color);

   /**
    * 输出汉字。遇到不能输出的字符将停止。
    *
    * \param img   输出的影象
    * \param text  文本内容
    * \param pos   文本位置
    * \param color 文本颜色
    *
    * \return 返回成功输出的字符长度,失败返回-1。
    */
   int putText(IplImage *img, const wchar_t *text, CvPoint pos, CvScalar color);

   //================================================================
   //================================================================

private:

   // 输出当前字符, 更新m_pos位置

   void putWChar(IplImage *img, wchar_t wc, CvPoint &pos, CvScalar color);

   //================================================================
   //================================================================

private:

   FT_Library   m_library;   // 字库
   FT_Face      m_face;      // 字体

   //================================================================
   //================================================================

   // 默认的字体输出参数

   int         m_fontType;
   CvScalar   m_fontSize;
   bool      m_fontUnderline;
   float      m_fontDiaphaneity;

   //================================================================
   //================================================================
};

#endif // OPENCV_CVX_TEXT_2007_08_31_H
### OpenCV 显示中文汉字的解决方案 在使用 OpenCV 进行图像处理时,显示中文字符是一个常见的需求。然而,OpenCV 原生并不支持直接渲染中文字符,因此需要借助其他方法来实现这一功能。 以下是几种常见且有效的解决方案: #### 方案一:利用 FreeType 库绘制中文 FreeType 是一个开源字体引擎库,可以用来解析 TrueType 字体文件并将其渲染到图像上。这种方法不需要修改 OpenCV 的核心代码,仅需加载字体文件并通过 FreeType 渲染文字到图片中[^1]。 具体实现如下: ```cpp #include <ft2build.h> #include FT_FREETYPE_H #include <opencv2/opencv.hpp> void drawText(cv::Mat &img, const std::string &text, cv::Point pos, const char *fontPath, double fontSize, cv::Scalar color) { FT_Library ft; if (FT_Init_FreeType(&ft)) { throw "Could not init FreeType Library"; } FT_Face face; if (FT_New_Face(ft, fontPath, 0, &face)) { throw "Could not open font"; } FT_Set_Pixel_Sizes(face, 0, static_cast<FT_UInt>(fontSize)); for (size_t i = 0; i < text.length(); ++i) { if (FT_Load_Char(face, text[i], FT_LOAD_RENDER)) { continue; } auto bitmap = face->glyph->bitmap; int x = pos.x + face->glyph->bitmap_left; int y = pos.y - face->glyph->bitmap_top; for (int j = 0; j < bitmap.rows; ++j) { for (int k = 0; k < bitmap.width; ++k) { if ((y + j >= 0 && y + j < img.rows) && (x + k >= 0 && x + k < img.cols)) { img.at<cv::Vec3b>(y + j, x + k)[0] = static_cast<unsigned char>(color[0] * (bitmap.buffer[j * bitmap.width + k]) / 255); img.at<cv::Vec3b>(y + j, x + k)[1] = static_cast<unsigned char>(color[1] * (bitmap.buffer[j * bitmap.width + k]) / 255); img.at<cv::Vec3b>(y + j, x + k)[2] = static_cast<unsigned char>(color[2] * (bitmap.buffer[j * bitmap.width + k]) / 255); } } } pos.x += face->glyph->advance.x >> 6; } FT_Done_Face(face); FT_Done_FreeType(ft); } ``` 此函数接受一张 `cv::Mat` 图像作为输入,在指定位置绘制中文字符串。需要注意的是,必须提供一个 `.ttf` 或 `.otf` 格式的字体文件路径[^1]。 --- #### 方案二:基于 PIL 和 Matplotlib 绘制中文 对于 Python 用户而言,PIL(Python Imaging Library)和 Matplotlib 提供了更简单的接口用于绘制中文。虽然这不是纯 OpenCV 实现的方式,但它非常方便快捷[^2]。 示例代码如下: ```python from PIL import ImageFont, ImageDraw, Image import numpy as np import cv2 def put_chinese_text(image, text, position, font_path, font_size=20, color=(255, 255, 255)): pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(pil_image) font = ImageFont.truetype(font_path, font_size) draw.text(position, text, fill=color, font=font) image_with_text = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR) return image_with_text # 使用示例 image = np.zeros((200, 400, 3), dtype=np.uint8) result = put_chinese_text(image, "你好世界", (50, 50), "./simhei.ttf") cv2.imshow("Result", result) cv2.waitKey(0) ``` 在此方案中,用户需要准备一份支持中文的 TTF 字体文件(如 SimHei)。通过这种方式,可以直接将中文文本叠加到图像上[^2]。 --- #### 方案三:使用 OpenCVC 工具包 OpenCVC 是专门为解决 OpenCV 中文显示问题设计的一个工具包。它提供了简单易用的 API 接口,允许开发者快速集成中文显示功能而不依赖任何外部库[^3]。 安装方式: ```bash git clone https://gitcode.com/Universal-Tool/cbd91.git cd cbd91 cmake . make sudo make install ``` 调用示例: ```cpp #include "opencvc/opencvc.h" using namespace opencvc; int main() { cv::Mat img = cv::imread("example.jpg"); ChineseDrawer drawer(img); drawer.drawText("你好,世界!", cv::Point(50, 50), "./fonts/simhei.ttf", 24, cv::Scalar(255, 255, 255)); cv::imshow("Chinese Text Example", img); cv::waitKey(0); return 0; } ``` 该工具包内置了对多种常用字体的支持,并优化了性能表现,适合大规模生产环境下的应用[^3]。 --- ### 总结 以上三种方法分别适用于不同的场景和技术栈。如果希望完全控制底层逻辑,则推荐 **方案一**;如果是 Python 开发者,可以选择更加便捷的 **方案二**;而对于追求高效性和稳定性的 C++ 开发者来说,**方案三** 将是最优解之一。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值