首页 > 编程语言 >c++中添加显示字体为中文

c++中添加显示字体为中文

时间:2024-07-05 11:33:41浏览次数:10  
标签:中文 val img int text pos c++ 字体 cv

sudo apt-get install libfreetype6-dev

安装上面的东西

然后创建一个cmake同级下创建一个cvxtext文件夹

并且创建cvxtext.h

#ifndef OPENCV_CVX_TEXT_HPP_
#define OPENCV_CVX_TEXT_HPP_

#include <freetype2/ft2build.h>
#include FT_FREETYPE_H

#include <opencv2/opencv.hpp>

namespace xt {

class CvxText {
  public:
    /**
     * 装载字库文件
     */
    CvxText(const char* freeType);
    virtual ~CvxText();

    /**
     * 获取字体.目前有些参数尚不支持.
     *
     * \param font        字体类型, 目前不支持
     * \param size        字体大小/空白比例/间隔比例/旋转角度
     * \param underline   下画线
     * \param diaphaneity 透明度
     *
     * \sa setFont, restoreFont
     */
    void getFont(int* type, cv::Scalar* size = nullptr, bool* underline = nullptr, float* diaphaneity = nullptr);

    /**
     * 设置字体.目前有些参数尚不支持.
     *
     * \param font        字体类型, 目前不支持
     * \param size        字体大小/空白比例/间隔比例/旋转角度
     * \param underline   下画线
     * \param diaphaneity 透明度
     *
     * \sa getFont, restoreFont
     */
    void setFont(int* type, cv::Scalar* size = nullptr, bool* underline = nullptr, float* diaphaneity = nullptr);

    /**
     * 恢复原始的字体设置.
     *
     * \sa getFont, setFont
     */
    void restoreFont();

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

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

    /**
     * 输出汉字.遇到不能输出的字符将停止.
     *
     * \param img   输出的影象
     * \param text  文本内容
     * \param pos   文本位置
     * \param color 文本颜色
     *
     * \return 返回成功输出的字符长度,失败返回-1.
     */
    int putText(cv::Mat& img, const char* text, cv::Point pos, cv::Scalar color);

    /**
     * 输出汉字.遇到不能输出的字符将停止.
     *
     * \param img   输出的影象
     * \param text  文本内容
     * \param pos   文本位置
     * \param color 文本颜色
     *
     * \return 返回成功输出的字符长度,失败返回-1.
     */
    int putText(cv::Mat& img, const wchar_t* text, cv::Point pos, cv::Scalar color);
    int toWchar(char* src, wchar_t*& dest, const char* locale = "zh_CN.utf8");

  private:
    // 禁止copy
    CvxText& operator=(const CvxText&);
    // 输出当前字符, 更新m_pos位置
    void putWChar(cv::Mat& img, wchar_t wc, cv::Point& pos, cv::Scalar color);

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

    // 默认的字体输出参数
    int m_fontType;
    cv::Scalar m_fontSize;
    bool m_fontUnderline;
    float m_fontDiaphaneity;
};
}  // namespace xt

#endif  // OPENCV_CVX_TEXT_HPP_
View Code

cvxtext.cc

#include "cvxtext.h"

#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <wchar.h>

#include <cmath>

namespace xt {

// 打开字库
CvxText::CvxText(const char *freeType) {
  assert(freeType != NULL);

  // 打开字库文件, 创建一个字体
  if (FT_Init_FreeType(&m_library))
    throw;
  if (FT_New_Face(m_library, freeType, 0, &m_face))
    throw;

  // 设置字体输出参数
  restoreFont();

  // 设置C语言的字符集环境
  setlocale(LC_ALL, "");
}

// 释放FreeType资源
CvxText::~CvxText() {
  FT_Done_Face(m_face);
  FT_Done_FreeType(m_library);
}

// 设置字体参数:
//
// font         - 字体类型, 目前不支持
// size         - 字体大小/空白比例/间隔比例/旋转角度
// underline   - 下画线
// diaphaneity   - 透明度
void CvxText::getFont(int *type, cv::Scalar *size, bool *underline,
                      float *diaphaneity) {
  if (type)
    *type = m_fontType;
  if (size)
    *size = m_fontSize;
  if (underline)
    *underline = m_fontUnderline;
  if (diaphaneity)
    *diaphaneity = m_fontDiaphaneity;
}

void CvxText::setFont(int *type, cv::Scalar *size, bool *underline,
                      float *diaphaneity) {
  // 参数合法性检查
  if (type) {
    if (type >= 0)
      m_fontType = *type;
  }
  if (size) {
    m_fontSize.val[0] = std::fabs(size->val[0]);
    m_fontSize.val[1] = std::fabs(size->val[1]);
    m_fontSize.val[2] = std::fabs(size->val[2]);
    m_fontSize.val[3] = std::fabs(size->val[3]);
  }
  if (underline) {
    m_fontUnderline = *underline;
  }
  if (diaphaneity) {
    m_fontDiaphaneity = *diaphaneity;
  }

  FT_Set_Pixel_Sizes(m_face, (int)m_fontSize.val[0], 0);
}

// 恢复原始的字体设置
void CvxText::restoreFont() {
  m_fontType = 0; // 字体类型(不支持)

  m_fontSize.val[0] = 20;  // 字体大小
  m_fontSize.val[1] = 0.5; // 空白字符大小比例
  m_fontSize.val[2] = 0.1; // 间隔大小比例
  m_fontSize.val[3] = 0;   // 旋转角度(不支持)

  m_fontUnderline = false; // 下画线(不支持)

  m_fontDiaphaneity = 1.0; // 色彩比例(可产生透明效果)

  // 设置字符大小
  FT_Set_Pixel_Sizes(m_face, (int)m_fontSize.val[0], 0);
}

// 输出函数(颜色默认为白色)
int CvxText::putText(cv::Mat &img, char *text, cv::Point pos) {
  return putText(img, text, pos, CV_RGB(255, 255, 255));
}

int CvxText::putText(cv::Mat &img, const wchar_t *text, cv::Point pos) {
  return putText(img, text, pos, CV_RGB(255, 255, 255));
}

int CvxText::putText(cv::Mat &img, const char *text, cv::Point pos,
                     cv::Scalar color) {
  if (img.data == nullptr)
    return -1;
  if (text == nullptr)
    return -1;

  int i;
  for (i = 0; text[i] != '\0'; ++i) {
    wchar_t wc = text[i];

    // 解析双字节符号
    if (!isascii(wc))
      mbtowc(&wc, &text[i++], 2);

    // 输出当前的字符
    putWChar(img, wc, pos, color);
  }

  return i;
}

int CvxText::putText(cv::Mat &img, const wchar_t *text, cv::Point pos,
                     cv::Scalar color) {
  if (img.data == nullptr)
    return -1;
  if (text == nullptr)
    return -1;

  int i;
  for (i = 0; text[i] != '\0'; ++i) {
    // 输出当前的字符
    putWChar(img, text[i], pos, color);
  }

  return i;
}

// 输出当前字符, 更新m_pos位置
void CvxText::putWChar(cv::Mat &img, wchar_t wc, cv::Point &pos,
                       cv::Scalar color) {
  // 根据unicode生成字体的二值位图
  FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);
  FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
  FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_MONO);

  FT_GlyphSlot slot = m_face->glyph;

  // 行列数
  int rows = slot->bitmap.rows;
  int cols = slot->bitmap.width;

  for (int i = 0; i < rows; ++i) {
    for (int j = 0; j < cols; ++j) {
      int off = i * slot->bitmap.pitch + j / 8;

      if (slot->bitmap.buffer[off] & (0xC0 >> (j % 8))) {
        int r = pos.y - (rows - 1 - i);
        int c = pos.x + j;

        if (r >= 0 && r < img.rows && c >= 0 && c < img.cols) {
          cv::Vec3b pixel = img.at<cv::Vec3b>(cv::Point(c, r));
          cv::Scalar scalar =
              cv::Scalar(pixel.val[0], pixel.val[1], pixel.val[2]);

          // 进行色彩融合
          float p = m_fontDiaphaneity;
          for (int k = 0; k < 4; ++k) {
            scalar.val[k] = scalar.val[k] * (1 - p) + color.val[k] * p;
          }

          img.at<cv::Vec3b>(cv::Point(c, r))[0] =
              (unsigned char)(scalar.val[0]);
          img.at<cv::Vec3b>(cv::Point(c, r))[1] =
              (unsigned char)(scalar.val[1]);
          img.at<cv::Vec3b>(cv::Point(c, r))[2] =
              (unsigned char)(scalar.val[2]);
        }
      }
    }
  }

  // 修改下一个字的输出位置
  double space = m_fontSize.val[0] * m_fontSize.val[1];
  double sep = m_fontSize.val[0] * m_fontSize.val[2];

  pos.x += (int)((cols ? cols : space) + sep);
}

int CvxText::toWchar(char *src, wchar_t *&dest, const char *locale) {
  if (src == NULL) {
    dest = NULL;
    return 0;
  }

  // 根据环境变量设置locale
  setlocale(LC_CTYPE, locale);

  // 得到转化为需要的宽字符大小
  int w_size = mbstowcs(NULL, src, 0) + 1;

  // w_size = 0
  // 说明mbstowcs返回值为-1。即在运行过程中遇到了非法字符(很有可能使locale
  // 没有设置正确)
  if (w_size == 0) {
    dest = NULL;
    return -1;
  }

  // wcout << "w_size" << w_size << endl;
  dest = new wchar_t[w_size];
  if (!dest) {
    return -1;
  }

  int ret = mbstowcs(dest, src, strlen(src) + 1);
  if (ret <= 0) {
    return -1;
  }
  return 0;
}
} // namespace xt
View Code

并且在初始化的时候做一个初始化

 text_ = new xt::CvxText("./fonts/SIMSUN.TTC");
    cv::Scalar size1{30, 0.5, 0.1, 0};  // (字体大小, 无效的, 字符间距, 无效的 }
    text_->setFont(nullptr, &size1, nullptr, 0);
xt::CvxText* text_;

在对应的位置化图

std::ostringstream labelStream;
            labelStream << label << ": " << std::fixed << std::setprecision(2) << confidence;
            std::string labelInfo = labelStream.str();

            int baseline;
            cv::Size labelSize = cv::getTextSize(labelInfo, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseline);

            // 绘制矩形框上方的标签
            cv::Point textOrigin(rect.x, rect.y - baseline);
            wchar_t* w_str;
            text_->toWchar((char*)labelInfo.c_str(), w_str);
            text_->putText(image.infer_img, w_str, textOrigin, cv::Scalar(0, 0, 255));
            delete w_str;

需要修改cmakelist代码为

include_directories(/usr/include/freetype2)
aux_source_directory(${PROJECT_SOURCE_DIR}/cvxtext          CVXTEXT_SRC_FILES)
target_link_libraries(${xx} freetype)
add_executable(${xx} 
    main.cc
    ${CVXTEXT_SRC_FILES}
    )

 

标签:中文,val,img,int,text,pos,c++,字体,cv
From: https://www.cnblogs.com/xiaoruirui/p/18285475

相关文章

  • C++设计模式---迭代器模式
    1、介绍        迭代器模式是⼀种行为型设计模式,是⼀种使⽤频率⾮常⾼的设计模式,在各个语⾔中都有应用,其主要⽬的是提供⼀种统⼀的⽅式来访问⼀个聚合对象中的各个元素,而不需要暴露该对象的内部表示。通过迭代器,客户端可以顺序访问聚合对象的元素,而无需了解底层数据结......
  • C++ 空间和时间高效的二项式系数(Space and time efficient Binomial Coefficient)
    这里函数采用两个参数n和k,并返回二项式系数C(n,k)的值。 例子: 输入:n=4和k=2输出:6解释:4C2等于4!/(2!*2!)=6输入:n=5和k=2输出:10解释:5C2等于5!/(3!*2!)=10        在本文中,我们讨论了O(n*k)时间和O(k)额外空间算法。C(n,......
  • 【OpenVINO™】YOLOv10在CPU上也能实现50+FPS推理—使用OpenVINO C++部署YOLOv10
    ​英特尔发行版OpenVINO™工具套件基于oneAPI而开发,可以加快高性能计算机视觉和深度学习视觉应用开发速度工具套件,适用于从边缘到云的各种英特尔平台上,帮助用户更快地将更准确的真实世界结果部署到生产系统中。YOLOv10是清华大学研究人员近期提出的一种实时目标检测方法,......
  • 【C++学习笔记 8】C++中的析构函数
    构造函数一般用于创建实例或初始化,而析构(destructor)函数则是在销毁一个对象时使用的。析构函数可以用在释放任何内容或需要清理内存空间的场景。举个例子#include<iostream>classEntity{public: floatX,Y; Entity() { X=0.0f; Y=0.0f; std::cout<<......
  • 2024华为OD机试真题-根据IP查找城市-(C++/Python)-C卷D卷-200分
    2024华为OD机试题库-(C卷+D卷)-(JAVA、Python、C++)       题目描述某业务需要根据终端的IP地址获取该终端归属的城市,可以根据公开的IP地址池信息查询归属城市。地址池格式如下:城市名=起始IP,结束IP起始和结束地址按照英文逗号分隔,多个地址段采用英文分号分隔。比......
  • C++中的引用:深入理解与高效利用
    引言在C++编程世界中,引用(References)是一种强大的语言特性,它提供了一种直接访问另一个变量的方式,而无需复制其数据。相比于指针,引用在语法上更加直观、安全,是C++标准库以及现代C++编程风格中不可或缺的一部分。本文将带你深入理解C++中的引用,包括其基本用法、与指针的区别、......
  • C++中的日期与时间处理:全面指南
    引言在C++编程中,处理日期和时间是一个常见且重要的任务。从简单的日志记录到复杂的时间序列分析,日期和时间的准确获取与格式化都是不可或缺的。然而,C++标准库(直到C++20之前)对日期和时间的支持相对基础,主要通过<ctime>和<chrono>头文件提供。随着C++20的发布,标准库增加了对......
  • c++类模板及应用
    文章目录为什么要有函数模板一般实现举例类模板举例继承中类模板的使用特殊情况友元函数模板类和静态成员类模板实践为什么要有函数模板项目需求:实现多个函数用来返回两个数的最大值,要求能支持char类型、int类型、double一般实现举例类模板举例继承中类模......
  • Intel DPC++安装与使用
    IntelDPC++安装与使用 DPC++(DataParallelC++)是Intel公司使用oneAPI实现的SYCL和SYCL编译器,这里记录一下V100服务器安装DPC++过程下载安装DPC++编译器前往官网下载地址,左侧选择Compilers->Intel®oneAPIDPC++/C++CompilerandIntel®C++CompilerClassic,选择目前最......
  • Python基础语法(与C++对比)(持续更新ing)
    代码块Python在统一缩进体系内,为同一代码块C++{...}内部的为同一代码块注释Python单行注释:#...多行注释:'''...'''C++单行注释://...多行注释:/*...*/数据类型1.Python数据类型    Python中支持数字之间使用下划线'_'分割数字,旨在查看方便    ......