python - 在灰度低分辨率图像上书写文本
问题描述
我一直在尝试将文本写入 80x80 16 位灰度图像,但在让它工作时遇到了一些麻烦。
我目前正在使用:
image = im[0]/255.0 #where im is just an np array of images (which are 80x80 np arrays)
# font
font = cv2.FONT_HERSHEY_SIMPLEX
# org
org = (40, 15)
# fontScale
fontScale = 0.3
# Blue color in BGR
color = (255.0)
# Line thickness of 2 px
thickness = 1
# Using cv2.putText() method
image = cv2.putText(image, 'Out:16', org, font, fontScale, color, thickness, cv2.LINE_AA)
# Displaying the image
cv2.imshow(window_name, image)
然而,不仅文字看起来非常饱满并且占用了大量空间(如果它不清晰,我不能再往下走),除了文字是白色的,图像变得全黑。
是否有更好的方法将文本写入低分辨率图像(使文本更小)?为什么图像变成全黑?
编辑:
我尝试使用 ImageDraw() 并且结果都是灰色的
from PIL import Image, ImageFont, ImageDraw
# creating a image object
image = Image.fromarray(im[0]/255.0)
draw = ImageDraw.Draw(image)
# specified font size
font = ImageFont.truetype('./arial.ttf', 10)
text = 'fyp:16'
# drawing text size
draw.text((5, 5), text, font = font, align ="left")
解决方案
看起来主要问题是将图像类型转换为float
.
假设(请验证):
im[0]
是 16 位灰度,并且im[0].dtype
是dtype('uint16')
.
image = im[0]/255.0
表示您要将范围从 16 位灰度转换为uint8
.
注意:要将范围从 [0, 2^16-1] 转换为 [0, 255] 您需要除以(2**16-1)/255
= 257.0
。但这不是主要问题。
主要问题是将类型转换为float
. OpenCV
中图像的有效范围是 [0, 1]。
以上所有值都是白色像素,并且是灰色像素。float
1.0
0.5
您可以保留图像类型uint16
- 您不必将其转换为uint8
.
类型的白色文本颜色uint16
是2**16-1
= 65535
(不是 255)。
这是适用于 16 位灰度(和uint16
类型)的代码示例:
import numpy as np
import cv2
im = np.full((80, 80), 10000, np.uint16) # 16 bits grayscale synthetic image - set all pixels to 10000
cv2.circle(im, (40, 40), 10, 0, 20, cv2.LINE_8) # draw black cicle - synthetic image
#image = im[0]/255.0 #where im is just an np array of images (which are 80x80 np arrays)
image = im #where im is just an np array of images (which are 80x80 np arrays)
color = 2**16-1 # 65535 is white color for 16 bis image
# Using cv2.putText() method
image = cv2.putText(image, 'Out:16', (40, 15), cv2.FONT_HERSHEY_SIMPLEX, 0.3, color, 1, cv2.LINE_AA)
# Displaying the image
cv2.imshow("image", image)
cv2.waitKey()
上面的代码为测试创建了合成的 16 位灰度。
从 16 位灰度转换为 8 位灰度:
# https://stackoverflow.com/questions/11337499/how-to-convert-an-image-from-np-uint16-to-np-uint8
uint8_image = cv2.convertScaleAbs(image, alpha=255.0/(2**16-1)) # Convent uint16 image to uint8 image (2**16-1 scaled to 255)
上述转换假定image
为全范围 16 位(像素范围 [0, 65535])。
关于字体:
OpenCV 是面向计算机视觉的,文本绘制有限。
为什么图像是黑色的?
不知道 的值很难回答im[0]
。
- 可能
im[0]
根本不是 16 位灰度。 - 可能是 的值
im[0]
非常小。 - 可能的类型
im[0]
不是uint16
。
使用 Pillow (PIL) 绘制文本:
与 OpenCV 相比,小文本的质量要好得多。您可以在此处
找到有关质量文本渲染的信息。
继续上uint8
图:
pil_image = Image.fromarray(uint8_image)
draw = ImageDraw.Draw(pil_image)
# specified font size
font = ImageFont.truetype('./arial.ttf', 10)
text = 'fyp:16'
# drawing text size
draw.text((5, 5), text, 255, font = font, align ="left")
pil_image.show()
结果:
与上述结果相比,我真的不知道您的文本看起来连线的原因。
推荐阅读
- dns - google dns 查询响应翻译
- c++ - 关闭最右边的设置位
- r - 寓言可以协调分层时间序列,其中层次结构在不同节点处具有不同的深度?
- python - 如何添加 2 个点之间的距离(SRID = 32636)?
- javascript - JavaScript 中的逗号什么时候被认为是逗号运算符,什么时候不是?
- ffmpeg - 在ffmpeg中旋转文本
- php - 谷歌分析 api 在工作了几个月后突然停止返回数据
- java - 为什么我的中断()没有杀死我的线程?
- snowflake-cloud-data-platform - 在 Snowflake ACCOUNT_USAGE.METERING_HISTORY 视图中,WAREHOUSE_METERING 条目的 ENTITY_ID 字段是否始终等于 WAREHOUSE_ID?
- r - 如何在ggboxplot中添加自定义图例