I want to put some text on a cv::Mat
, but cv::putText()
is not flexible enough for me.
I need to put labels of variable length at several pixel positions which are known at runtime, but since cv::putText()
places the origin of the output always on the left, my text disappears beyond the image borders, if the position is too far on the left.
I could not find alternatives to cv::putText()
. Are there any?
It would suffice for me to know the width and height of the output text in pixels, so I could adjust the position myself.
Even better would be a method where I could specify the origin of my text to be at the right, left or middle (vertically and horizontally).
As a bonus I'd like to draw text with contours, e.g. white characters with black contours, so that you can read them on any background.
Here is the example of using freetype with 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;
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加