我想在cv::Mat
上添加一些文字,但cv::putText()
对我来说不够灵活。
我需要将可变长度的标签放在运行时已知的几个像素位置,但由于cv::putText()
将输出的原点始终放在左边,我的文字会消失在图像边框之外,如果位置在左边太远了。
我找不到cv::putText()
的替代品。有没有?
我只需要以像素为单位知道输出文本的宽度和高度就足够了,所以我可以自己调整位置。
更好的方法是我可以将文本的原点指定为右侧,左侧或中间(垂直和水平)。
作为奖励,我想用轮廓绘制文字,例如带有黑色轮廓的白色字符,以便您可以在任何背景上阅读它们。
答案 0 :(得分:3)
以下是使用freetype与OpenCV的示例:
#include "opencv2/opencv.hpp"
#include "ft2build.h"
#include FT_FREETYPE_H
FT_Library library;
FT_Face face;
using namespace cv;
using namespace std;
//-----------------------------------------------------------------------
void my_draw_bitmap(Mat& img,FT_Bitmap* bitmap,int x,int y, Scalar color)
{
Scalar src_col,dst_col;
for(int i=0;i<bitmap->rows;i++)
{
for(int j=0;j<bitmap->width;j++)
{
unsigned char val=bitmap->buffer[j+i*bitmap->pitch];
float mix=(float)val/255.0;
if(val!=0)
{
src_col=Scalar(img.at<Vec3b>(i+y,j+x));
dst_col=mix*color+(1.0-mix)*src_col;
img.at<Vec3b>(i+y,j+x)=Vec3b(dst_col[0],dst_col[1],dst_col[2]);
}
}
}
}
//-----------------------------------------------------------------------
float PrintString(Mat& img,std::wstring str,int x,int y,Scalar color)
{
FT_Bool use_kerning=0;
FT_UInt previous=0;
use_kerning = FT_HAS_KERNING( face );
float prev_yadv=0;
float posx=0;
float posy=0;
float dx=0;
for(int k=0;k<str.length();k++)
{
int glyph_index = FT_Get_Char_Index( face, str.c_str()[k] );
FT_GlyphSlot slot = face->glyph; // a small shortcut
if(k>0){dx=slot->advance.x/64; }
FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
FT_Render_Glyph (slot,FT_RENDER_MODE_NORMAL);
prev_yadv=slot->metrics.vertAdvance/64;
if ( use_kerning && previous && glyph_index )
{
FT_Vector delta;
FT_Get_Kerning( face, previous, glyph_index, FT_KERNING_DEFAULT, &delta );
posx += (delta.x/64);
}
posx+=(dx);
my_draw_bitmap(img,&slot->bitmap,posx+x+ slot->bitmap_left,y - slot->bitmap_top+posy,color);
previous = glyph_index;
}
return prev_yadv;
}
//-----------------------------------------------------------------------
void PrintText(Mat& img,std::wstring str,int x,int y,Scalar color)
{
float posy=0;
for(int pos=str.find_first_of(L'\n');pos!=wstring::npos;pos=str.find_first_of(L'\n'))
{
std::wstring substr=str.substr(0,pos);
str.erase(0,pos+1);
posy+=PrintString(img,substr,x,y+posy, color);
}
PrintString(img,str,x,y+posy,color);
}
//-----------------------------------------------------------------------
int main(int argc, char* argv[])
{
FT_Init_FreeType( &library );
FT_New_Face( library,"arial.ttf",0,&face );
FT_Set_Pixel_Sizes(face,24,0);
FT_Select_Charmap(face, FT_ENCODING_UNICODE);
Mat img=imread("D:/ImagesForTest/lena.jpg");
std::wstring str= L"Мой дядя самых честных правил,\n\
Когда не в шутку занемог,\n\
Он уважать себя заставил \n\
И лучше выдумать не мог.\n\
Его пример другим наука;\n\
Но, боже мой, какая скука\n\
С больным сидеть и день и ночь,\n\
Не отходя ни шагу прочь!\n\
Какое низкое коварство\n\
Полу-живого забавлять,\n\
Ему подушки поправлять,\n\
Печально подносить лекарство,\n\
Вздыхать и думать про себя:\n\
Когда же чёрт возьмет тебя!\n";
PrintText(img,str,100,50,Scalar(0,255,255));
cv::imshow("win",img);
cv::waitKey(0);
return 0;
}