python - 使用 Jetson.utils.cudaFont.OverlayText() 函数时,如何处理非典型英语的字母?
问题描述
我正在尝试制作一个检测对象然后将对象名称翻译成丹麦语的程序,但是当将翻译文本覆盖在图像本身上时,英语中找不到的字母,例如Æ,Ø和Å,总是出现非常糟糕(例如 fængsel 显示为 fÃ|ngsel)。在命令行中,我打印出我放入函数参数中的文本,它在命令提示符下很好,但在覆盖在图像上时很糟糕。
我正在使用 python 3 并拥有 Nvidia Jetson nano。
这是在图像上覆盖不正确文本的行。
font.OverlayText(img, width, height, "{:05.2f}% {:s}".format(confidence * 100, translateText(class_desc, "da")), 5, 5, font.White, font.Gray40)
translateText() 是一个单独的函数,您可以在其中输入要翻译的文本和语言,它会返回一个我检查过的字符串是否正确
字体定义为
font = jetson.utils.cudaFont()
解决方案
您正在输入cudafont
UTF-8 编码的文本。查看源代码,似乎没有任何东西可以处理 UTF-8 - 甚至,如果我没看错的话,也没有任何东西可以将字体中的自然字形顺序重新编码为常规编码:
char c = str[n];
if( c < FirstGlyph || c > LastGlyph )
continue;
c -= FirstGlyph;
... now c will hold glyph data for a character
(来自函数int4 cudaFont::TextExtents
)
这意味着该库在其字符处理方面严重受损。
在以下上下文中,字形仅表示“可以与现有字符或字符组合相关联的特定图像(即,连字“fi”是表示两个字符“f”和“i”的单个字形). 字体还必须定义一种编码(内置的,通过某种约定,例如 PostScript Type 1 字体,或者,在 TrueType/OpenType 字体的情况下,在它们的cmap
表中定义)以将字符代码与其正确的字形相关联.
CUDA 的默认字体 DejaVu Sans 和 DejaVu Sans Mono 是 TrueType 字体并且确实包含一个cmap
表格,因此它们的字形在物理上可以是任意随机顺序——这取决于字体设计者的判断。一种字体可以首先列出它的所有 A 字形,然后是所有 B 字形,依此类推,或者按字面上的任何顺序列出。如果字体包含 Latin-1 的编码表,则该表将在相应字形的字符代码A
和字体的字形位置之间进行转换。如果相同的字体还包含完全不同的编码,例如 EBCDIC,它自己的代码A
(不是基于 ASCII,因此不是“通常的”0x41,而是 0xC1)仍将指向字体中的相同A
字形。
做什么cudafont
完全是另一回事。它假定至少基本 ASCII的字形完全按照该顺序出现,从字体中的第一个字形开始。这意味着除了字体设计者强加的字形顺序之外,您不能使用任何其他字形顺序。此外,由于cudafont
将字符代码限制为仅 8 位,因此您无法访问 6,107 (DejaVu Sans) 和 3,309 (DejaVu Sans Mono) 字符中的任何字符,ASCII 代码 256 之前范围内的字符除外。
我简要浏览了字形集,在我看来它们是按Unicode 顺序排列的。现在,幸运的是(对于cudafont
s 程序员),这确实意味着前 95 个字符是按 ASCII 顺序排列的。
不幸的是,我的西欧读者(通常对 Latin-1 边界之外的任何东西都不感兴趣)——下一个仍然遵循常见的ISO/IEC 8859-1顺序,但是按照惯例,缺少从 0x7F 到 0x9F 的范围。在基于原始 Latin-1 的 Unicode Latin-1 Supplement 中,这些代码表示控制代码并且没有字形表示。
这仍然意味着您无法将 Python 的默认 UTF-8 编码字符串输入其中,但除了纯 ASCII 之外,您也无法指示 Python 将您的文本编码为 Latin-1。Python可以对其进行编码:
text = 'fængsel'
print (text)
print (text.encode('latin-1'))
fængsel
b'f\xe6ngsel'
但由于缺少范围,显示的字符在列表中仅出现 33 个字形:ć
.
解决方案:中间缺少 33 个字符,因此您可以调整(现在)二进制字符串内容以再次匹配物理字形顺序:
btext = bytes([c if c <= 0x7f else c-33 for c in text.encode('latin-1')])
print (btext)
b'f\xc5ngsel'
并且该字符串应该(理论上)最终呈现您的fængsel
.
任何想要访问超出此修复范围的字形的假设用户都不走运,直到cudafont
更新为 (a) 正确使用字体的编码,以及 (b) 支持完整的 Unicode 范围而不是char
仅支持 s。至少它得到了一个简短的提及stb_truetype.h
:
// Todo:
// 非 MS cmaps
推荐阅读
- android - 如何创建具有两行和动态项目宽度的水平回收视图
- python - 继承和循环导入的问题
- matlab - 如何剖析文件路径并保持扩展Matlab
- laravel - 我已经通过 make:auth 生成了用户登录和注册,现在我想更新详细信息
- javascript - 如何在 JavaScript 中向 ContextualWeb 图像搜索 API 发出 GET 请求?
- python - 无法在 Python 中将图像重塑为二维数组
- azure-devops - 如何在 Azure DevOps 的拉取请求中显示构建状态
- javascript - 使用 if 语句过滤具有多个字符串值的数据
- javascript - 单击表单提交后选项卡按钮不起作用
- python - 如何将当前 pgAdmin 用户或当前 DB 用户记录到文件中?