簡體   English   中英

OpenCV putText() 換行符

[英]OpenCV putText() new line character

我正在使用 cv2.putText() 在圖像上繪制文本字符串。

當我寫:

cv2.putText(img, "This is \n some text", (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, 2)

圖片上繪制的文字是:

This is? some text

我期待文本打印在新行中,因為\n是換行符的轉義字符,但它會繪制? 而是在圖像上。

為什么會這樣? 難道我做錯了什么?

不幸的是putText不能正確處理\\n符號。 請參閱相關的拒絕拉取請求 您需要自己拆分文本並進行幾次putText調用,例如:

text = "This is \n some text"
y0, dy = 50, 4
for i, line in enumerate(text.split('\n')):
    y = y0 + i*dy
    cv2.putText(img, line, (50, y ), cv2.FONT_HERSHEY_SIMPLEX, 1, 2)

這是另一個例子:

https://gist.github.com/EricCousineau-TRI/596f04c83da9b82d0389d3ea1d782592

基本上,與 elyase 的答案相同,但也使用getTextSize() (盡管我不得不將行大小增加到比預期大一點)。

elyase 提出的方法在 OpenCV 4.5.1.38 中對我很有效。 我確實驗證了文本字符串仍然可以用“+”連接,並且可以使用“str(value)”插入數值。 換行符的開頭只是加上“\\n”,一切都按預期進行。

y0, dy, text = 185,50, "FPS: "+str(framerate)+"\nMIN: "+str(frMIN)+"\nMAX: "+str(frMAX)+"\nAVG: "+str(frAVG)
for i, line in enumerate(text.split('\n')):
    y = y0 + i*dy
    cv2.putText(currStack, line, (50, y ), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA, False)

我為這個海豚寫了一個實用程序 function:

from typing import Optional, Tuple

import cv2
import numpy as np


def add_text_to_image(
    image_rgb: np.ndarray,
    label: str,
    top_left_xy: Tuple = (0, 0),
    font_scale: float = 1,
    font_thickness: float = 1,
    font_face=cv2.FONT_HERSHEY_SIMPLEX,
    font_color_rgb: Tuple = (0, 0, 255),
    bg_color_rgb: Optional[Tuple] = None,
    outline_color_rgb: Optional[Tuple] = None,
    line_spacing: float = 1,
):
    """
    Adds text (including multi line text) to images.
    You can also control background color, outline color, and line spacing.

    outline color and line spacing adopted from: https://gist.github.com/EricCousineau-TRI/596f04c83da9b82d0389d3ea1d782592
    """
    OUTLINE_FONT_THICKNESS = 3 * font_thickness

    im_h, im_w = image_rgb.shape[:2]

    for line in label.splitlines():
        x, y = top_left_xy

        # ====== get text size
        if outline_color_rgb is None:
            get_text_size_font_thickness = font_thickness
        else:
            get_text_size_font_thickness = OUTLINE_FONT_THICKNESS

        (line_width, line_height_no_baseline), baseline = cv2.getTextSize(
            line,
            font_face,
            font_scale,
            get_text_size_font_thickness,
        )
        line_height = line_height_no_baseline + baseline

        if bg_color_rgb is not None and line:
            # === get actual mask sizes with regard to image crop
            if im_h - (y + line_height) <= 0:
                sz_h = max(im_h - y, 0)
            else:
                sz_h = line_height

            if im_w - (x + line_width) <= 0:
                sz_w = max(im_w - x, 0)
            else:
                sz_w = line_width

            # ==== add mask to image
            if sz_h > 0 and sz_w > 0:
                bg_mask = np.zeros((sz_h, sz_w, 3), np.uint8)
                bg_mask[:, :] = np.array(bg_color_rgb)
                image_rgb[
                    y : y + sz_h,
                    x : x + sz_w,
                ] = bg_mask

        # === add outline text to image
        if outline_color_rgb is not None:
            image_rgb = cv2.putText(
                image_rgb,
                line,
                (x, y + line_height_no_baseline),  # putText start bottom-left
                font_face,
                font_scale,
                outline_color_rgb,
                OUTLINE_FONT_THICKNESS,
                cv2.LINE_AA,
            )
        # === add text to image
        image_rgb = cv2.putText(
            image_rgb,
            line,
            (x, y + line_height_no_baseline),  # putText start bottom-left
            font_face,
            font_scale,
            font_color_rgb,
            font_thickness,
            cv2.LINE_AA,
        )
        top_left_xy = (x, y + int(line_height * line_spacing))

    return image_rgb

以下是示例結果:

image = 200 * np.ones((550, 410, 3), dtype=np.uint8)

image = add_text_to_image(
    image,
    "Testing \nDouble new line\n\nLine too longggggggggggggggggggggg",
)
image = add_text_to_image(
    image,
    "Testing with font scale",
    font_scale=0.5,
    font_color_rgb=(0, 255, 0),
    top_left_xy=(0, 150),
)
image = add_text_to_image(
    image,
    "Testing with bg \nDouble new line\n\nLine too longggggggggggggggggggggg",
    bg_color_rgb=(255, 255, 255),
    font_color_rgb=(255, 0, 0),
    top_left_xy=(0, 200),
)
image = add_text_to_image(
    image,
    "Testing with line specing\nand outline",
    font_color_rgb=(0, 255, 255),
    outline_color_rgb=(0, 0, 0),
    top_left_xy=(0, 350),
    line_spacing=1.5,
)
import matplotlib.pyplot as plt
plt.imshow(image)
plt.show()

代碼結果

如果要將多行數據添加到視頻幀中,則必須添加多行putText(),即使上述帶for循環的答案僅適用於圖像,而不適用於創建視頻時通過代碼。

您可以做的是在python中使用“ exec”函數,該函數將字符串作為輸入並將其呈現到代碼中。

因此,我建議通過使用for循環附加所有行來創建一個小的python代碼段作為字符串,並在所需的位置執行它,它也將顯示在不同的位置。 這種情況對我來說可以為視頻添加數據。

stringexec = ""
m=0
for i in TextList:
    stringexec = steval+"cv2.putText(frame, TextList[" + str(TextList.index(i))+"], (100, 100+"+str(m)+"), cv2.FONT_HERSHEY_COMPLEX, 0.5, (200, 100, 100), 1, cv2.LINE_AA)\n"
    m += 100
exec(stringexec)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM