英文:
Mask of color on gray scale image for saturated areas
问题
我从相机获取类型为 '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 是图像的 NumPy 数组,我将其显示在一个名为 liveMain 的 tkinter 标签上,方法如下:
img = Image.fromarray(data2)
imgtk = ImageTk.PhotoImage(image=img)
self.liveMain.imgtk = imgtk
self.liveMain.config(image=imgtk)
我想在饱和像素上显示一个红色蒙版,但我不知道如何做。欢迎任何建议。谢谢。
英文:
i get images from a camera in type 'numpy.uint16' that i transform to 255 bits like so:
imax2 = np.amax(self.data)
if imax2 > 0:
imul2 = int(65535/imax2)
self.data = self.data*imul2
data2 = (self.data/256).astype('u2')
where self.data is the numpy array of the image that i show on a tkinter label (called liveMain) like so:
img = Image.fromarray(data2)
imgtk = ImageTk.PhotoImage(image=img)
self.liveMain.imgtk = imgtk
self.liveMain.config(image=imgtk)
I want to show a red mask over the image on the saturated pixels and i don´t know how. any idea is welcome. Thanks.
答案1
得分: 1
标记饱和像素为红色的方法相对简单。由于您没有分享示例图像(您可能需要选择较低的饱和度阈值),我无法验证示例是否完全匹配您的相机。
以下解决方案主要使用NumPy:
- 创建一个遮罩(NumPy数组),其中
True
表示图像饱和,False
表示非饱和:
sat_mask = data > saturation_threshold
- 将图像从单通道(灰度)转换为RGB(3个颜色通道),其中红色=绿色=蓝色(假设输入是灰度图像):
data2_rgb = np.dstack((data2, data2, data2))
- 在遮罩为
True
的位置放置红色:
data2_rgb[sat_mask] = np.array([255, 0, 0], np.uint8) # [255, 0, 0]表示红色,如果图像是uint16,则使用[65535, 0, 0]。
代码示例(请阅读注释):
from PIL import Image
import numpy as np
# 创建一个uint16灰度Tiff图像,用于测试。
# ...
# 读取输入图像(uint16灰度)
# ...
# 选择一个阈值,高于该阈值,像素被视为饱和
saturation_threshold = 50000
# 创建一个遮罩,其中True表示图像饱和,False表示非饱和
sat_mask = data > saturation_threshold
# 将图像从单通道(灰度)转换为RGB,其中红色=绿色=蓝色
data2_rgb = np.dstack((data2, data2, data2))
# 在遮罩为True的位置放置红色
data2_rgb[sat_mask] = np.array([255, 0, 0], np.uint8)
# 保存图像以进行测试
# ...
英文:
The method for marking saturated pixels with red color is relatively simple.
I can't verify that the example perfectly matches your camera, because you didn't share a sample image (you probably have to select a lower saturation threshold).
The following solution uses mainly NumPy:
-
Build a mask (NumPy array) with
True
where images is saturated, andFalse
where not:sat_mask = data > saturation_threshold
-
Convert the image from single channel (grayscale) to RGB (3 color channels) where red=green=blue (assume the input is grayscale):
data2_rgb = np.dstack((data2, data2, data2))
-
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].
Code sample (please read the comments):
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论