14

I want to write to an image a formatted text. OpenCV offers only a limited set of default fonts. Is it possible to use others? For example to read them from the *.ttf file (in Ubuntu)?

user1592546
  • 1,480
  • 1
  • 14
  • 30
  • Have a look at the link http://opencv.willowgarage.com/documentation/cpp/drawing_functions.html#cv-puttext – G453 Aug 11 '12 at 20:20

2 Answers2

13

If you cannot or don't want to use the Qt bindings, here is a way to do it with CAIRO:

#include <opencv2/opencv.hpp>
#include <cairo/cairo.h>
#include <string>

void putTextCairo(
        cv::Mat &targetImage,
        std::string const& text,
        cv::Point2d centerPoint,
        std::string const& fontFace,
        double fontSize,
        cv::Scalar textColor,
        bool fontItalic,
        bool fontBold)
{
    // Create Cairo
    cairo_surface_t* surface =
            cairo_image_surface_create(
                CAIRO_FORMAT_ARGB32,
                targetImage.cols,
                targetImage.rows);

    cairo_t* cairo = cairo_create(surface);

    // Wrap Cairo with a Mat
    cv::Mat cairoTarget(
                cairo_image_surface_get_height(surface),
                cairo_image_surface_get_width(surface),
                CV_8UC4,
                cairo_image_surface_get_data(surface),
                cairo_image_surface_get_stride(surface));

    // Put image onto Cairo
    cv::cvtColor(targetImage, cairoTarget, cv::COLOR_BGR2BGRA);

    // Set font and write text
    cairo_select_font_face(
                cairo,
                fontFace.c_str(),
                fontItalic ? CAIRO_FONT_SLANT_ITALIC : CAIRO_FONT_SLANT_NORMAL,
                fontBold ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);

    cairo_set_font_size(cairo, fontSize);
    cairo_set_source_rgb(cairo, textColor[2], textColor[1], textColor[0]);

    cairo_text_extents_t extents;
    cairo_text_extents(cairo, text.c_str(), &extents);

    cairo_move_to(
                cairo,
                centerPoint.x - extents.width/2 - extents.x_bearing,
                centerPoint.y - extents.height/2- extents.y_bearing);
    cairo_show_text(cairo, text.c_str());

    // Copy the data to the output image
    cv::cvtColor(cairoTarget, targetImage, cv::COLOR_BGRA2BGR);

    cairo_destroy(cairo);
    cairo_surface_destroy(surface);
}

Example call:

putTextCairo(mat, "Hello World", cv::Point2d(50,50), "arial", 15, cv::Scalar(0,0,255), false, false);

It assumes that the target image is BGR.

It puts the text's center to the given point. If you want some different positioning, you have to modify the cairo_move_to call.

isarandi
  • 3,120
  • 25
  • 35
  • Thanks for the tip. But is 'centerAnchor' referring to 'centerPoint'? And how can we install the Cairo in Ubuntu 16.04? – user1098761 May 25 '17 at 01:13
  • 1
    @user1098761 `sudo apt install libcairo2-dev`. If you are using CMake, you can follow this answer https://stackoverflow.com/questions/41636886/cairo-library-and-cmake . I used FindCairo.cmake from WebKit. – Ondrej Galbavý Feb 14 '18 at 10:22
3

It's possible to use other fonts but you need to link the Qt library to OpenCV and use the cvAddText function with a cvFontQt

http://docs.opencv.org/modules/highgui/doc/qt_new_functions.html#addtext

http://docs.opencv.org/modules/highgui/doc/qt_new_functions.html#fontqt

There are other solutions you might try, with more or less the same performance as OpenCV. For instance, you can use CAIRO to write fonts into the image.

Andris
  • 921
  • 7
  • 14
Nikko
  • 4,182
  • 1
  • 26
  • 44