Image Processing #7 - OpenCV Text
You can download the source codes here(https://github.com/raspberry-pi-maker/OpenCV)
Basic text output using putText
putText function Draws a text string.
-
Python:
cv2.
putText
(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) → None
cv.
PutText
(img, text, org, font, color) → None
Parameters: - img – Image.
- text – Text string to be drawn.
- org – Bottom-left corner of the text string in the image.
- font –
CvFont
structure initialized usingInitFont()
. - fontFace – Font type. One of
FONT_HERSHEY_SIMPLEX
,FONT_HERSHEY_PLAIN
,FONT_HERSHEY_DUPLEX
,FONT_HERSHEY_COMPLEX
,FONT_HERSHEY_TRIPLEX
,FONT_HERSHEY_COMPLEX_SMALL
,FONT_HERSHEY_SCRIPT_SIMPLEX
, orFONT_HERSHEY_SCRIPT_COMPLEX
, where each of the font ID’s can be combined withFONT_ITALIC
to get the slanted letters. - fontScale – Font scale factor that is multiplied by the font-specific base size.
- color – Text color.
- thickness – Thickness of the lines used to draw a text.
- lineType – Line type. See the
line
for details. - bottomLeftOrigin – When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner.
putText
renders the specified text string in the image.
Symbols that cannot be rendered using the specified font are
replaced by question marks. See
getTextSize()
for a text rendering code example.import argparse import numpy as np import cv2 parser = argparse.ArgumentParser(description="OpenCV Example") parser.add_argument("--thick", default = 3, type=int, help="font thickness") parser.add_argument("--scale", default = 2.0, type=float, help="font thickness") args = parser.parse_args() w = 640 h = 480 channel = 3 img = np.zeros((h, w, channel), np.uint8) red = (0, 0, 255) green = (0, 255, 0) blue = (255, 0, 0) white = (255, 255, 255) yellow = (0, 255, 255) cyan = (255, 255, 0) magenta = (255, 0, 255) y_pos = 50 location = (20, y_pos) font = cv2.FONT_HERSHEY_SCRIPT_SIMPLEX # hand-writing style font cv2.putText(img, 'Hello OpenCV', location, font, fontScale = args.scale, color = yellow, thickness = args.thick) location = (20, y_pos + 50) font = cv2.FONT_ITALIC # italic font cv2.putText(img, 'OpenCV Cooking', location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20, y_pos + 100) font = cv2.FONT_HERSHEY_SIMPLEX # normal size sans-serif font cv2.putText(img, 'Hello spypiggy', location, font, fontScale = args.scale, color = blue, thickness = args.thick) location = (20, y_pos + 150) font = cv2.FONT_HERSHEY_COMPLEX # normal size serif font cv2.putText(img, 'Hello NVIDIA Jetson ', location, font, fontScale = args.scale, color = green, thickness = args.thick) cv2.imshow("drawing", img) cv2.waitKey(0)
Run the code.
python exam6-1.py
Text line spacing does not match. And some text is out of bounds on the canvas. To solve this problem, you need to find out the size of text in the canvas, and then change the canvas size or adjust the font size.
Get text box size using getTextSize
Calculates the width and height of a text string.
Python:
cv2.
getTextSize
(text, fontFace, fontScale, thickness) → retval, baseLine
-
Python:
cv.
GetTextSize
(textString, font)-> (textSize, baseline) Parameters: - text – Input text string.
- text_string – Input text string in C format.
- fontFace – Font to use. See the
putText()
for details. - fontScale – Font scale. See the
putText()
for details. - thickness – Thickness of lines used to render the text. See
putText()
for details. - baseLine – Output parameter - y-coordinate of the baseline relative to the bottom-most text point.
- baseline – Output parameter - y-coordinate of the baseline relative to the bottom-most text point.
- font – Font description in terms of old C API.
- text_size – Output parameter - The size of a box that contains the specified text.
getTextSize
calculates and returns the size of a box that contains the specified text.
That is, the following code renders some text, the tight box surrounding it, and the baseline:Let's try to get the canvas size suitable for the text output before printing the text.
import argparse import numpy as np import cv2 parser = argparse.ArgumentParser(description="OpenCV Example") parser.add_argument("--thick", default = 3, type=int, help="font thickness") parser.add_argument("--scale", default = 2.0, type=float, help="font thickness") args = parser.parse_args() channel = 3 red = (0, 0, 255) green = (0, 255, 0) blue = (255, 0, 0) white = (255, 255, 255) yellow = (0, 255, 255) cyan = (255, 255, 0) magenta = (255, 0, 255) x_leading = 20 y_leading = 20 def get_canvas_size(text, font): y_pos = y_leading y_size = 0 x_size = 0 for t, f in zip(text, font): (label_width, label_height), baseline = cv2.getTextSize(t, f, fontScale = args.scale, thickness = args.thick) y_pos += (label_height + baseline + y_leading) if(label_width > x_size - x_leading): x_size = label_width + x_leading if(y_pos > y_size): y_size = y_pos print('canvas size : W[%d] H[%d]'%(x_size, y_size)) img = np.zeros((y_size, x_size, channel), np.uint8) return img text = ('Hello OpenCV', 'OpenCV Cooking', 'Hello spypiggy', 'Hello NVIDIA Jetson') font = (cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, cv2.FONT_ITALIC, cv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_COMPLEX) color = (red,green, blue, white) img = get_canvas_size(text, font) y_pos = 0 for t, f, c in zip(text, font, color): (label_width, label_height), baseline = cv2.getTextSize(t, f, fontScale = args.scale, thickness = args.thick) y_pos += label_height + baseline + y_leading location = (20, y_pos) cv2.putText(img, t, location, f, fontScale = args.scale, color = c, thickness = args.thick) cv2.imshow("drawing", img) cv2.waitKey(0)
Run the code.
python exam6-2.py
Now you can see the text is printed properly on the canvas of the right size.
Changing the background color using np.fill and cv2.merge functions
We used the np.zeros function to create a canvas with a black background. You can create canvases of various colors using the np.full function.
import argparse import numpy as np import cv2 parser = argparse.ArgumentParser(description="OpenCV Example") parser.add_argument("--thick", default = 3, type=int, help="font thickness") parser.add_argument("--scale", default = 2.0, type=float, help="font thickness") args = parser.parse_args() channel = 3 red = (0, 0, 255) green = (0, 255, 0) blue = (255, 0, 0) white = (255, 255, 255) yellow = (0, 255, 255) cyan = (255, 255, 0) magenta = (255, 0, 255) x_leading = 20 y_leading = 20 ''' This function get a color value for canvas background ''' def get_canvas_size(text, font, color): y_pos = y_leading y_size = 0 x_size = 0 for t, f in zip(text, font): (label_width, label_height), baseline = cv2.getTextSize(t, f, fontScale = args.scale, thickness = args.thick) y_pos += (label_height + baseline + y_leading) if(label_width > x_size - x_leading): x_size = label_width + x_leading if(y_pos > y_size): y_size = y_pos print('canvas size : W[%d] H[%d]'%(x_size, y_size)) B = np.full((y_size, x_size, 1), color[0], dtype=np.uint8) G = np.full((y_size, x_size, 1), color[1], dtype=np.uint8) R = np.full((y_size, x_size, 1), color[2], dtype=np.uint8) img = cv2.merge((B, G, R)) return img text = ('Hello OpenCV', 'OpenCV Cooking', 'Hello spypiggy', 'Hello NVIDIA Jetson') font = (cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, cv2.FONT_ITALIC, cv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_COMPLEX) color = (red,green, blue, white) img = get_canvas_size(text, font, yellow) y_pos = 0 for t, f, c in zip(text, font, color): (label_width, label_height), baseline = cv2.getTextSize(t, f, fontScale = args.scale, thickness = args.thick) y_pos += label_height + baseline + y_leading location = (20, y_pos) cv2.putText(img, t, location, f, fontScale = args.scale, color = c, thickness = args.thick) cv2.imshow("drawing", img) cv2.waitKey(0)
Run the code.
python exam6-3.py
Changing the text background color usingcv2.rectangle
We will use the cv2.getTextSize function we used earlier to fill in the rectangular area surrounding the text.
import argparse import numpy as np import cv2 parser = argparse.ArgumentParser(description="OpenCV Example") parser.add_argument("--thick", default = 3, type=int, help="font thickness") parser.add_argument("--scale", default = 2.0, type=float, help="font thickness") args = parser.parse_args() channel = 3 red = (0, 0, 255) green = (0, 255, 0) blue = (255, 0, 0) white = (255, 255, 255) yellow = (0, 255, 255) cyan = (255, 255, 0) magenta = (255, 0, 255) gray = (127, 127, 127,) x_leading = 20 y_leading = 20 ''' This function get a color value for canvas background ''' def get_canvas_size(text, font, color): y_pos = y_leading y_size = 0 x_size = 0 for t, f in zip(text, font): (label_width, label_height), baseline = cv2.getTextSize(t, f, fontScale = args.scale, thickness = args.thick) y_pos += (label_height + baseline + y_leading) if(label_width > x_size - x_leading): x_size = label_width + x_leading if(y_pos > y_size): y_size = y_pos print('canvas size : W[%d] H[%d]'%(x_size, y_size)) B = np.full((y_size, x_size, 1), color[0], dtype=np.uint8) G = np.full((y_size, x_size, 1), color[1], dtype=np.uint8) R = np.full((y_size, x_size, 1), color[2], dtype=np.uint8) img = cv2.merge((B, G, R)) return img text = ('Hello OpenCV', 'OpenCV Cooking', 'Hello spypiggy', 'Hello NVIDIA Jetson') font = (cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, cv2.FONT_ITALIC, cv2.FONT_HERSHEY_SIMPLEX, cv2.FONT_HERSHEY_COMPLEX) color = (red,green, blue, white) img = get_canvas_size(text, font, yellow) y_pos = 0 box_offset_x = 10 box_offset_y = 10 rectangle_bgr = gray for t, f, c in zip(text, font, color): (label_width, label_height), baseline = cv2.getTextSize(t, f, fontScale = args.scale, thickness = args.thick) y_pos += label_height + baseline + y_leading location = (x_leading, y_pos) box_coords = ((x_leading - box_offset_x , y_pos - (label_height + baseline ) ), (x_leading + label_width , y_pos + box_offset_y)) cv2.rectangle(img, box_coords[0], box_coords[1], rectangle_bgr, cv2.FILLED) cv2.putText(img, t, location, f, fontScale = args.scale, color = c, thickness = args.thick) cv2.imshow("drawing", img) cv2.waitKey(0)
Run the code.
python exam6-4.py
Outline Text using multiple cv2.putText
You can create a outline text by adjusting the cv2.putText function's org parameter a little bit forward, backward, left, or right.
#-*- coding:utf-8 -*- import argparse import numpy as np import cv2 parser = argparse.ArgumentParser(description="OpenCV Example") parser.add_argument("--thick", default = 4, type=int, help="font thickness") parser.add_argument("--scale", default = 4.0, type=float, help="font thickness") args = parser.parse_args() w = 640 h = 480 channel = 3 img = np.zeros((h, w, channel), np.uint8) red = (0, 0, 255) green = (0, 255, 0) blue = (255, 0, 0) white = (255, 255, 255) yellow = (0, 255, 255) cyan = (255, 255, 0) magenta = (255, 0, 255) x_leading = 20 y_leading = 20 def get_canvas_size(t, f): y_pos = y_leading y_size = 0 x_size = 0 (label_width, label_height), baseline = cv2.getTextSize(t, f, fontScale = args.scale, thickness = args.thick) y_pos += (label_height + baseline + y_leading) if(label_width > x_size - x_leading): x_size = label_width + x_leading if(y_pos > y_size): y_size = y_pos print('canvas size : W[%d] H[%d]'%(x_size, y_size)) img = np.zeros((y_size, x_size, channel), np.uint8) return img text = 'Hello OpenCV' font = cv2.FONT_HERSHEY_COMPLEX img = get_canvas_size(text, font) y_pos = 0 thick = 4 (label_width, label_height), baseline = cv2.getTextSize(text, font, fontScale = args.scale, thickness = args.thick) y_pos += label_height + baseline + y_leading location = (20 - thick, y_pos) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20 + thick, y_pos) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20, y_pos - thick) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20, y_pos + thick) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20 - thick, y_pos - thick) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20 + thick, y_pos + thick) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20 - thick, y_pos - thick) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20 + thick, y_pos + thick) cv2.putText(img, text, location, font, fontScale = args.scale, color = red, thickness = args.thick) location = (20 , y_pos) cv2.putText(img, text, location, font, fontScale = args.scale, color = white, thickness = args.thick) cv2.imshow("drawing", img) cv2.waitKey(0)
Run the code.
python exam6-5.py
Be Careful : OpenCV does not support text output using various fonts. PIL is a good way to print text using a variety of fonts such as "Arial, Hevetica, ..". For text output using PIL, see my other post https://opencvcooking.blogspot.com/2019/12/basic-cooking-2-pil-text.html. If you want to print non-English characters, you should use PIL, which allows you to directly call fonts containing those characters.
댓글
댓글 쓰기