zoukankan      html  css  js  c++  java
  • 利用OpenCV给图像添加中文标注

     利用OpenCV给图像添加中文标注 :

    参考:
    http://blog.sina.com.cn/s/blog_6bbd2dd101012dbh.html  和
    https://blog.csdn.net/ubunfans/article/details/45719009

    OpenCV不支持汉字输出,参考了网上的相关内容,将解决步骤简要记录如下:
    1、从 http://download.savannah.gnu.org/releases/freetype/ 下载FreeType库,windows下,根据自己用的编译器版本,打开相应的工程文件。比如,我用的VS2008,则打开目录 uildswin32vc2008 下的工程文件,编译成功,关闭工程退出。
    2、编译成功后,在工具->选项->C++目录中添加freetype下的include文件夹以及lib文件夹,将objswin32vc2008中的库文件添加到当前工程的附加依赖项中。
    3、参考opencv中文论坛这篇帖子: http://www.opencv.org.cn/forum/viewtopic.php?f=1&t=2083&hilit=汉字 直接copy前两个源码文件,保存为CvxText.h和CvxText.cpp,分别添加到当前工程中。
    4、接下来就可以直接调用函数了,最简单的例子:

           IplImage *img = cvLoadImage("test.jpg", 1);      
           CvxText text("simsun.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));
    这样就可以往图像test.jpg中坐标为(100,150)的位置添加红色的“汉字”二字啦。

    //-----------------------------------------------------------------------------
    注意:需要显示的图片一定是IplImage的 下面是Opencv Mat与Iplimage的相互转换:
    1、将Mat转换为IplImage
    //! converts header to IplImage; no data is copied
        operator IplImage() const;
    举例:Mat img;
                IplImage *src;
                 src=&IplImage(img);


    2、将IplImage转换为Mat
    //! converts old-style IplImage to the new matrix; the data is not copied by default
        Mat(const IplImage* img, bool copyData=false);
    //-----------------------------------------------------------------------------------------------
    CvxText.h 代码:
    // CvxText.h
    #ifndef OPENCV_CVX_TEXT_2007_08_31_H
    #define OPENCV_CVX_TEXT_2007_08_31_H
    #include <ft2build.h>
    #include FT_FREETYPE_H
    #include<opencv.hpp>
     
    class CvxText  
    {
       CvxText& operator=(const CvxText&);
    public:
       CvxText(const char *freeType);
       virtual ~CvxText();
       void getFont(int *type,
          CvScalar *size=NULL, bool *underline=NULL, float *diaphaneity=NULL);
       void setFont(int *type,
          CvScalar *size=NULL, bool *underline=NULL, float *diaphaneity=NULL);
       void restoreFont();

       int putText(IplImage *img, const char    *text, CvPoint pos);
       int putText(IplImage *img, const wchar_t *text, CvPoint pos);
       int putText(IplImage *img, const char    *text, CvPoint pos, CvScalar color);
       int putText(IplImage *img, const wchar_t *text, CvPoint pos, CvScalar color);
    private:
       void putWChar(IplImage *img, wchar_t wc, CvPoint &pos, CvScalar color);
    private:
       FT_Library   m_library;   // 字á?库a
       FT_Face      m_face;      // 字á?体??
       int         m_fontType;
       CvScalar   m_fontSize;
       bool      m_fontUnderline;
       float      m_fontDiaphaneity;
    };


    CvxText.cpp 代码:
        #include <wchar.h>
        #include <assert.h>
        #include <locale.h>
        #include <ctype.h>
        #include "CvxText.h"

        // 打开字库
        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, 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;
           }
        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(IplImage *img, const char    *text, CvPoint pos)
        {
           return putText(img, text, pos, CV_RGB(255,255,255));
        }
        int CvxText::putText(IplImage *img, const wchar_t *text, CvPoint pos)
        {
           return putText(img, text, pos, CV_RGB(255,255,255));
        }
        
        int CvxText::putText(IplImage *img, const char    *text, CvPoint pos, CvScalar color)
        {
           if(img == NULL) return -1;
           if(text == NULL) return -1;
        
           int i;
           for(i = 0; text[i] != ''; ++i)
           {
              wchar_t wc = text[i];
              // 解析双字节符号
              if(!isascii(wc)) mbtowc(&wc, &text[i++], 2);
              // 输出当前的字符
              putWChar(img, wc, pos, color);
           }
           return i;
        }
        int CvxText::putText(IplImage *img, const wchar_t *text, CvPoint pos, CvScalar color)
        {
           if(img == NULL) return -1;
           if(text == NULL) return -1;
           int i;
           for(i = 0; text[i] != ''; ++i)
           {
              // 输出当前的字符
              putWChar(img, text[i], pos, color);
           }
           return i;
        }
         
        // 输出当前字符, 更新m_pos位置
        void CvxText::putWChar(IplImage *img, wchar_t wc, CvPoint &pos, CvScalar 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  = ((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);
                    }
                 }
              }
           }
         
           // 修改下一个字的输出位置
           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);
        }

    //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    freetype下载和配置
    https://blog.csdn.net/xufeng0991/article/details/40735651
    一 下载编译freetype库

    1 下载
    地址:http://www.freetype.org/
    得到压缩文件:freetype-2.5.3.tar.gz

    2 解压:
    直接解压,得到目录freetype-2.5.3

    3 编译:
    用vs2010打开:(路径)freetype-2.5.3uildswindowsvc2010freetype.sln

    二 将freetype库添加到工程
    1 添加包含目录
    依次点击:Project->properties->VC++directories->Include Directories
    添加:(路径)freetype-2.5.3include

    2 添加库目录
    依次点击:Project->properties->VC++directories->Library Directories
    添加:(路径)freetype-2.5.3objswin32vc2010

    3 添加附加依赖项
    依次点击:Project->properties->Linker->Input->Additional Dependencies
    添加:(路径)freetype253.lib;freetype253_D.lib

    三 测试
    运行以下代码:

        #include <ft2build.h>
        #include FT_FREETYPE_H
        #include <iostream>
        using namespace std;
         
        int main()
        {
            FT_Library library;
            FT_Init_FreeType(&library);
        
            FT_Face face;
            FT_New_Face(library, "msyh.ttf", 0, &face);
        
            cout<<"num_glyphs:"<<face->num_glyphs<<endl;
            cout<<"num_faces:"<<face->num_faces<<endl;
            system("Pause");
            return 0;
        }
    能编译运行,就一切ok了

    //---------------------------------------------------------------------
    Opencv310图片Mat中叠加汉字(freetype+VS2015)
    https://blog.csdn.net/zmdsjtu/article/details/53133223

  • 相关阅读:
    Fidder4 顶部提示 “The system proxy was changed,click to reenable fiddler capture”。
    redis 哨兵 sentinel master slave 连接建立过程
    虚拟点赞浏览功能的大数据量测试
    python基础练习题(题目 字母识词)
    python基础练习题(题目 回文数)
    python基础练习题(题目 递归求等差数列)
    python基础练习题(题目 递归输出)
    python基础练习题(题目 递归求阶乘)
    python基础练习题(题目 阶乘求和)
    python基础练习题(题目 斐波那契数列II)
  • 原文地址:https://www.cnblogs.com/qiantao/p/9441328.html
Copyright © 2011-2022 走看看