我从类型为“numpy.uint16”的相机获取图像,我将其转换为 255 位,如下所示:
imax2 = np.amax(self.data)
if imax2 > 0:
imul2 = int(65535/imax2)
self.data = self.data*imul2
data2 = (self.data/256).astype('u2')
其中 self.data 是我在 tkinter 标签(称为 liveMain)上显示的图像的 numpy 数组,如下所示:
img = Image.fromarray(data2)
imgtk = ImageTk.PhotoImage(image=img)
self.liveMain.imgtk = imgtk
self.liveMain.config(image=imgtk)
我想在图像上的饱和像素上显示一个红色遮罩,但我不知道该怎么做。欢迎任何想法。谢谢。
用红色标记饱和像素的方法比较简单
我无法验证该示例是否与您的相机完美匹配,因为您没有共享示例图像(您可能必须选择较低的饱和度阈值)。
以下解决方案主要使用NumPy:
构建一个蒙版(NumPy 数组),在图像饱和的地方使用
True
,在不饱和的地方使用 False
:
sat_mask = data > saturation_threshold
将图像从单通道(灰度)转换为 RGB(3 个颜色通道),其中 red=green=blue(假设输入为灰度):
data2_rgb = np.dstack((data2, data2, data2))
在掩码正确的地方涂上红色:
data2_rgb[sat_mask] = np.array([255, 0, 0], np.uint8) # [255, 0, 0] applies red color, in case the image is uint16, use [65535, 0, 0].
代码示例(请阅读评论):
from PIL import Image
import numpy as np
# Build uint16 grayscale Tiff image out of uint8 JPEG image, for testing.
################################################################################
img8 = Image.open('maxresdefault.jpg').convert('L') # Read image and convert to Grayscale.
img16 = Image.fromarray(np.asarray(img8).astype(np.uint16)*255)
img16.save('uint16_img.tif')
################################################################################
uint16_img = Image.open('uint16_img.tif') # Read input image (uint16 grayscale)
data = np.asarray(uint16_img) # Convert to NumPy array - assume data applies self.data from the question
# Select a threshold, that above it, a pixel is considered saturated
# The threshold is specific to the camera (may by 4000 for example - we can't know from the correct value from question).
saturation_threshold = 50000
# Build a mask (NumPy array) with True where images is saturated, and False where not.
sat_mask = data > saturation_threshold
imax2 = np.amax(data) # 64770
if imax2 > 0:
scale = 255.0/imax2
#data2 = (data.astype(float) * scale).astype('u2')
# For making the solution less confusing, convert data2 to uint8 type
# When displaying and image, uint8 is prefered, since the display uses 8 bits per color channel (unless using HDR, but that irrelevant for the answer).
data2 = (data.astype(float) * scale).astype('uint8')
else:
data2 = data2.astype('uint8')
# Converting from single channel (grayscale) to RGB (3 color channels) where red=green=blue (we need RGB for marking with red).
data2_rgb = np.dstack((data2, data2, data2))
#sat_mask = np.dstack((sat_mask, sat_mask, sat_mask))
# Put red color where mask is True
data2_rgb[sat_mask] = np.array([255, 0, 0], np.uint8) # [255, 0, 0] applies red color, in case the image is uint16, use [65535, 0, 0].
Image.fromarray(np.asarray(data2_rgb)).save('data2_rgb.png') # Save image for testing
if False:
# Display the image in tkinter...
img = Image.fromarray(data2_rgb)
imgtk = ImageTk.PhotoImage(image=img)
self.liveMain.imgtk = imgtk
self.liveMain.config(image=imgtk)
输入图像(
maxresdefault.jpg
):