首页 > 解决方案 > 在灰度低分辨率图像上书写文本

问题描述

我一直在尝试将文本写入 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")

在此处输入图像描述

标签: pythonopencv

解决方案


看起来主要问题是将图像类型转换为float.

假设(请验证):
im[0]是 16 位灰度,并且im[0].dtypedtype('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.00.5


您可以保留图像类型uint16- 您不必将其转换为uint8.
类型的白色文本颜色uint162**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()

结果:

在此处输入图像描述

与上述结果相比,我真的不知道您的文本看起来连线的原因。


推荐阅读