如何创建边界框并将文本放入其中?
Posted
技术标签:
【中文标题】如何创建边界框并将文本放入其中?【英文标题】:How can I create a bounding box and fit text into it? 【发布时间】:2022-01-05 04:16:58 【问题描述】:我正在尝试将文本放入边界框。 基本上该函数的输入是:
-
文本 -> 字符串(以','分隔的单词列表)
width -> int(框的设置宽度)
示例 1:
** 如果所有文本都可以在边界框内并在一行中,则保持这种方式
输入: “测试,测试2,测试3”,100它应该输出如下内容:
示例 2:
** 如果文本不能在一行中放入框内,则会使框变大(高度)并继续向下写一行
输入: "test, test2, test3, test4, test5", 100它应该输出如下内容:
示例 3:
** 如果以','
分隔的字符串列表中最长的字符串不能放入一行中的框中,则会使文本变小
它应该输出如下内容:
另一个例子:
我想要一些提示/帮助, 谢谢。
【问题讨论】:
【参考方案1】:我又尝试了一次,我做到了!
代码如下:
def fit_text(text, text_size, text_color, max_horizontal_chars, box_outline_color, box_background_color,
box_outline_width, font_file, word_bank_outline, high_res):
"""
:param text: The text that needs to be fir inside the bounding box (words separated by ,)
:type text: str
:param text_size: The size of the text
:type text_size: int
:param text_color: The color of the text
:type text_color: Tuple(int, int, int) | str
:param max_horizontal_chars: The number of the max horizontal chars allowed in one line
:type max_horizontal_chars: int
:param box_outline_color: The color of the outline of the bounding box
:type box_outline_color: Tuple(int, int, int) | str
:param box_background_color: The color of the background of the bounding box
:type box_background_color: Tuple(int, int, int) | str
:param box_outline_width: The thickness of the outline of the bounding box
:type box_outline_width: int
:param font_file: The file of the font of the text
:type font_file: str
:param word_bank_outline: Whether there will be an outline or not
:type word_bank_outline: bool
:return: The image
:rtype: Image
"""
multiplier = 2
text_size *= multiplier //2
# Replaces every ',' to '-' because the wrapper library will associate '-' as a separator and sorts by length
text = text.split(',')
text.sort(key=len, reverse=True)
text = ','.join(text).upper()
text = text.replace(',', '-')
# Changes the text size to fit the box if the longest word cannot fit in one line
font = ImageFont.truetype(font_file, text_size)
longest_word = sorted(text.split('-'), key=len)[-1]
if longest_word[0] == ' ':
longest_word = longest_word[1:]
longest_word_size = font.getsize(longest_word)[0]
while longest_word_size >= 1100:
longest_word = sorted(text.split('-'), key=len)[-1]
if longest_word[0] == ' ':
longest_word = longest_word[1:]
longest_word_size = font.getsize(longest_word)[0]
text_size -= 1
font = ImageFont.truetype(font_file, text_size)
# Initializes the text wrapper
wrapper = textwrap.TextWrapper()
wrapper.max_lines = 3
wrapper.placeholder = '...'
wrapper.break_long_words = False
wrapper.width = max_horizontal_chars
# Wrap the text
text = wrapper.fill(text=text)
# Create a new image according to the size of the text
img = Image.new('RGBA', (font.getsize_multiline(text)[0], (font.getsize_multiline(text)[1]+20+(60 if high_res else 20)+box_outline_width+(text.count('\n')*10))), (0,0,0,0))
# Initializes the ImageDraw.Draw for the img so I can draw on it
draw = ImageDraw.Draw(im=img)
# If word_bank_outline is true it will draw a bunch or rectangles according to box_outline_width
if word_bank_outline:
w, h = img.size
for i in range(0, box_outline_width):
shape = [(0 + i, 0 + i), (w - i, h - i)]
draw.rectangle(shape, box_background_color, box_outline_color)
# Replaces every '-' back to ','
text = text.replace('-', ',').upper()
# Checks if the first char is ' ' if it is it will be cut out
if text[0] == ' ':
text = text[1:]
# Draws the text onto the bounding box
draw.multiline_text(xy=(10 + (20 if high_res else 0), 0), text=text, font=font, fill=text_color, spacing=20)
return img
基本上实现它的主要因素是函数ttffont.getsize
,它以像素为单位返回字符串的大小,因此我可以知道字符串的确切大小,我可以更准确地适应它,另一件事是库textwraper
将文本分成单独的行。
所以首先它会检查字符串中最长的单词是否可以容纳在边界框内,如果不是,它将循环并减小文本大小直到它适合 然后它会调用 textwrapper.fill 来分割文本,然后它只会在图像上绘制文本并绘制轮廓,然后它会返回图像。
最终结果:
【讨论】:
如果您确切指出解决问题的更改以及解决问题的原因,答案会更好。 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。 感谢 Matthew 的反馈,我稍微改变了答案。现在答案好不好?我需要添加更多信息或其他任何内容吗?以上是关于如何创建边界框并将文本放入其中?的主要内容,如果未能解决你的问题,请参考以下文章
如何在堆栈上创建大小为 x 的数组并将 scanf 值放入其中
如何在Word周围绘制边界框并将其保存在文件夹opencv python中