Opencv C++ 绘制中文

零、源码

  • GitHub - ITC-AI/Opencv_Chinese: C++ 的 Opencv绘制中文

一、代码编写

  • 参考
    • https://blog.csdn.net/long630576366/article/details/131440684

1、cvxFont.h

#ifndef OPENCVUNICODE_CVXFONT_H
#define OPENCVUNICODE_CVXFONT_H#include <ft2build.h>
#include FT_FREETYPE_H
#include <opencv2/opencv.hpp>#include <typeinfo>
#include <codecvt>
#include <string>
#include <locale>namespace cvx {struct FontProperty {int fontSize;           // font size (pixel)double spaceRatio;       // ratio of distance when meet a space, base on font sizedouble fontRatio;        // ratio of distance between each character, base on font sizedouble fontRotateAngle;  // rotate angledouble fontDiaphaneity;  // merge ratiobool fontIsUnderline;   // underlinebool fontIsVertical;    // put text in vertical};class CvxFont{public:explicit CvxFont(const cv::String& fontType);virtual ~CvxFont();void setFontSize(int fontSize);void setSpaceRatio(const double spaceRatio) { m_font->spaceRatio = spaceRatio; }void setFontRatio(const double fontRatio) { m_font->fontRatio = fontRatio; }void setRotateAngle(const double angle) { m_font->fontRotateAngle = angle; }void setUnderline(const bool isUnderline) { m_font->fontIsUnderline = isUnderline; }void setDiaphaneity(const double diaphaneity) { m_font->fontDiaphaneity = diaphaneity; }void setVertical(const bool vertical) { m_font->fontIsVertical = vertical; }[[nodiscard]] int getFontSize() const { return m_font->fontSize; }[[nodiscard]] double getSpaceRatio() const { return m_font->spaceRatio; }[[nodiscard]] double getFontRatio() const { return m_font->fontRatio; }[[nodiscard]] double getAngle() const { return m_font->fontRotateAngle; }[[nodiscard]] bool getUnderline() const { return m_font->fontIsUnderline; }[[nodiscard]] double getDiaphaneity() const { return m_font->fontDiaphaneity; }[[nodiscard]] bool getVertical() const { return m_font->fontIsVertical; }private:void initFont();void rotateFont(double angle);void putTextStr(cv::Mat& img, const cv::String& text, cv::Point pos, const cv::Scalar& color);void putWChar(cv::Mat& img, uint32_t wc, cv::Point& pos, const cv::Scalar& color);friend void putText(cv::Mat&, const std::string&, cv::Point, cvx::CvxFont&, int, const cv::Scalar&);FT_Library   m_library{};   // font libraryFT_Face      m_face{};      // font typeFT_Matrix    m_matrix{};FT_Vector    m_pen{};FT_Error     m_error;FontProperty* m_font;long m_maxDiffHeight{ 0 };};void putText(cv::Mat& img, const std::string& text, cv::Point pos, cvx::CvxFont& fontFace, int fontSize, const cv::Scalar& color);void putSymbols(cv::Mat& img, std::vector<uint32_t>& symbols, cv::Point pos, cvx::CvxFont& fontFace, int fontSize, const cv::Scalar& color);void putOneSymbol(cv::Mat& img, uint32_t symbol, cv::Point pos, cvx::CvxFont& fontFace, int fontSize, const cv::Scalar& color);
}#endif //OPENCVUNICODE_CVXFONT_H

2、 cvxFont.cpp

#include "cvxFont.h"
#include <cassert>
#include <clocale>
#include <utility>
#include <sstream>
#include <cstdlib>cvx::CvxFont::CvxFont(const cv::String& fontType)
{assert(!fontType.empty());m_error = FT_Init_FreeType(&m_library);if (m_error){std::cerr << "library initial error!" << std::endl;return;}m_error = FT_New_Face(m_library, fontType.c_str(), 0, &m_face);if (m_error == FT_Err_Unknown_File_Format){std::cerr << "unsupported font format!" << std::endl;return;}else if (m_error){std::cerr << " can not open font files" << std::endl;return;}// use default parametersm_font = new FontProperty;initFont();setlocale(LC_ALL, "");
}// release freetype resource
cvx::CvxFont::~CvxFont()
{delete m_font;FT_Done_Face(m_face);FT_Done_FreeType(m_library);
}void cvx::CvxFont::setFontSize(const int fontSize)
{m_font->fontSize = fontSize;FT_Set_Pixel_Sizes(m_face, fontSize, 0);
}// initial font
void cvx::CvxFont::initFont()
{setFontSize(16);setSpaceRatio(0.5);setFontRatio(0);setRotateAngle(0);setDiaphaneity(1);setUnderline(false);setVertical(false);// set fontFT_Set_Pixel_Sizes(m_face, getFontSize(), 0);
}void cvx::CvxFont::rotateFont(double angle) {angle = (angle / 360) * 3.14159 * 2;/* set up matrix */m_matrix.xx = static_cast<FT_Fixed>(cos(angle) * 0x10000L);m_matrix.xy = static_cast<FT_Fixed>(-sin(angle) * 0x10000L);m_matrix.yx = static_cast<FT_Fixed>(sin(angle) * 0x10000L);m_matrix.yy = static_cast<FT_Fixed>(cos(angle) * 0x10000L);FT_Set_Transform(m_face, &m_matrix, nullptr);
}void cvx::CvxFont::putTextStr(cv::Mat& img, const cv::String& text, cv::Point pos, const cv::Scalar& color)
{CV_Assert(!img.empty());CV_Assert(!text.empty());int xStart = pos.x;int yStart = pos.y;m_maxDiffHeight = 0;const char* ptr = text.c_str();std::mbtowc(nullptr, nullptr, 0); // reset the conversion stateconst char* end = ptr + std::strlen(ptr);int ret;for (wchar_t wc; (ret = std::mbtowc(&wc, ptr, end - ptr)) > 0; ptr += ret) {putWChar(img, (wc & 0xffffffff), pos, color);}int xEnd = pos.x;int yEnd = pos.y;if (getUnderline()) {if (getVertical()) {cv::line(img, cv::Point(xStart + m_maxDiffHeight, yStart), cv::Point(xStart + m_maxDiffHeight, yEnd), color, 2);}else {cv::line(img, cv::Point(xStart, yStart + m_maxDiffHeight), cv::Point(xEnd, yStart + m_maxDiffHeight), color, 2);}}}void cvx::CvxFont::putWChar(cv::Mat& img, uint32_t wc, cv::Point& pos, const cv::Scalar& color)
{rotateFont(getAngle());const auto vertical = getVertical();const auto size = getFontSize();// Converting a Character Code Into a Glyph IndexFT_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;FT_Bitmap bitmap = slot->bitmap;bool isSpace = wc == ' ';// get rows and cols of current wide charauto rows = bitmap.rows;auto cols = bitmap.width;cv::Point gPos = pos;//gPos.y += m_font->fontSize;if (vertical){gPos.x += (slot->metrics.vertBearingX >> 6);gPos.y += (slot->metrics.vertBearingY >> 6);m_maxDiffHeight = std::max(m_maxDiffHeight, rows - (slot->metrics.vertBearingY >> 6));}else{gPos.x += (slot->metrics.horiBearingX >> 6);gPos.y -= (slot->metrics.horiBearingY >> 6);m_maxDiffHeight = std::max(m_maxDiffHeight, rows - (slot->metrics.horiBearingY >> 6));}// https://stackoverflow.com/questions/52254639/how-to-access-pixels-state-in-monochrome-bitmap-using-freetype2for (auto i = 0; i < rows; ++i){for (auto j = 0; j < cols; ++j){int off = i * slot->bitmap.pitch + j / 8;if (slot->bitmap.buffer[off] & (0x80 >> (j % 8))){const auto r = gPos.y + i; //vertical ? pos.y + i : pos.y + i + (size - rows); // to make align to bottomconst auto c = gPos.x + j;if (r >= 0 && r < img.rows && c >= 0 && c < img.cols){cv::Vec3b scalar = img.at<cv::Vec3b>(cv::Point(c, r));// merge set color with origin colordouble p = getDiaphaneity();for (int k = 0; k < 3; ++k){scalar.val[k] = static_cast<uchar>(scalar.val[k] * (1 - p) + color.val[k] * p);}img.at<cv::Vec3b>(cv::Point(c, r)) = cv::Vec3b(scalar[0], scalar[1], scalar[2]);}}}}// modify position to next characterconst auto space = static_cast<int>(size * getSpaceRatio());const auto sep = static_cast<int>(size * getFontRatio());// vertical string or not, default not verticalif (vertical){const auto moveX = (static_cast<int>(getAngle()) == 0) ?  (slot->metrics.vertAdvance >> 6) : rows + 1;pos.y += isSpace ? space : moveX + sep;}else{const auto moveY = (static_cast<int>(getAngle()) == 0) ? (slot->metrics.horiAdvance >> 6) : cols + 1;pos.x += isSpace ? space : moveY + sep;}
}void cvx::putText(cv::Mat& img, const std::string& text, cv::Point pos, cvx::CvxFont& fontFace, int fontSize, const cv::Scalar& color) {fontFace.setFontSize(fontSize);fontFace.putTextStr(img, text, std::move(pos), color);fontFace.initFont();
}

3、main.cpp

#include "cvxFont.h"
using namespace cvx;
int main(int argc, char *argv[])
{cvx::CvxFont font("../simsun.ttc");cv::Mat img(400, 800, CV_8UC3, cv::Scalar(255, 255, 255)); // create a black backgroundcv::String msg6 = "文字:[主要功能】:可紧致头发磷层,从而达到";// be careful to use the font that support ChineseputText(img, msg6, cv::Point(10, 40), font, 18,  cv::Scalar(255, 0, 0));cv::imshow("test", img);cv::waitKey(0);return 0;
}

4、CMakeLists.txt

  • X64的编译链
cmake_minimum_required(VERSION 3.10)
project(OpenCVUnicode)set(CMAKE_CXX_STANDARD 14)find_package(OpenCV REQUIRED)
message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
include_directories(${OpenCV_INCLUDE_DIRS})find_package(Freetype REQUIRED)
message(STATUS "Freetype library status")
message(STATUS "    ${FREETYPE_INCLUDE_DIRS}")
message(STATUS "    ${FREETYPE_INCLUDE_DIR_ft2build}")
message(STATUS "    ${FREETYPE_INCLUDE_DIR_freetype2}")
include_directories(${FREETYPE_INCLUDE_DIRS})set(SRCmain.cppcvxFont.cpp
)
include_directories (cvxFont.h) add_executable(OpenCVUnicode ${SRC})
target_link_libraries(OpenCVUnicode ${OpenCV_LIBS})
target_link_libraries(OpenCVUnicode ${FREETYPE_LIBRARIES})
  • Arm的编译链
#工程名称
project (OcrChinese)
#版本限定
cmake_minimum_required(VERSION 3.10.2)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
#设置编译链
SET(CMAKE_C_COMPILER "aarch64-buildroot-linux-gnu-gcc")
SET(CMAKE_CXX_COMPILER "aarch64-buildroot-linux-gnu-g++")
SET(CMAKE_AR "aarch64-buildroot-linux-gnu-ar")
SET(CMAKE_LINKER "aarch64-buildroot-linux-gnu-ld")link_directories(${SYS_LIB_PATH}/link)#opencv库路径
set(OpenCV_DIR ${CMAKE_CURRENT_LIST_DIR}/source/rk3588_opencv455/lib/cmake/opencv4)
find_package(OpenCV REQUIRED COMPONENTS imgproc core imgcodecs)  # 指定需要的 OpenCV 组件if (OpenCV_FOUND)message("OpenCV found: ${OpenCV_VERSION}")include_directories(${OpenCV_INCLUDE_DIRS})
else()message(FATAL_ERROR "OpenCV not found")
endif()# FreeType
link_directories(${CMAKE_CURRENT_LIST_DIR}/FreeType/lib)
include_directories(${CMAKE_CURRENT_LIST_DIR}/FreeType/include)#源文件
set (SRC_PATH${CMAKE_CURRENT_LIST_DIR}${CMAKE_CURRENT_LIST_DIR}/Font/src
)
foreach(item ${SRC_PATH})aux_source_directory (${item} SRC_LIST)
endforeach()
#头文件
set (STREAM_INCLUDE${CMAKE_CURRENT_LIST_DIR}/Font/include
)
foreach(item ${STREAM_INCLUDE})include_directories ( ${item} ) 
endforeach()add_compile_options(-Wall)#添加库
set (LIBS pthread stdc++)add_executable(OcrChinese ${SRC_LIST})
target_link_libraries (OcrChinese  ${LIBS} ${OpenCV_LIBS})

二、C++编译

1、X64系统

(1) 安装opencv

  • 在 Ubuntu 上安装 OpenCV,你可以使用以下命令:
sudo apt update
sudo apt install libopencv-dev python3-opencv
  • 在 CentOS 上安装 OpenCV,你可以使用以下命令:
sudo yum install epel-release
sudo yum install opencv opencv-devel

(2) 安装FreeType

  • 在 Ubuntu 上安装 FreeType,可以使用以下命令:
sudo apt update
sudo apt install libfreetype6 libfreetype6-dev
  • 在 CentOS 上安装 FreeType,可以使用以下命令:
sudo yum install freetype freetype-devel

(3) 编译

# 1、建一个build文件用于编译
mkdir build && cd build
# 2、编译
cmake .. && make -j8

 2、Arm系统 (这个中文没成功,可能是系统文字编码问题)

  •  参考:
    • freetype的交叉编译及在嵌入式linux上的简单使用 - 代码先锋网

(1) 交叉编译 opencv

  • 参考
    • RK3588移植-opencv交叉编译aarch64_arm64 opencv-CSDN博客

(2) 交叉编译FreeType

  • 参考
    • freetype的交叉编译及在嵌入式linux上的简单使用 - 代码先锋网
  • freetype源码下载地址:

    • The FreeType Project - Browse /freetype2/2.8.1 at SourceForge.net

    • (官网) The FreeType Project

  • 交叉编译
# 1、解压
tar zxvf freetype-2.8.1.tar.gzcd freetype-2.8.1/# 2、选定交叉编译侗剧,进行编译
./configure CC=/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc --host=arm-linux --prefix=$PWD/INSTALL --with-zlib=no --with-png=n# 3、编译
make
make install

(3) 编译

# 1、建一个build文件用于编译
mkdir build && cd build
# 2、编译
cmake .. && make -j8

三、效果图 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/285889.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ入门指南(一):初识与安装

专栏导航 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、消息队列介绍 1.同步调用和异步调用 2.常见消息队列介绍 二、RabbitMQ简介及其安装步骤 1.RabbitMQ简介 2.RabbitMQ安装步骤&#xff08;使用Docker&#xff09; (1) 创建网络 (2) 使用Docker来…

【LeetCode:1901. 寻找峰值 II | 二分】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

初识Python之Networkx模块

初识Python之Networkx模块 文章目录 初识Python之Networkx模块简介安装Networkx导入模块、查看版本信息一些基本操作创建Graph添加边&#xff08;节点&#xff09;获取Graph的基本信息Graph的基本绘图 简单应用案例使用内置的Graph数据创建一个无向图创建一个有向图在计算机网络…

LinuxCNC系统安装

首先我们需要准备一个U盘来安装系统&#xff0c;然后进入Debian官网。操作系统处&#xff0c;点击“下载Debian”。 如果需要下载其他比较全版本&#xff0c;可以点击“其他下载链接”&#xff0c;选择DVD的安装&#xff0c;因为是国外的网站&#xff0c;最好不要选择网络安装。…

MSDN:Mutually Semantic Distillation Network for Zero-Shot Learning 中文版 待更新

摘要 零样本学习&#xff08;ZSL&#xff09;的关键挑战是如何将潜在的语义知识融合在可见类的视觉特征和抽象特征之间&#xff0c;从而实现向不可见类的横向知识转移。之前的工作要么只是将图像的全局特征与其相关的类语义向量对齐&#xff0c;要么利用单向注意力来学习有限的…

【Linux基础】3. 文件基本属性

文章目录 【 1. 文件的属主和属组 】【 2. 显示文件的类型、权限 】2.1 文件类型2.2 文件权限 【 3. 更改文件属性 】3.1 chgrp 更改文件属组3.2 chown 更改文件所有者3.3 更改文件权限3.3.1 数字法更改文件权限3.3.2 符号法更改文件权限 【 1. 文件的属主和属组 】 Linux 系统…

CentOS:Docker容器中安装vim

在使用docker容器时&#xff0c;里边没有安装vim时&#xff0c;敲vim命令时提示说&#xff1a;vim: command not found 这个时候就须要安装vim&#xff0c;安装命令&#xff1a; apt-get install vim 出现以下错误&#xff1a; 解决方法&#xff1a; apt-get update 这个命令的…

EMC测试与整改实践?|深圳比创达电子

电磁兼容(EMC)测试和整改是当今社会对电磁兼容(EMC)意识日益深入的表现&#xff0c;EMC测试与整改随着社会对电磁环境要求的不断提高&#xff0c;越来越受到重视&#xff0c;下面就EMC测试与整改实践进行一下详细介绍。 一、什么是EMC测试&#xff1f; EMC测试是指在一定的电…

RPC(3):HttpClient实现RPC之GET请求

1HttpClient简介 在JDK中java.net包下提供了用户HTTP访问的基本功能&#xff0c;但是它缺少灵活性或许多应用所需要的功能。 HttpClient起初是Apache Jakarta Common 的子项目。用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包&#xff0c;并且它支持 H…

Nginx快速入门:Nginx应用场景、安装与部署(一)

1. Nginx简介 Nginx 是一个高性能的 HTTP 和反向代理服务器&#xff0c;也是一个非常流行的开源 Web 服务器软件。它是由俄罗斯程序员 Igor Sysoev 开发的&#xff0c;最初是为了解决在高并发场景下的C10k 问题&#xff08;即一个服务器进程只能处理 10,000 个并发连接&#x…

计算机论文写作助手

本人原创AI应用&#xff0c;现有公开&#xff0c;体验一下

基于hfl/rbt3模型的情感分析学习研究——文本挖掘

参考书籍《HuggingFace自然语言处理详解 》 什么是文本挖掘 文本挖掘&#xff08;Text mining&#xff09;有时也被称为文字探勘、文本数据挖掘等&#xff0c;大致相当于文字分析&#xff0c;一般指文本处理过程中产生高质量的信息。高质量的信息通常通过分类和预测来产生&…