在opencv中结合Freetype实现在图像写入中文

由于OpenCV自带的cvInitFont和cvPutText函数不支持向图像中写入中文,而FreeType是一个完全开源的、可扩展、可定制且可移植的字体引擎,它提供TrueType字体驱动的实现统一的接口来访问多种字体格式文件,它将字变成位图,进而用于显示。由于Freetype是GPL版权发布的库,和opencv版权并不一致,因此目前还没有合并到opencv扩展库中,本文讲诉在windows环境下安装利用Freetype。关于Freetype的细节访问http://www.freetype.org/


这里是windows 32位版本:http://gnuwin32.sourceforge.net/packages/freetype.htm 【lib+dll】

而我需要静态库,已有前辈做了工作,http://sourceforge.net/projects/freetype/files/freetype2/2.5.1/,本文所用的版本是2.5.3,解压包,在freetype-2.5.3\builds\windows\路径下有vc6.0、vs2005、vs2008、vs2010这几个工程,重新编译,得到我们所想要的静态库。

vs2010下的方法步骤:

1. 打开freetype-2.5.3\builds\win32\vc2005下的freetype.vcproj,得到一个工程。

2. 依次点击“工具”->“选项”->“项目和解决方案”->“vc++ 目录”,设置包含文件,即添加freetype-2.5.3下的include文件夹

3. 依次点击“项目”->“freetype属性”->“配置属性”->“常规”,修改配置类型为动态库

4. 依次点击“项目”->“freetype属性”->“配置属性”->“C/C++”->“预处理器”,在“预处理器定义”这一行添加内容:DLL_EXPORT

5. 依次点击“项目”->“freetype属性”配置选择“Release Multithreaded”

6. 修改工程头文件 ftconfig.h

#ifndef FT_EXPORT
#ifdef __cplusplus
#define FT_EXPORT( x )   extern "C"   x
#else
#define FT_EXPORT( x )   extern   x
#endif

改为

#ifdef   DLL_EXPORT
#undef   DLL_EXPORT
#define DLL_EXPORT   __declspec(dllexport)
#else
#define DLL_EXPORT   __declspec(dllimport)
#endif /* !DLL_EXPORT */
#ifndef FT_EXPORT
#ifdef __cplusplus
#define FT_EXPORT( x ) extern "C" DLL_EXPORT x
#else
#define FT_EXPORT( x ) extern DLL_EXPORT x
#endif

7. 选择工程点击“重新生成解决方案”,在freetype-2.5.3\objs\win32\vc2010目录下就产生了freetype253_D.lib 和 freetype253_D.dll文件

至此,得到了我们所想要的静态库。


8. 新建一个工程Test,将freetype253_D.dllfreetype253_D.lib,CvxText.h,CvxText.cpp,simhei.ttf复制到工程目录下,将CvxText.h,CvxText.cpp添加到工程中,将freetype253_D.lib加入到库目录中。

9. 将CvxText.h中的#include <cv.h> #include <highgui.h> 用#include<opencv2/opencv.hpp>代替

10.  在CvxText.cpp文件首行添加#include"stdafx.h" ,在函数setFont末尾添加语句 FT_Set_Pixel_Sizes(m_face, (int)m_fontSize.val[0], 0);

11. 在工具->选项->c++目录中的包含目录中添加freetype-2.5.3下的include文件夹(头文件)

12. 简单的测试代码

#include <opencv2/opencv.hpp>
#include <iostream>
#include <string> 
#include "CvxText.h"

#include <ft2build.h> 
#include FT_FREETYPE_H 

 using namespace cv;
 using namespace std;

 int main()
 {

IplImage *img=cvLoadImage("lena.jpg");
CvxText text("simhei.ttf"); 
const char *msg = "汉字";
float p = 0.5; 
        text.setFont(NULL, NULL, NULL, &p);   // 透明处理 
text.putText(img, msg, cvPoint(100, 150), CV_RGB(255,0,0)); 


cvShowImage("11",img);
        return 0;
}


CvxText.h:

[cpp]  view plain copy
  1. //====================================================================  
  2. //====================================================================  
  3. //  
  4. // 文件: CvxText.h  
  5. //  
  6. // 说明: OpenCV汉字输出  
  7. //  
  8. // 时间:   
  9. //  
  10. // 作者: chaishushan#gmail.com  
  11. //  
  12. //====================================================================  
  13. //====================================================================  
  14.   
  15. #ifndef OPENCV_CVX_TEXT_2007_08_31_H  
  16. #define OPENCV_CVX_TEXT_2007_08_31_H  
  17.   
  18. /** 
  19. * \file CvxText.h 
  20. * \brief OpenCV汉字输出接口 
  21. * 
  22. * 实现了汉字输出功能。 
  23. */  
  24.   
  25. #include <ft2build.h>  
  26. #include FT_FREETYPE_H  
  27.   
  28. #include <cv.h>  
  29. #include <highgui.h>  
  30.   
  31. /** 
  32. * \class CvxText 
  33. * \brief OpenCV中输出汉字 
  34. * 
  35. * OpenCV中输出汉字。字库提取采用了开源的FreeFype库。由于FreeFype是 
  36. * GPL版权发布的库,和OpenCV版权并不一致,因此目前还没有合并到OpenCV 
  37. * 扩展库中。 
  38. * 
  39. * 显示汉字的时候需要一个汉字字库文件,字库文件系统一般都自带了。 
  40. * 这里采用的是一个开源的字库:“文泉驿正黑体”。 
  41. * 
  42. * 关于"OpenCV扩展库"的细节请访问 
  43. * http://code.google.com/p/opencv-extension-library/ 
  44. * 
  45. * 关于FreeType的细节请访问 
  46. * http://www.freetype.org/ 
  47. * 
  48. * 例子: 
  49. * 
  50. * \code 
  51. int main(int argc, char *argv[]) 
  52. { 
  53.    // 定义CvxApplication对象 
  54.  
  55.    CvxApplication app(argc, argv); 
  56.  
  57.    // 打开一个影象 
  58.  
  59.    IplImage *img = cvLoadImage("test.jpg", 1); 
  60.  
  61.    // 输出汉字 
  62.  
  63.    { 
  64.       // "wqy-zenhei.ttf"为文泉驿正黑体 
  65.  
  66.       CvText text("wqy-zenhei.ttf"); 
  67.  
  68.       const char *msg = "在OpenCV中输出汉字!"; 
  69.  
  70.       float p = 0.5; 
  71.       text.setFont(NULL, NULL, NULL, &p);   // 透明处理 
  72.  
  73.       text.putText(img, msg, cvPoint(100, 150), CV_RGB(255,0,0)); 
  74.    } 
  75.    // 定义窗口,并显示影象 
  76.  
  77.    CvxWindow myWin("myWin"); 
  78.    myWin.showImage(img); 
  79.  
  80.    // 进入消息循环 
  81.  
  82.    return app.exec(); 
  83. } 
  84. * \endcode 
  85. */  
  86.   
  87. class CvxText    
  88. {  
  89.    // 禁止copy  
  90.   
  91.    CvxText& operator=(const CvxText&);  
  92.   
  93.    //================================================================  
  94.    //================================================================  
  95.   
  96. public:  
  97.   
  98.    /** 
  99.     * 装载字库文件 
  100.     */  
  101.   
  102.    CvxText(const char *freeType);  
  103.    virtual ~CvxText();  
  104.   
  105.    //================================================================  
  106.    //================================================================  
  107.   
  108.    /** 
  109.     * 获取字体。目前有些参数尚不支持。 
  110.     * 
  111.     * \param font        字体类型, 目前不支持 
  112.     * \param size        字体大小/空白比例/间隔比例/旋转角度 
  113.     * \param underline   下画线 
  114.     * \param diaphaneity 透明度 
  115.     * 
  116.     * \sa setFont, restoreFont 
  117.     */  
  118.   
  119.    void getFont(int *type,  
  120.       CvScalar *size=NULL, bool *underline=NULL, float *diaphaneity=NULL);  
  121.   
  122.    /** 
  123.     * 设置字体。目前有些参数尚不支持。 
  124.     * 
  125.     * \param font        字体类型, 目前不支持 
  126.     * \param size        字体大小/空白比例/间隔比例/旋转角度 
  127.     * \param underline   下画线 
  128.     * \param diaphaneity 透明度 
  129.     * 
  130.     * \sa getFont, restoreFont 
  131.     */  
  132.   
  133.    void setFont(int *type,  
  134.       CvScalar *size=NULL, bool *underline=NULL, float *diaphaneity=NULL);  
  135.   
  136.    /** 
  137.     * 恢复原始的字体设置。 
  138.     * 
  139.     * \sa getFont, setFont 
  140.     */  
  141.   
  142.    void restoreFont();  
  143.   
  144.    //================================================================  
  145.    //================================================================  
  146.   
  147.    /** 
  148.     * 输出汉字(颜色默认为黑色)。遇到不能输出的字符将停止。 
  149.     * 
  150.     * \param img  输出的影象 
  151.     * \param text 文本内容 
  152.     * \param pos  文本位置 
  153.     * 
  154.     * \return 返回成功输出的字符长度,失败返回-1。 
  155.     */  
  156.   
  157.    int putText(IplImage *img, const char    *text, CvPoint pos);  
  158.   
  159.    /** 
  160.     * 输出汉字(颜色默认为黑色)。遇到不能输出的字符将停止。 
  161.     * 
  162.     * \param img  输出的影象 
  163.     * \param text 文本内容 
  164.     * \param pos  文本位置 
  165.     * 
  166.     * \return 返回成功输出的字符长度,失败返回-1。 
  167.     */  
  168.   
  169.    int putText(IplImage *img, const wchar_t *text, CvPoint pos);  
  170.   
  171.    /** 
  172.     * 输出汉字。遇到不能输出的字符将停止。 
  173.     * 
  174.     * \param img   输出的影象 
  175.     * \param text  文本内容 
  176.     * \param pos   文本位置 
  177.     * \param color 文本颜色 
  178.     * 
  179.     * \return 返回成功输出的字符长度,失败返回-1。 
  180.     */  
  181.   
  182.    int putText(IplImage *img, const char    *text, CvPoint pos, CvScalar color);  
  183.   
  184.    /** 
  185.     * 输出汉字。遇到不能输出的字符将停止。 
  186.     * 
  187.     * \param img   输出的影象 
  188.     * \param text  文本内容 
  189.     * \param pos   文本位置 
  190.     * \param color 文本颜色 
  191.     * 
  192.     * \return 返回成功输出的字符长度,失败返回-1。 
  193.     */  
  194.    int putText(IplImage *img, const wchar_t *text, CvPoint pos, CvScalar color);  
  195.   
  196.    //================================================================  
  197.    //================================================================  
  198.   
  199. private:  
  200.   
  201.    // 输出当前字符, 更新m_pos位置  
  202.   
  203.    void putWChar(IplImage *img, wchar_t wc, CvPoint &pos, CvScalar color);  
  204.   
  205.    //================================================================  
  206.    //================================================================  
  207.   
  208. private:  
  209.   
  210.    FT_Library   m_library;   // 字库  
  211.    FT_Face      m_face;      // 字体  
  212.   
  213.    //================================================================  
  214.    //================================================================  
  215.   
  216.    // 默认的字体输出参数  
  217.   
  218.    int         m_fontType;  
  219.    CvScalar   m_fontSize;  
  220.    bool      m_fontUnderline;  
  221.    float      m_fontDiaphaneity;  
  222.   
  223.    //================================================================  
  224.    //================================================================  
  225. };  
  226.   
  227. #endif // OPENCV_CVX_TEXT_2007_08_31_H  
CvxText.cpp:

CvxText.cpp:

[cpp]  view plain copy
  1. #include <wchar.h>  
  2. #include <assert.h>  
  3. #include <locale.h>  
  4. #include <ctype.h>  
  5.   
  6. #include "CvxText.h"  
  7.   
  8. //====================================================================  
  9. //====================================================================  
  10.   
  11. // 打开字库  
  12.   
  13. CvxText::CvxText(const char *freeType)  
  14. {  
  15.    assert(freeType != NULL);  
  16.   
  17.    // 打开字库文件, 创建一个字体  
  18.   
  19.    if(FT_Init_FreeType(&m_library)) throw;  
  20.    if(FT_New_Face(m_library, freeType, 0, &m_face)) throw;  
  21.   
  22.    // 设置字体输出参数  
  23.   
  24.    restoreFont();  
  25.   
  26.    // 设置C语言的字符集环境  
  27.   
  28.    setlocale(LC_ALL, "");  
  29. }  
  30.   
  31. // 释放FreeType资源  
  32.   
  33. CvxText::~CvxText()  
  34. {  
  35.    FT_Done_Face    (m_face);  
  36.    FT_Done_FreeType(m_library);  
  37. }  
  38.   
  39. // 设置字体参数:  
  40. //  
  41. // font         - 字体类型, 目前不支持  
  42. // size         - 字体大小/空白比例/间隔比例/旋转角度  
  43. // underline   - 下画线  
  44. // diaphaneity   - 透明度  
  45.   
  46. void CvxText::getFont(int *type, CvScalar *size, bool *underline, float *diaphaneity)  
  47. {  
  48.    if(type) *type = m_fontType;  
  49.    if(size) *size = m_fontSize;  
  50.    if(underline) *underline = m_fontUnderline;  
  51.    if(diaphaneity) *diaphaneity = m_fontDiaphaneity;  
  52. }  
  53.   
  54. void CvxText::setFont(int *type, CvScalar *size, bool *underline, float *diaphaneity)  
  55. {  
  56.    // 参数合法性检查  
  57.   
  58.    if(type)  
  59.    {  
  60.       if(type >= 0) m_fontType = *type;  
  61.    }  
  62.    if(size)  
  63.    {  
  64.       m_fontSize.val[0] = fabs(size->val[0]);  
  65.       m_fontSize.val[1] = fabs(size->val[1]);  
  66.       m_fontSize.val[2] = fabs(size->val[2]);  
  67.       m_fontSize.val[3] = fabs(size->val[3]);  
  68.    }  
  69.    if(underline)  
  70.    {  
  71.       m_fontUnderline   = *underline;  
  72.    }  
  73.    if(diaphaneity)  
  74.    {  
  75.       m_fontDiaphaneity = *diaphaneity;  
  76.    }  
  77. }  
  78.   
  79. // 恢复原始的字体设置  
  80.   
  81. void CvxText::restoreFont()  
  82. {  
  83.    m_fontType = 0;            // 字体类型(不支持)  
  84.   
  85.    m_fontSize.val[0] = 20;      // 字体大小  
  86.    m_fontSize.val[1] = 0.5;   // 空白字符大小比例  
  87.    m_fontSize.val[2] = 0.1;   // 间隔大小比例  
  88.    m_fontSize.val[3] = 0;      // 旋转角度(不支持)  
  89.   
  90.    m_fontUnderline   = false;   // 下画线(不支持)  
  91.   
  92.    m_fontDiaphaneity = 1.0;   // 色彩比例(可产生透明效果)  
  93.   
  94.    // 设置字符大小  
  95.   
  96.    FT_Set_Pixel_Sizes(m_face, (int)m_fontSize.val[0], 0);  
  97. }  
  98.   
  99. // 输出函数(颜色默认为黑色)  
  100.   
  101. int CvxText::putText(IplImage *img, const char    *text, CvPoint pos)  
  102. {  
  103.    return putText(img, text, pos, CV_RGB(255,255,255));  
  104. }  
  105. int CvxText::putText(IplImage *img, const wchar_t *text, CvPoint pos)  
  106. {  
  107.    return putText(img, text, pos, CV_RGB(255,255,255));  
  108. }  
  109.   
  110. //  
  111.   
  112. int CvxText::putText(IplImage *img, const char    *text, CvPoint pos, CvScalar color)  
  113. {  
  114.    if(img == NULL) return -1;  
  115.    if(text == NULL) return -1;  
  116.   
  117.    //  
  118.   
  119.    int i;  
  120.    for(i = 0; text[i] != '\0'; ++i)  
  121.    {  
  122.       wchar_t wc = text[i];  
  123.   
  124.       // 解析双字节符号  
  125.   
  126.       if(!isascii(wc)) mbtowc(&wc, &text[i++], 2);  
  127.   
  128.       // 输出当前的字符  
  129.   
  130.       putWChar(img, wc, pos, color);  
  131.    }  
  132.    return i;  
  133. }  
  134. int CvxText::putText(IplImage *img, const wchar_t *text, CvPoint pos, CvScalar color)  
  135. {  
  136.    if(img == NULL) return -1;  
  137.    if(text == NULL) return -1;  
  138.   
  139.    //  
  140.   
  141.    int i;  
  142.    for(i = 0; text[i] != '\0'; ++i)  
  143.    {  
  144.       // 输出当前的字符  
  145.   
  146.       putWChar(img, text[i], pos, color);  
  147.    }  
  148.    return i;  
  149. }  
  150.   
  151. // 输出当前字符, 更新m_pos位置  
  152.   
  153. void CvxText::putWChar(IplImage *img, wchar_t wc, CvPoint &pos, CvScalar color)  
  154. {  
  155.    // 根据unicode生成字体的二值位图  
  156.   
  157.    FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);  
  158.    FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);  
  159.    FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_MONO);  
  160.   
  161.    //  
  162.   
  163.    FT_GlyphSlot slot = m_face->glyph;  
  164.   
  165.    // 行列数  
  166.   
  167.    int rows = slot->bitmap.rows;  
  168.    int cols = slot->bitmap.width;  
  169.   
  170.    //  
  171.   
  172.    for(int i = 0; i < rows; ++i)  
  173.    {  
  174.       for(int j = 0; j < cols; ++j)  
  175.       {  
  176.          int off  = ((img->origin==0)? i: (rows-1-i))  
  177.             * slot->bitmap.pitch + j/8;  
  178.   
  179.          if(slot->bitmap.buffer[off] & (0xC0 >> (j%8)))  
  180.          {  
  181.             int r = (img->origin==0)? pos.y - (rows-1-i): pos.y + i;;  
  182.             int c = pos.x + j;  
  183.            
  184.             if(r >= 0 && r < img->height  
  185.                && c >= 0 && c < img->width)  
  186.             {  
  187.                CvScalar scalar = cvGet2D(img, r, c);  
  188.   
  189.                // 进行色彩融合  
  190.   
  191.                float p = m_fontDiaphaneity;  
  192.                for(int k = 0; k < 4; ++k)  
  193.                {  
  194.                   scalar.val[k] = scalar.val[k]*(1-p) + color.val[k]*p;  
  195.                }  
  196.   
  197.                cvSet2D(img, r, c, scalar);  
  198.             }  
  199.          }  
  200.       } // end for  
  201.    } // end for  
  202.   
  203.    // 修改下一个字的输出位置  
  204.   
  205.    double space = m_fontSize.val[0]*m_fontSize.val[1];  
  206.    double sep   = m_fontSize.val[0]*m_fontSize.val[2];  
  207.   
  208.    pos.x += (int)((cols? cols: space) + sep);  
  209. }  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值