OpenCV支持中文字符输出实现

2023-11-12

        在 http://www.opencv.org.cn/forum.php?mod=viewthread&tid=2083&extra=&page=1 中,作者给出了原始的在OpenCV中 支持中文字符的输入,原始的实现使用的是OpenCV的C接口,使用起来不怎么方便,这里对原作者的实现进行调整,通过OpenCV的C++接口实现中文的输出,调整后的code如下:

        CvxText.hpp:

#ifndef OPENCV_CVX_TEXT_HPP_
#define OPENCV_CVX_TEXT_HPP_

// source from: http://www.opencv.org.cn/forum.php?mod=viewthread&tid=2083&extra=&page=1
// 支持OpenCV中文汉字输入

#include <ft2build.h>
#include FT_FREETYPE_H

#include <opencv2/opencv.hpp>

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, const 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);

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;
};

#endif // OPENCV_CVX_TEXT_HPP_

        CvxText.cpp:

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

#include "CvxText.hpp"

// 打开字库
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, const 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);
}

        测试代码如下:

#include "funset.hpp"
#include <iostream>

//It contains various macro declarations that are later used to #include the
//appropriate public FreeType 2 header files.
#include <ft2build.h>
//FT_FREETYPE_H is a special macro defined in file ftheader.h. It contains some
//installation-specific macros to name other public header files of the FreeType 2 API.
#include FT_FREETYPE_H
#include <ftglyph.h>

#include <opencv2/opencv.hpp>

#include "CvxText.hpp"

int test_opencv_support_chinese_text()
{
	cv::Mat mat = cv::imread("E:/GitCode/OCR_Test/test_data/lena.png", 1);
	if (!mat.data || mat.channels() != 3) {
		fprintf(stderr, "read image fail\n");
		return -1;
	}

	CvxText text("E:/GitCode/OCR_Test/test_data/simhei.ttf"); //指定字体
	cv::Scalar size1{ 100, 0.5, 0.1, 0 }, size2{ 100, 0, 0.1, 0 }, size3{ 50, 0, 1, 0 }, size4{50, 0, 0.1, 0}; // (字体大小, 无效的, 字符间距, 无效的 }

	text.setFont(nullptr, &size1, nullptr, 0);
	text.putText(mat, "中国", cv::Point(50, 100));

	text.setFont(nullptr, &size2, nullptr, 0);
	text.putText(mat, "北京", cv::Point(50, 200), cv::Scalar(255, 0, 0));

	text.setFont(nullptr, &size3, nullptr, 0);
	text.putText(mat, "China", cv::Point(50, 250), cv::Scalar(0, 255, 0));

	text.setFont(nullptr, &size4, nullptr, 0);
	text.putText(mat, "BeiJing", cv::Point(50, 300), cv::Scalar(0, 0, 255));

	cv::imwrite("E:/GitCode/OCR_Test/test_data/result_lena.png", mat);

	return 0;
}

        测试结果如下:

GitHub: https://github.com/fengbingchun/OCR_Test 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV支持中文字符输出实现 的相关文章

  • Tesseract 是否会忽略扫描文档中的任何非文本区域?

    我正在使用 Tesseract 但我不知道它是否忽略任何非文本区域并仅针对文本 我是否必须删除任何非文本区域作为预处理步骤以获得更好的输出 Tesseract 有一个非常好的算法来检测文本 但它最终会给出误报匹配 理想情况下 您应该在将图像
  • 我可以使用 openCV 比较两张不同图像上的两张脸吗?

    我对 openCV 很陌生 我看到它可以计算出脸部并返回一个矩形来指示脸部 我想知道 openCV 是否可以访问两张包含一张脸的图像 并且我希望 openCV 返回这两个人是否相同的可能性 Thanks OpenCV 不提供完整的人脸识别引
  • 如何将 mat 转换为 array2d

    我为dlib http dlib net face landmark detection ex cpp html那里的面部地标代码使用 array2d 来获取图像 但我喜欢使用 Mat 读取图像并转换为 array2d 因为 dlib 仅支
  • OpenCV 仅围绕大轮廓绘制矩形?

    第一次发帖 希望我以正确的方式放置代码 我正在尝试检测和计算视频中的车辆 因此 如果您查看下面的代码 我会在阈值处理和膨胀后找到图像的轮廓 然后我使用 drawContours 和矩形在检测到的轮廓周围绘制一个框 我试图在 drawCont
  • 多视图几何

    我从相距一定距离的两台相同品牌的相机捕获了两张图像 捕获了相同的场景 我想计算两个相机之间的现实世界旋转和平移 为了实现这一点 我首先提取了两张图像的 SIFT 特征并进行匹配 我现在有基本矩阵也单应性矩阵 然而无法进一步进行 有很多混乱
  • 来自连接到远程机器的相机的 Opencv 流

    我正在用 python 开发一个 wx 应用程序 用于流式传输和显示来自两个不同网络摄像头的视频 这工作正常 但现在我需要在不同的场景中执行此操作 其中两个摄像头连接在通过网络连接的 Windows 上运行的单独计算机中 我的应用程序将在机
  • Tess4j 问题 java.lang.UnsatisfiedLinkError

    我正在尝试解决 Tess4J 安装问题 1 我在 WEB INF win32 x86 中创建了一个文件夹2 我把 libtesseract302 dll 和 liblept168 dll 放在那里 然后将其添加到 java 构建路径中的源
  • 创建 OpenCV 的 mouseCallback 函数的基于类的实现时遇到问题

    正如标题所示 我在基于类的 C 结构中实现 OpenCV 的 mouseCallback 函数时遇到了一些麻烦 请允许我解释一下 我定义了一个名为 BriskMatching 的类 在其中创建了一个名为 mouseCallback 的成员函
  • 如何使用 python、openCV 计算图像中的行数

    我想数纸张 所以我正在考虑使用线条检测 我尝试过一些方法 例如Canny HoughLines and FLD 但我只得到处理过的照片 我不知道如何计算 有一些小线段就是我们想要的线 我用过len lines or len contours
  • 如何确定与视频中物体的距离?

    我有一个从行驶中的车辆前面录制的视频文件 我将使用 OpenCV 进行对象检测和识别 但我停留在一方面 如何确定距已识别物体的距离 我可以知道我当前的速度和现实世界的 GPS 位置 但仅此而已 我无法对我正在跟踪的对象做出任何假设 我计划用
  • Tesseract OCR - 手写字体

    我正在尝试使用Tesseract OCR http code google com p tesseract ocr 检测其中包含纯文本的图像文本 但这些文本具有名为的手写字体Journal Example 结果不是最好的 千里马 尺寸 宽
  • 在 Python 中将 OpenCV 帧流式传输为 HTML

    我正在尝试从 opencv Pyt hon 中的 URL 读取视频 然后逐帧处理它 然后将其发送到 HTML 页面 But I am only getting the first frame after that the program g
  • cv2.drawContours() - 取消填充字符内的圆圈(Python,OpenCV)

    根据 Silencer的建议 我使用了他发布的代码here https stackoverflow com questions 48244328 copy shape to blank canvas opencv python 482465
  • cv2.VideoWriter:请求一个元组作为 Size 参数,然后拒绝它

    我正在使用 OpenCV 4 0 和 Python 3 7 创建延时视频 构造 VideoWriter 对象时 文档表示 Size 参数应该是一个元组 当我给它一个元组时 它拒绝它 当我尝试用其他东西替换它时 它不会接受它 因为它说参数不是
  • 是否可以在 PyScript 中使用 OpenCV 模块?

    我想使用 opencv 模块 但无法导入 OpenCV 那么我该如何解决这个问题呢 顺便说一句 Pyodide 支持 OpenCV 示例代码 https i stack imgur com ahwex jpg 尚不支持 OpenCV 此时O
  • “没有名为‘cv2’的模块”,但已安装

    我已经安装了包含 opencv 贡献的 whl 文件 因为我想使用 SIFT 算法 我在 conda 环境中使用 pip 安装了它 所以当我在 conda list 中提示时 它会向我显示 opencv python 3 4 5 contr
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • VideoCapture.read() 返回过去的图像

    我在跑python3 6 with openCV on the Raspberry pi OS is Raspbian 代码的大致结构如下 The image以时间间隔 3 5 分钟 捕获 被捕获image在函数中处理并返回度量 精度的种类
  • 查找具有不同强度/亮度的相似图像

    假设我有如下图像 我可以选择什么来比较两个图像之间的相似度 显然它们是相同的图像 只是亮度不同 我找不到任何可行的方法 目前我最好的选择是训练 cnn 或自动编码器并比较输出的特征向量 但这似乎有点矫枉过正 任何提示将不胜感激 相当强大的工
  • 找到 4 个特定的角像素并将它们与扭曲透视一起使用

    我正在使用 OpenCV 我想知道如何构建一个简单版本的透视变换程序 我有一张平行四边形的图像 它的每个角都由具有特定颜色的像素组成 该像素在图像中没有其他位置 我想遍历所有像素并找到这 4 个像素 然后我想将它们用作新图像中的角点 以扭曲

随机推荐

  • 用Javascript实现随机抽奖

    用Javascript实现随机抽奖 思路 首先我们先把一组元素保存到数组arr中 再利用随机生成的整数和数组下标关联起来 这里的重点就是怎样获取随机的整数 下面跟着我一起来看看 HTML部分
  • Linux基础命令

    命令 关闭防火墙1 systemctl stop firewalld service 关闭防火墙程序 systemctl disable firewalld service 关闭开机自启动 关闭防火墙2 firewall cmd set d
  • UVM基础-m_sequencer和p_sequencer

    一 Sequencer问题的由来 1 1 sequence与sequencer之间的数据交互 在UVM的sequence机制中 sequence其实是独立与验证环境之外的部件 作为uvm object而存在 那么sequence最终是要在某
  • VSAN故障案例分享——超经典三场景

    前言 虽然个人认为现VSAN的常规运维都已经很成熟便捷了 像磁盘更换 但还是有诸多需要注意的地方 近期又突然跟VSAN项目有了一些交集 整理原有资料时 发现有几个不错的案例 故拿出来出大家分享下 如有不足之处 也希望大佬们帮指正
  • 基于双向门控循环单元(BIGRU)的数据分类预测。matlab代码,要求2020及以上版本。多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序可出分类效果图,迭代

    清空环境变量 warning off 关闭报警信息 close all 关闭开启的图窗 clear 清空变量 clc 清空命令行 读取数据 res xlsread 数据集 xlsx 分析数据 num class length unique
  • FreeRtos移植到stm32

    每次都忘记怎么移植 还是在此记录下来比较好 1 打开官网FreeRTOS Free RTOS Source Code Downloads the official FreeRTOS zip file release download2 下载
  • 【安装部署】Mysql下载及其安装的详细步骤

    1 下载压缩包 官网地址 www mysql com 2 环境配置 1 先解压压缩包 2 配置环境变量 添加环境变量 我的电脑 gt 属性 gt 高级 gt 环境变量 gt 系统变量 gt path 3 在mysql安装目录下新建my in
  • 如何处理海量数据文件以及大文件数据查找

    目录 一 处理海量整数文件 问 假定有40亿个无符号整数 判断某数据是否在其中 问 假定有40亿个无符号整数 找到只出现一次的数据 两次 三次 问 两个文件各有100亿个整数 只有1G内存 找交集整数 二 处理海量数据 非整数 文件 问 超
  • matlab算出中心差分方法_美赛准备第12期丨美赛ABCDEF题型分析与建模方法

    美赛还有十多天的时间就正式开始了 参赛的小伙伴准备好咯吗 美国大学生数学建模竞赛有MCM和ICM MCM Mathematical Contest in Modeling 为数学建模竞赛 ICM The Interdisciplinary
  • 微信的信息会保存在苹果服务器上吗,【每日一技】如何将微信文件保存到 iPhone 里?...

    由于 iOS 系统的封闭性 在 iPhone 本地储存文件一直是一件麻烦事 特别是在微信内收到很多文件之后 分类管理更加不便 如果长时间未操作 文件还可能永久失效 今天小编图文详解 如何解决 iOS 存储文件问题以及如何在 iOS 内找到文
  • 透明网关

    Oracle与SQL Server的互连 不同数据库平台的互连一般称之为数据库的异构服务 现在各大数据库之间都可以实现这样的异构互连 只是各厂商的具体实现技术不一样 如 在SQL SERVER里面叫做LINKED SERVER 通过ODBC
  • 人工智能从头学(一)

    人工智能从头学 一 Python基础 本系列是对人工智能学习之路的一次复现与总结 适合期末突击复习概念知识点 回顾人工智能知识体系等场景 本文对纯小白极不友好 至少至少对计算机方向有个大概的了解 如有纰漏 欢迎指正 暂定计划 Python基
  • centos7 使用libvirt创建kvm虚拟机并vnc连接

    文章目录 环境 安装libvirt 查看libvirt的一些默认配置 查看libvirt的默认网络配置 kvm虚拟机搭建与连接 创建虚拟机 创建磁盘 下载镜像 使用libvirt创建kvm虚拟机 libvirt常用参数 创建kvm常用指令
  • android上实现Table

    package com android import java util ArrayList import java util HashMap import java util List import java util Map impor
  • 机器学习(十八) 方差、标准差、协方差、协方差矩阵、相关系数

    实例计算 学习数学理论发现还是懂了理论自己算一算 印象才深刻 记忆才清晰 并且在整理计算过程中会使得想法进一步加深 挖掘出来表面想象够不到的地方 先来看看统计学定义 大意是通过各种研究方法研究某一现象的内在规律 促进科学发展 统计学 统计学
  • Python 编写shell脚本

    详细讲解 shell中常用的是ls命令 python的写法是 os listdir dirname 这个函数返回字符串列表 里面是所有的文件名 不过不包含 和 os listdir python 把当前工作目录切换到dirname下 os
  • 30天学习之-自动化测试

    30天学习之 自动化测试 工具类实现自动化测试 1 postman自动化测试 1 postman Tests下写脚本 2 newman生成postman的测试报告 2 Jmter 基本操作 jmter基本元件 切换中文简体 登陆请求界面 自
  • 【精】与HDFS相关的Linux基础知识:内核是怎么保存文件描述符相关数据结构的?

    研究分布式文件存储系统 少不了与底层操作系统 文件系统 存储设备等打交道 了解这些基本原理对我们全方位理解分布式存储 问题定位 性能优化等有很大帮助 大家都知道 在linux中 一切都是文件 对文件的操作都是通过打开此文件拿到文件描述符 然
  • 数字大写

    人民币大写数字注意事项 中文大写金额数字应用正楷或行书填写 如壹 贰 叁 肆 伍 陆 柒 捌 玖 拾 佰 仟 万 亿 元 角 分 零 整 正 等字样 不得用一 二 两 三 四 五 六 七 八 九 十 廿 毛 另 或0 填写 不得自造简化字
  • OpenCV支持中文字符输出实现

    在 http www opencv org cn forum php mod viewthread tid 2083 extra page 1 中 作者给出了原始的在OpenCV中 支持中文字符的输入 原始的实现使用的是OpenCV的C接口