OpenCV支持中文字符输出实现
在 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:// 禁止copyCvxText& 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
OpenCV支持中文字符输出实现相关推荐
- python语言支持中文字符作为量变_尔雅尔雅汉语揭秘章节考试答案
运营是让产品持续产生产品价值和商业价值目的. [多选题]作为现代战略营销的核心,STP营销是企业制定有效营销组合策略的基础和前提,其内容包括 ( ) A. 市场进入 B. 细分市场 C. 目标营销 D ...
- android 4.4.3上面,联系人的头像默认显示首字母,但是不支持中文字符,修改支持中文
在android 4.4.3上面,联系人的头像默认显示首字母,但是不支持中文字符,如下图: 如果联系人名字的第一位是英文字符(a-z || A-Z),则默认头像将显示该首字母. 如果支持中文时显示第一 ...
- Dicom文件支持中文字符
Dicom文件的默认字符集编码为ISO-IR6,这种字符集是不支持中文的,当使用Dicom工具修改病人姓名后,名字会成乱码而无法正常显示,如下图: 知道了原因就知道解决办法了,修改Dicom的字符集( ...
- moviepy音视频剪辑:TextClip不支持中文字符以及OSError: magick.exe: unable to read font 仿宋_GB2312.ttf的解决办法
☞ ░ 前往老猿Python博文目录 ░ 一.引言 moviepy对中文和多语言环境的支持做得并不好,包括中文文件名以及用于显示文字的TextClip就是典型的中文支持方面存在问题的.对于编解码的问题 ...
- 又重新让aspspider.net支持中文PDF输出了
经过一番努力,再次看到中文PDF的输出: aspspider.net经过这次更新后,不知道什么原因,使用 BaseFont.AddToResourceSearch(MapPath(@".\i ...
- lua 不支持中文字符_英雄联盟跳票?不支持中文?别急看这里!界面最强翻译!...
大家期待英雄联盟手游已经很久了,16 号放出消息苦苦等待 28 号.老范跟大家的心情是一样的,注册拳头账号遇到种种问题,半天注册不成功等,要么就是卡在最后一步. 注册麻烦就不用说了,约定好的日子就跳票 ...
- C语言读入txt文件中的中文字符输出乱码
**记录下自己在文件操作上遇到的常见问题** 输出乱码的情况 fopen函数读写的相关操作 输出乱码的情况 在使用C语言时我们一般用fopen函数打开文件,如下 #include<stdio.h ...
- SciTE: 中文字符支持问题
SciTE: 中文字符支持问题 SciTE(Scintilla Text Editor)是一个体积小巧的文本编辑器. 但是它默认的设置对中文字符处理不好,其实只要对它进行相应的配置,就可以了. 1 ...
- C++fstream文件流处理对中文字符不支持的解决办法
转载一篇C++文件流处理中文路径问题的方法. http://www.cnblogs.com/upendi/archive/2013/05/10/3072195.html [以下内容转自:我住包子山 让 ...
最新文章
- [译]如何在C#中调试LINQ查询
- 判断整数序列是不是二元查找树的后序遍历结果
- www.android ind.com,Android
- TDSQL 安装部署(多图预警)
- 系统集成的系统架构图的相关的vsd素材_信息系统集成专业技术知识:软件架构...
- 数据结构 3-2-1 队列的链式存储实现
- Javascript 操作二进制数据
- Access SqLDbHelper
- ASP.NET之ScriptManager和ClientScriptManager
- 携程中转机票竟然相差23小时
- 如何利用迅雷下载百度云?
- stm32 SSI读编码器
- 【开发日常】手动安装fastboot驱动(开发板连不上minitool)
- 一级导航,二级导航,三级导航介绍
- 分时操作系统与分布式操作系统
- asp.net大文件分块上传视频教程
- tp-link无线路由与android手机无线连接设置指南,手机设置tplink无线路由器_tplink路由器手机设置步骤-192路由网...
- 100行Python代码,做一个打地鼠小游戏!
- Max 文件制作三维场景
- 清华大学计算机专业的cpu,我们研制成功进入世界500强的超级计算机
热门文章
- 用代码优雅的终止springboot服务
- opencv学习笔记(二)
- 第二章:3、BP神经网络
- 【camera】3.相机成像颜色及其组成
- 通信系统未编码、卷积码与格雷码的仿真性能比较
- Linux那些事儿 之 戏说USB(3)我是一棵树
- 学习《Linux设备模型浅析之驱动篇》笔记(一)
- 剑指offer:面试题24. 反转链表
- div自己移除自己/移除div下面的所有子元素
- 【进阶玩法】Angular用emit()实现类似Vue.js的v-model双向绑定[(ngModel)]功能