由于Opencv默认不显示中文,所以我们需要通过需要通过一些库来设置OpenCV支持中文显示
源码下载链接:Ubuntu下Opencv显示中文
代码说明
项目需要ft2build.h,它是freetype库中的一个头文件。所以在shell中执行下列语句安装freetype:
sudo apt-get install libfreetype6-dev
然后使用下列语句查找ft2build.h并在cmake中链接即可:
sudo find / -name ft2build.h
simhei.ttf是字体文件,可以在windows系统直接进行索引,更换自己喜爱的默认字体即可。
结果
源码解析
由于下载需要积分,所以将源码粘贴出来
cmake文件
cmake_minimum_required(VERSION 3.12)
project(chinese)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenCV REQUIRED)
message(STATUS ${OpenCV_LIBRARY_DIRS})
include_directories(
/usr/include/freetype2/
${OpenCV_INCLUDE_DIRS}
)
#link_directories(${OpenCV_LIBRARY_DIRS} )
add_executable(chinese main.cpp CvxText.cpp CvxText.h)
target_link_libraries(chinese ${OpenCV_LIBS} freetype)
CvxText.h
#ifndef OPENCV_CVX_TEXT_HPP_
#define OPENCV_CVX_TEXT_HPP_
#include <ft2build.h>
#include FT_FREETYPE_H
#include <opencv2/opencv.hpp>
class CvxText
{
public
:
CvxText(const char* freeType
);
virtual
~CvxText();
void getFont(int* type
, cv
::Scalar
* size
=nullptr
, bool
* underline
=nullptr
, float* diaphaneity
=nullptr
);
void setFont(int* type
, cv
::Scalar
* size
=nullptr
, bool
* underline
=nullptr
, float* diaphaneity
=nullptr
);
void restoreFont();
int putText(cv
::Mat
& img
, char* text
, cv
::Point pos
);
int putText(cv
::Mat
& img
, const wchar_t
* text
, cv
::Point pos
);
int putText(cv
::Mat
& img
, const char* text
, cv
::Point pos
, cv
::Scalar color
);
int putText(cv
::Mat
& img
, const wchar_t
* text
, cv
::Point pos
, cv
::Scalar color
);
private
:
CvxText
& operator
=(const CvxText
&);
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
CvxText.cpp
#include <wchar.h>
#include <assert.h>
#include <locale.h>
#include <ctype.h>
#include <cmath>
#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();
setlocale(LC_ALL
, "");
}
CvxText
::~CvxText()
{
FT_Done_Face(m_face
);
FT_Done_FreeType(m_library
);
}
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
, 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
;
}
void CvxText
::putWChar(cv
::Mat
& img
, wchar_t wc
, cv
::Point
& pos
, cv
::Scalar color
)
{
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
);
}
main.cpp
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <vector>
#include "opencv2/opencv.hpp"
#include "time.h"
#include "CvxText.h"
static int ToWchar(char* &src
, wchar_t
* &dest
, const char *locale
= "zh_CN.utf8")
{
if (src
== NULL) {
dest
= NULL;
return 0;
}
setlocale(LC_CTYPE
, locale
);
int w_size
= mbstowcs(NULL, src
, 0) + 1;
if (w_size
== 0) {
dest
= NULL;
return -1;
}
dest
= new wchar_t
[w_size
];
if (!dest
) {
return -1;
}
int ret
= mbstowcs(dest
, src
, strlen(src
)+1);
if (ret
<= 0) {
return -1;
}
return 0;
}
int main()
{
cv
::Mat img
= cv
::imread("./demo.jpg");
if (!img
.data
|| img
.channels() != 3) {
fprintf(stderr, "read image fail\n");
return -1;
}
CvxText
text("./simhei.ttf");
cv
::Scalar size1
{ 80, 0.5, 0.1, 0 };
text
.setFont(nullptr
, &size1
, nullptr
, 0);
char* str
= (char *)"你好,李家网";
wchar_t
*w_str
;
ToWchar(str
,w_str
);
text
.putText(img
, w_str
, cv
::Point(50,100), cv
::Scalar(0, 0, 255));
cv
::resize(img
, img
, cv
::Size(300,300));
cv
::imshow("demo", img
);
cv
::waitKey(0);
cv
::imwrite("./res.jpg", img
);
return 0;
}