It's a bit tricky, but you can play with cv::getTextSize()
. There is a sample code in the description of the function but it only renders some text, the tight box (surrounding the text), and the baseline of it.
If you'd like to render the text in an arbitrary ROI of an image then you first need to render it into another image (which fits to the text size), resize it to the ROI desired and then put it over the image, such as below:
void PutText(cv::Mat& img, const std::string& text, const cv::Rect& roi, const cv::Scalar& color, int fontFace, double fontScale, int thickness = 1, int lineType = 8)
{
CV_Assert(!img.empty() && (img.type() == CV_8UC3 || img.type() == CV_8UC1));
CV_Assert(roi.area() > 0);
CV_Assert(!text.empty());
int baseline = 0;
// Calculates the width and height of a text string
cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseline);
// Y-coordinate of the baseline relative to the bottom-most text point
baseline += thickness;
// Render the text over here (fits to the text size)
cv::Mat textImg(textSize.height + baseline, textSize.width, img.type());
if (color == cv::Scalar::all(0)) textImg = cv::Scalar::all(255);
else textImg = cv::Scalar::all(0);
// Estimating the resolution of bounding image
cv::Point textOrg((textImg.cols - textSize.width) / 2, (textImg.rows + textSize.height - baseline) / 2);
// TR and BL points of the bounding box
cv::Point tr(textOrg.x, textOrg.y + baseline);
cv::Point bl(textOrg.x + textSize.width, textOrg.y - textSize.height);
cv::putText(textImg, text, textOrg, fontFace, fontScale, color, thickness);
// Resizing according to the ROI
cv::resize(textImg, textImg, roi.size());
cv::Mat textImgMask = textImg;
if (textImgMask.type() == CV_8UC3)
cv::cvtColor(textImgMask, textImgMask, cv::COLOR_BGR2GRAY);
// Creating the mask
cv::equalizeHist(textImgMask, textImgMask);
if (color == cv::Scalar::all(0)) cv::threshold(textImgMask, textImgMask, 1, 255, cv::THRESH_BINARY_INV);
else cv::threshold(textImgMask, textImgMask, 254, 255, cv::THRESH_BINARY);
// Put into the original image
cv::Mat destRoi = img(roi);
textImg.copyTo(destRoi, textImgMask);
}
And call it like:
cv::Mat image = cv::imread("C:/opencv_logo.png");
cv::Rect roi(5, 5, image.cols - 5, image.rows - 5);
cv::Scalar color(255, 0, 0);
int fontFace = cv::FONT_HERSHEY_SCRIPT_SIMPLEX;
double fontScale = 2.5;
int thickness = 2;
PutText(image, "OpenCV", roi, color, fontFace, fontScale, thickness);
As a result of the PutText()
function you can render any text over an arbitrary ROI of the image, such as:

Hope it helps and works :)
Update #1:
And keep in mind that text rendering (with or without this trick) in OpenCV is very expensive and can affect to the runtime of your applications. Other libraries may outperform the OpenCVs rendering system.