OpenCV 4.X 使用CvxText在图片显示汉字

最近又需要在图像上实时绘制汉字。一般来讲如果绘制汉字的需求绕不过的话,直接绘制在图片总归是最easy的实现方式。因为不然的话可能要额外调用GUI组件来实现。一般都是用freetype+cvxtext,老生常谈。且不说实际实现起来是否最easy,主要是这种方法多年来实践了无数次了,不过今次切换到OpenCV4.5,突然发现可能又要修改CvxText代码才可以,因为直接使用,不work。

准备

需要的依赖有:

  • C/C++ 编译环境(似乎是废话)
  • OpenCV (仍然废话)
  • freetype的lib: 提前编译好,官网是 https://freetype.org/,我使用的版本是2.9.1
  • 字体文件,一般用simhei.ttf。在操作系统的字体里面哦。

修改 CvxText 代码

我这里有一份CvxText代码,在旧版本的OpenCV下可以使用(OpenCV3.X)。如今更换到了OpenCV4.5,这份代码直接使用会有些小问题,不过都很容易修改。

OpenCV头文件包含方式

首先需要重写头文件包含方法。在OpenCV4以前,include下有两个子目录,分别是opencv,和opencv2。在OpenCV4.X后,include下只剩一个opencv2文件夹了。涉及到opencv的头文件包含代码,改为如下形式:

#include "opencv2/core/core.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

这里特别说明,引入core_c.h这个头文件很重要。因为我手里这份CvxText代码类型都是基于旧式的C类型,core_c.h 提供了对C类型的兼容。

CvScalar类型问题

下一处需要修改的是和CvScalar相关的代码。尽管我们重新写了头文件包含,引入了C类型,但是有些代码仍然不能直接编译通过, 因为CvScalar不能隐式的转为C++类型的cv::Scalar。下面的puttext函数代码中,我修改了显式的手工转换替代了注释中的代码。样子很丑,但是简单好用(总共花费了不到1分钟)。


int CvxText::putText(cv::Mat &frame, const char    *text, CvPoint pos)
{//return putText(frame, text, pos, CV_RGB(255, 255, 255));CvScalar s = {255, 255, 255};return putText(frame, text, pos, s);
}
int CvxText::putText(cv::Mat &frame, const wchar_t *text, CvPoint pos)
{//return putText(frame, text, pos, CV_RGB(255, 255, 255));CvScalar s = {255, 255, 255};return putText(frame, text, pos, s);
}

cv::Mat转为IplImage

另一处就是比较老生常谈的问题,cv::Mat转为IplImage。这里之前的实现是直接采用C形式的强制转换,如下所示:

void CvxText::putWChar(cv::Mat &frame, wchar_t wc, CvPoint &pos, CvScalar color)
{IplImage* img = NULL;img = &(IplImage)frame;...}

很不幸,现在这样做在似乎不work了。好在cv::Mat转IplImage仍然有提供接口可用。打开core_c.h文件,可以看到一个很显眼的函数声明,

CV_EXPORTS _IplImage cvIplImage(const cv::Mat& m);

所以调用该接口,传入cv::Mat对象会返回转换好的IplImage类型的对象。直接修改代码如下

	IplImage* img = NULL;img = &(cvIplImage(frame));

至此,代码就可以正常工作了。

调用方法

初始化

    CvxText text;

调用接口

int putText(cv::Mat &frame, const char    *text, CvPoint pos);

CvxText代码

把我改后的代码分享一下。在OpenCV 4.5下亲测可用。理论上4.X的OpenCV应该都可使用。

头文件 CvxText.h

#ifndef CVX_TEXT_H
#define CVX_TEXT_H#include <ft2build.h>  
#include FT_FREETYPE_H  
#include "opencv2/core/core.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
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(cv::Mat &frame, const char    *text, CvPoint pos);/*** �������(��ɫĬ��Ϊ��ɫ)����������������ַ���ֹͣ��** \param img  �����Ӱ��* \param text �ı�����* \param pos  �ı�λ��** \return ���سɹ�������ַ����ȣ�ʧ�ܷ���-1��*/int putText(cv::Mat &frame, const wchar_t *text, CvPoint pos);/*** ������֡���������������ַ���ֹͣ��** \param img   �����Ӱ��* \param text  �ı�����* \param pos   �ı�λ��* \param color �ı���ɫ** \return ���سɹ�������ַ����ȣ�ʧ�ܷ���-1��*/int putText(cv::Mat &frame, const char    *text, CvPoint pos, CvScalar color);/*** ������֡���������������ַ���ֹͣ��** \param img   �����Ӱ��* \param text  �ı�����* \param pos   �ı�λ��* \param color �ı���ɫ** \return ���سɹ�������ַ����ȣ�ʧ�ܷ���-1��*/int putText(cv::Mat &frame, const wchar_t *text, CvPoint pos, CvScalar color);//================================================================  //================================================================  private:// �����ǰ�ַ�, ����m_posλ��  void putWChar(cv::Mat &frame, 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

实现文件 CvxText.cpp


#include "CvxText.h"
#include <wchar.h>  
#include <assert.h>  
#include <locale.h>  
#include <ctype.h> 
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"using namespace cv;
// ���ֿ�  CvxText::CvxText(const char *freeType)
{assert(freeType != NULL);// ���ֿ��ļ�, ����һ������  if (FT_Init_FreeType(&m_library)) throw;int result = 100;//result = FT_New_Face(m_library, freeType, 0, &m_face);if (result = 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, CvScalar *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, CvScalar *size, bool *underline, float *diaphaneity)
{// �����Ϸ��Լ��  if (type){if (type >= 0) m_fontType = *type;}if (size){m_fontSize.val[0] = fabs(size->val[0]);m_fontSize.val[1] = fabs(size->val[1]);m_fontSize.val[2] = fabs(size->val[2]);m_fontSize.val[3] = fabs(size->val[3]);}if (underline){m_fontUnderline = *underline;}if (diaphaneity){m_fontDiaphaneity = *diaphaneity;}
}// �ָ�ԭʼ����������  void CvxText::restoreFont()
{m_fontType = 0;            // ��������(��֧��)  m_fontSize.val[0] = 40;      // �����С  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 &frame, const char    *text, CvPoint pos)
{//return putText(frame, text, pos, CV_RGB(255, 255, 255));CvScalar s = {255, 255, 255};return putText(frame, text, pos, s);
}
int CvxText::putText(cv::Mat &frame, const wchar_t *text, CvPoint pos)
{//return putText(frame, text, pos, CV_RGB(255, 255, 255));CvScalar s = {255, 255, 255};return putText(frame, text, pos, s);
}//  int CvxText::putText(cv::Mat &frame, const char    *text, CvPoint pos, CvScalar color)
{if (frame.empty()) return -1;if (text == NULL) 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(frame, wc, pos, color);}return i;
}
int CvxText::putText(cv::Mat &frame, const wchar_t *text, CvPoint pos, CvScalar color)
{if (frame.empty()) return -1;if (text == NULL) return -1;//  int i;for (i = 0; text[i] != '\0'; ++i){// �����ǰ���ַ�  putWChar(frame, text[i], pos, color);}return i;
}// �����ǰ�ַ�, ����m_posλ��  void CvxText::putWChar(cv::Mat &frame, wchar_t wc, CvPoint &pos, CvScalar color)
{IplImage* img = NULL;img = &(cvIplImage(frame));// ����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 = ((img->origin == 0) ? i : (rows - 1 - i))* slot->bitmap.pitch + j / 8;if (slot->bitmap.buffer[off] & (0xC0 >> (j % 8))){int r = (img->origin == 0) ? pos.y - (rows - 1 - i) : pos.y + i;;int c = pos.x + j;if (r >= 0 && r < img->height&& c >= 0 && c < img->width){CvScalar scalar = cvGet2D(img, r, c);// ����ɫ���ں�  float p = m_fontDiaphaneity;for (int k = 0; k < 4; ++k){scalar.val[k] = scalar.val[k] * (1 - p) + color.val[k] * p;}cvSet2D(img, r, c, scalar);}}} // end for  } // end for  // �޸���һ���ֵ����λ��  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);
}

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

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

相关文章

GAT1399协议分析(10)--视频定义及解析

一、官方定义 二、字段解析 VideoID 类型BasicObjectID 解析参考GAT1399协议分析(8)--ImageInfo字段详解-CSDN博客 InfoKind 采集类型

小程序自定义marker弹出框教程

需求背景 微信小程序开发&#xff0c;需要使用腾讯地图显示自定义marker&#xff0c;并且点击marker后弹出自定义的customCallout&#xff0c;并且customCallout的内容为用户点击marker的时候再从后台接口获取数据。 百度了一圈后发现居然没有一篇文章可以一次性完成&#xf…

SSM旅游论坛(前后分离源码+论文)

该旅游论坛是基于Spring、SpringMVC、Mybatis框架开发出来的 用户信息管理 此页面提供给管理员的功能有&#xff1a;用户信息的查询管理&#xff0c;可以删除用户信息、修改用户信息、新增用户信息&#xff0c; 还进行了对用户名称的模糊查询的条件 景点信息管理 论坛类型管理…

医诊合作怎么避免减少双方损失,吸引更多的优质医疗资源下沉到基层?防漏费系统又起到什么作用?

健康领域的现代化治理要求在公共医疗卫生机构之间建立合作关系,然而我国公共医疗卫生服务领域呈现各级各类健康服务机构自由混合竞争的格局,这对公医分类分级诊疗法治秩序构成全面挑战,并成为影响转诊制度构建的重要因素.我国转诊制度的建设应以维护诊疗合作的法律秩序为前提,并…

Git概念用法

Git是一种版本控制系统&#xff0c;它可以追踪文件的修改并保存这些修改的历史记录。以下是Git的基本概念和使用方式&#xff1a; 仓库&#xff08;Repository&#xff09;&#xff1a;仓库是存储代码和版本历史记录的地方。可以在本地或远程服务器上创建仓库。 提交&#xff…

帕友饮食小建议,健康美味两不误

亲爱的帕友们&#xff0c;大家好&#xff01; 在忙碌的生活中&#xff0c;饮食健康往往是我们容易忽视的一环。作为帕友&#xff0c;我们更应该注重饮食的均衡与营养&#xff0c;让身体得到充分的滋养。今天&#xff0c;就来给大家分享一些帕友饮食的小建议&#xff0c;让我们…

【x264】码率控制模块的简单分析—编码主流程

【x264】码率控制&#xff08;rate control&#xff09;模块的简单分析—编码主流程 1. 码率控制概述1.1 比特分配1.2 率失真优化&#xff08;RDO&#xff09; 2.码率控制中比特分配的实现2.1 码率控制器的创建&#xff08;x264_ratecontrol_new&#xff09;2.1.1 码控模块的重…

项目工具|git相关

本博客暂时只作为个人资料&#xff0c;后续会进行完善&#xff0c;主要内容来自&#xff1a; 【【Git第一讲】&#xff1a;git分区与两个盒子的故事】 理解暂存区和未暂存区 git为什么要多一个暂存区&#xff1f;难道不能我把代码写完后就是未暂存区&#xff0c;然后直接提交…

【C++PCL】点云处理点到面ICP配准

作者:迅卓科技 简介:本人从事过多项点云项目,并且负责的项目均已得到好评! 公众号:迅卓科技,一个可以让您可以学习点云的好地方 重点:每个模块都有参数如何调试的讲解,即调试某个参数对结果的影响是什么,大家有问题可以评论哈,如果文章有错误的地方,欢迎来指出错误的…

VS2015安装模块时报错:安装包丢失或损坏,,,,,无效的驱动器

解决&#xff1a; 1、解压.iso文件&#xff1b; 2、替换目录 替换为解压后的对应的目录&#xff0c;点击重试即可。

Mysql学习(三)——SQL通用语法之DML

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 DML添加数据修改数据删除数据 总结 DML DML用来对数据库中表的数据记录进行增删改操作。 添加数据 -- 给指定字段添加数据 insert into 表名(字段1&#xff0c;字…

关于调用百度AI开放平台短文本在线合成API接口 Open api characters limit reached 问题

官方示例代码中心&#xff1a; https://console.bce.baidu.com/support/?_1668482508529#/api?productAI&project语音技术&parent语音合成&apitext2audio&methodpost 一、调试时&#xff0c;若提示 16: Open api characters limit reached&#xff08;{"…

Highcharts 条形图:数据可视化利器

Highcharts 条形图:数据可视化利器 引言 在数据分析和信息展示领域,图表发挥着至关重要的作用。它们能够将复杂的数据以直观、易于理解的方式呈现给用户。Highcharts 是一个流行的 JavaScript 图表库,广泛用于创建交互式图表。其中,条形图作为一种基础但功能强大的图表类…

线程及其应用

1.线程概念及其用途和优缺点 2.互斥量&#xff08;锁&#xff09; 3.条件变量 4.POSIX信号量 5.生产者消费者模型 6.线程池 7.线程安全的单例模式 1.线程概念及其用途和优缺点 概念&#xff1a;线程是比进程更轻量化的一种执行流&#xff0c;是在进程内部执行的一种执行…

Redis数据类型深掘:如何有效使用List,Set和Sorted Set

List(列表) List 数据类型的深度解析 定义复习 Redis的List数据类型是一个字符串的序列集合,这些字符串按照插入的顺序进行排序。得益于它的设计,List允许重复的值出现,并支持两端的推入(push)和弹出(pop)操作。这种数据类型非常适合用作堆栈(Stack)或队列(Queue)。 …

基于工业互联网打造敏捷供应链的实现方式:创新路径与实践应用

引言 工业互联网和敏捷供应链是当今制造业发展中的两个重要概念。工业互联网以数字化、网络化和智能化为核心&#xff0c;致力于将传统工业生产与互联网技术相融合&#xff0c;从而实现生产过程的高效、智能和灵活。而敏捷供应链则强调快速响应市场需求、灵活调整生产和供应计划…

fastadmin批量导入

表的字段必须备注清楚导出的excel表头必须对应上如果mysql表有约束&#xff0c;导入会自动限制&#xff0c;挺方便的一个功能。

上心师傅的思路分享(二)

Druid monitor 与Springboot常见报错界面渗透小技巧 目录 前言 1.Druid monitor介绍 2.Druid未授权(1rank) 3.druid弱口令 4.Druid进一步利用 4.1 URL监控 4.2 Session监控 利用思路 EditThisCookie(小饼干插件) 5.SpringBoot Actuator未授权访问漏洞 5.1 简介 5…

微信群聊天机器人怎么搭建

要使用 chatgpt-on-wechat 项目搭建一个微信群聊机器人并获取群聊信息&#xff0c;请按照以下步骤操作&#xff1a; 克隆仓库&#xff1a; git clone https://github.com/zhayujie/chatgpt-on-wechat cd chatgpt-on-wechat/安装依赖&#xff1a; pip3 install -r requirements.…

深入理解Linux中的`as`命令:汇编器之旅

标题&#xff1a;深入理解Linux中的as命令&#xff1a;汇编器之旅 在Linux的世界中&#xff0c;编程和编译过程通常涉及多个步骤&#xff0c;从源代码到可执行文件&#xff0c;每一步都至关重要。其中一个重要的步骤是将汇编代码转换为机器代码&#xff0c;这通常是由汇编器&a…