-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
jiasibo
committed
May 9, 2017
1 parent
2293afc
commit 5f2e19a
Showing
10 changed files
with
1,270 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
cmake_minimum_required(VERSION 3.8) | ||
project(cvUniText) | ||
|
||
set(CMAKE_CXX_STANDARD 11) | ||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -O3") | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -O3") | ||
include_directories(/usr/include/freetype2/) | ||
find_package( OpenCV REQUIRED ) | ||
|
||
add_library(cvunitext SHARED cvUniText.cpp) | ||
add_executable(main test.cpp) | ||
target_link_libraries(main cvunitext) | ||
target_link_libraries(cvunitext freetype ${OpenCV_LIBS}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
#include "cvUniText.hpp" | ||
#include <cstdio> | ||
#include "utf8.h" | ||
#include <ft2build.h> | ||
#include <freetype/freetype.h> | ||
|
||
using namespace uni_text; | ||
|
||
namespace uni_text { | ||
class Impl { | ||
public: | ||
Impl(const std::string &font_face, int font_size); | ||
|
||
~Impl(); | ||
|
||
void SetParam(int font_size, float interval_ratio = 0.1, float whitespace_ratio = 0.3, float alpha = 1); | ||
|
||
cv::Rect PutText(cv::Mat &img, const std::string &text, cv::Point &org, | ||
cv::Scalar &color, bool calc_size); | ||
|
||
private: | ||
cv::Rect _cvPutUniTextUCS2(cv::Mat &img, const std::u16string &text, | ||
cv::Point &org, cv::Scalar &color, bool calc_size); | ||
|
||
double _cvPutUniChar(cv::Mat &img, char16_t wc, | ||
cv::Point &pos, cv::Scalar &color, bool calc_size); | ||
|
||
FT_Library m_library; | ||
FT_Face m_face; | ||
int m_fontType; | ||
cv::Scalar m_fontSize; | ||
float m_fontDiaphaneity; | ||
}; | ||
} | ||
|
||
UniText::UniText(const std::string &font_face, int font_size) { | ||
pimpl = std::unique_ptr<Impl>(new Impl(font_face, font_size)); | ||
} | ||
|
||
UniText::~UniText() = default; | ||
|
||
void UniText::SetParam(int font_size, float interval_ratio, float whitespace_ratio, float alpha) { | ||
pimpl->SetParam(font_size, interval_ratio, whitespace_ratio, alpha); | ||
} | ||
|
||
cv::Rect UniText::PutText(cv::Mat& img, const std::string& text, cv::Point& org, | ||
cv::Scalar& color, bool calc_size) { | ||
return pimpl->PutText(img, text, org, color, calc_size); | ||
} | ||
|
||
Impl::Impl(const std::string& font_face, int font_size) { | ||
if (FT_Init_FreeType(&m_library) != 0) { | ||
fprintf(stderr, "Freetype init failed!\n"); | ||
abort(); | ||
} | ||
|
||
if (FT_New_Face(m_library, font_face.c_str(), 0, &m_face) != 0) { | ||
fprintf(stderr, "Freetype font load failed!\n"); | ||
abort(); | ||
} | ||
|
||
m_fontType = 0; | ||
m_fontSize[0] = font_size; //FontSize | ||
m_fontSize[1] = 0.5; //whitechar ratio, such like ' ' | ||
m_fontSize[2] = 0.1; //inverval ratio, for each char. | ||
m_fontDiaphaneity = 1;//alpha | ||
|
||
FT_Set_Pixel_Sizes(m_face, (int) m_fontSize[0], 0); | ||
} | ||
|
||
Impl::~Impl() { | ||
FT_Done_Face(m_face); | ||
FT_Done_FreeType(m_library); | ||
} | ||
|
||
void Impl::SetParam(int font_size, float interval_ratio, float whitespace_ratio, float alpha) { | ||
m_fontSize[0] = font_size; //FontSize | ||
m_fontSize[1] = whitespace_ratio; //whitechar ratio, such like ' ' | ||
m_fontSize[2] = interval_ratio; //inverval ratio, for each char. | ||
m_fontDiaphaneity = alpha;//alpha | ||
FT_Set_Pixel_Sizes(m_face, (int) m_fontSize[0], 0); | ||
} | ||
|
||
double Impl::_cvPutUniChar(cv::Mat& img, char16_t wc, | ||
cv::Point& pos, cv::Scalar& color, bool calc_size) { | ||
// generate font bitmap from unicode | ||
FT_GlyphSlot ft_slot; | ||
// int ft_ascender; | ||
int ft_bmp_height; | ||
int ft_bmp_width;//0 when ' ' | ||
int ft_bmp_step; | ||
int ft_bmp_left; | ||
int ft_bmp_top; | ||
unsigned char *ft_bmp_buffer; | ||
|
||
|
||
double whitespace_width; | ||
double interval_width; | ||
double horizontal_offset; | ||
|
||
// | ||
// img coordinate | ||
// 0------+ x | ||
// | | ||
// + | ||
// y | ||
// | ||
//freetype bmp coordinate | ||
// y | ||
// + | ||
// | | ||
// 0------+ x | ||
// | ||
//freetype algin | ||
// 'a' | ||
// -+- -+- | ||
// | | | ||
// |height |top | ||
// | | | ||
// -baseline-: -+- -+- | ||
// | ||
// 'g' | ||
// -+- -+- | ||
// | | | ||
// | |top | ||
// | | | ||
// -baseline-: |height -+- | ||
// | | ||
// -+- | ||
// | ||
|
||
//get font_id from database of char | ||
// ft_ascender = m_face->size->metrics.ascender / 64; | ||
|
||
FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc); | ||
//load bitmap font to slot | ||
FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT); | ||
//render to 8bits | ||
FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL); | ||
ft_slot = m_face->glyph; | ||
ft_bmp_width = ft_slot->bitmap.width; | ||
ft_bmp_height = ft_slot->bitmap.rows; | ||
ft_bmp_step = ft_slot->bitmap.pitch; | ||
ft_bmp_buffer = ft_slot->bitmap.buffer; | ||
ft_bmp_left = ft_slot->bitmap_left; | ||
ft_bmp_top = ft_slot->bitmap_top; | ||
|
||
#ifdef CVUNITEXT_DEBUG | ||
if (wc < 256) { | ||
printf(" %c: ", ((char*)&wc)[0]); | ||
} else { | ||
printf(" 0x%02x%02x: ", ((char*)&wc)[1] & 0xFF, ((char*)&wc)[0] & 0xFF); | ||
} | ||
printf("width %4d, height %4d, ", ft_bmp_width, ft_bmp_height); | ||
printf("left %4d, ", ft_bmp_left); | ||
printf("top %4d, ", ft_bmp_top); | ||
printf("\n"); | ||
#endif | ||
|
||
//calculate char width | ||
whitespace_width = m_fontSize[0] * m_fontSize[1]; | ||
interval_width = m_fontSize[0] * m_fontSize[2]; | ||
if (ft_bmp_width != 0) { | ||
horizontal_offset = ft_bmp_width + interval_width; | ||
} else { | ||
horizontal_offset = whitespace_width; | ||
} | ||
|
||
int loc_x = pos.x + ft_bmp_left; | ||
int loc_y = pos.y + ft_bmp_height - ft_bmp_top; | ||
|
||
if (calc_size) { | ||
return horizontal_offset; | ||
} | ||
|
||
//draw font bitmap to opencv image | ||
//(bmp_j,bmp_i) is freetype bitmap location | ||
for (int bmp_i = 0; bmp_i < ft_bmp_height; ++bmp_i) { | ||
for (int bmp_j = 0; bmp_j < ft_bmp_width; ++bmp_j) { | ||
int bmp_valoff = bmp_i * ft_bmp_step + bmp_j; | ||
unsigned int bmp_val = ft_bmp_buffer[bmp_valoff]; | ||
float bmp_valf = (float) bmp_val / 255 * m_fontDiaphaneity; | ||
if (bmp_val == 0) { | ||
continue; | ||
} | ||
//(img_x,img_y) is opencv bitmap location | ||
int img_y = loc_y - (ft_bmp_height - 1 - bmp_i); | ||
int img_x = loc_x + bmp_j; | ||
|
||
//update pixel when location is valid | ||
// alpha = font_bitmap_val / 255; | ||
// pixel = alpha * color + (1 - alpha) * pixel; | ||
if ((0 <= img_y) && (img_y < img.rows) && (0 <= img_x) && (img_x < img.cols)) { | ||
unsigned char *data = img.ptr<unsigned char>(img_y); | ||
for (int img_channel = 0; img_channel < img.channels(); img_channel++) { | ||
data[img_x * img.channels() + img_channel] = | ||
(1 - bmp_valf) * data[img_x * img.channels() + img_channel] + | ||
bmp_valf * color[img_channel]; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return horizontal_offset; | ||
} | ||
|
||
cv::Rect Impl::_cvPutUniTextUCS2(cv::Mat& img, const std::u16string& text, | ||
cv::Point& org, cv::Scalar& color, bool calc_size) { | ||
cv::Point pt0 = org; | ||
cv::Point pt1 = org; | ||
double offset; | ||
cv::Rect rect; | ||
int ascender = m_face->size->metrics.ascender / 64; | ||
int descender = m_face->size->metrics.descender / 64; | ||
|
||
for (unsigned int i = 0; i < text.size(); i++) { | ||
offset = _cvPutUniChar(img, text[i], pt1, color, calc_size); | ||
pt1.x += (int) offset; | ||
} | ||
rect.width = pt1.x - pt0.x; | ||
rect.height = ascender - descender; | ||
rect.x = pt0.x; | ||
rect.y = pt0.y - descender; | ||
return rect; | ||
} | ||
|
||
cv::Rect Impl::PutText(cv::Mat& img, const std::string& text, cv::Point &org, | ||
cv::Scalar& color, bool calc_size) { | ||
// std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; | ||
// std::u16string dest = convert.from_bytes(text); | ||
std::u16string dest; | ||
utf8::utf8to32(text.begin(), text.end(), std::back_inserter(dest)); | ||
cv::Rect sz = _cvPutUniTextUCS2(img, dest, org, color, calc_size); | ||
return sz; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef CV_UNI_TEXT_HPP | ||
#define CV_UNI_TEXT_HPP | ||
#include <opencv2/opencv.hpp> | ||
#include <string> | ||
#include <memory> | ||
|
||
namespace uni_text { | ||
class Impl; | ||
|
||
class UniText { | ||
public: | ||
/// Initialization | ||
/// \param font_face: the file path of your font | ||
/// \param font_size | ||
UniText(const std::string &font_face, int font_size); | ||
~UniText(); | ||
|
||
/// Detailed parameter of text rendering. Call this before drawing the text | ||
/// \param font_size | ||
/// \param interval_ratio: Ratio of character interval over character width | ||
/// \param whitespace_ratio: Ratio of whitespace width over character width | ||
/// \param alpha: Transparency. 1 means totally opaque. | ||
void SetParam(int font_size, float interval_ratio = 0.1, float whitespace_ratio = 0.5, float alpha = 1); | ||
|
||
/// Draw text on an Opencv Mat | ||
/// \param img | ||
/// \param utf8_text: Text encoded in utf8. (if it is hardcoded, make sure your source file is saved | ||
/// with utf8 encoding. | ||
/// \param org: The left-bottom point of the text. Notice some letters like 'g' may go under this point | ||
/// \param color | ||
/// \param calc_size: true -> return rect. False -> return rect and draw text. | ||
/// Useful e.g. when you want to draw a rectangle under the text | ||
/// \return The precise bounding box of the text in the image | ||
cv::Rect PutText(cv::Mat &img, const std::string &utf8_text, cv::Point &org, | ||
cv::Scalar &color, bool calc_size); | ||
|
||
private: | ||
/// Hide implementations | ||
std::unique_ptr<Impl> pimpl; | ||
}; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#ifndef CV_UNI_TEXT_HPP | ||
#define CV_UNI_TEXT_HPP | ||
#include <opencv2/opencv.hpp> | ||
#include <string> | ||
#include <memory> | ||
|
||
namespace uni_text { | ||
class Impl; | ||
|
||
class UniText { | ||
public: | ||
/// Initialization | ||
/// \param font_face: the file path of your font | ||
/// \param font_size | ||
UniText(const std::string &font_face, int font_size); | ||
~UniText(); | ||
|
||
/// Detailed parameter of text rendering. Call this before drawing the text | ||
/// \param font_size | ||
/// \param interval_ratio: Ratio of character interval over character width | ||
/// \param whitespace_ratio: Ratio of whitespace width over character width | ||
/// \param alpha: Transparency. 1 means totally opaque. | ||
void SetParam(int font_size, float interval_ratio = 0.1, float whitespace_ratio = 0.5, float alpha = 1); | ||
|
||
/// Draw text on an Opencv Mat | ||
/// \param img | ||
/// \param utf8_text: Text encoded in utf8. (if it is hardcoded, make sure your source file is saved | ||
/// with utf8 encoding. | ||
/// \param org: The left-bottom point of the text. Notice some letters like 'g' may go under this point | ||
/// \param color | ||
/// \param calc_size: true -> return rect. False -> return rect and draw text. | ||
/// Useful e.g. when you want to draw a rectangle under the text | ||
/// \return The precise bounding box of the text in the image | ||
cv::Rect PutText(cv::Mat &img, const std::string &utf8_text, cv::Point &org, | ||
cv::Scalar &color, bool calc_size); | ||
|
||
private: | ||
/// Hide implementations | ||
std::unique_ptr<Impl> pimpl; | ||
}; | ||
} | ||
|
||
#endif |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// Created by mini on 2017/5/8. | ||
// | ||
|
||
#include <opencv2/opencv.hpp> | ||
#include "cvUniText.hpp" | ||
#include <iostream> | ||
|
||
int main() { | ||
cv::Mat img = cv::imread("/home/jiasibo/1.jpg"); | ||
uni_text::UniText uniText("/usr/share/fonts/wqy-microhei/wqy-microhei.ttc", 80); | ||
cv::Point p(100, 100); | ||
cv::Scalar color(0,255,0); | ||
cv::Rect rect = uniText.PutText(img, "Hello, 哈哈哈哈哈嗝", p, color, false); | ||
std::cout << rect << std::endl; | ||
cv::imwrite("1.jpg", img); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright 2006 Nemanja Trifunovic | ||
|
||
/* | ||
Permission is hereby granted, free of charge, to any person or organization | ||
obtaining a copy of the software and accompanying documentation covered by | ||
this license (the "Software") to use, reproduce, display, distribute, | ||
execute, and transmit the Software, and to prepare derivative works of the | ||
Software, and to permit third-parties to whom the Software is furnished to | ||
do so, all subject to the following: | ||
The copyright notices in the Software and this entire statement, including | ||
the above license grant, this restriction and the following disclaimer, | ||
must be included in all copies of the Software, in whole or in part, and | ||
all derivative works of the Software, unless such copies or derivative | ||
works are solely in the form of machine-executable object code generated by | ||
a source language processor. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
DEALINGS IN THE SOFTWARE. | ||
*/ | ||
|
||
|
||
#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 | ||
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 | ||
|
||
#include "utf8/checked.h" | ||
#include "utf8/unchecked.h" | ||
|
||
#endif // header guard |
Oops, something went wrong.