在饱和区域的灰度图像上的彩色遮罩。

huangapple go评论59阅读模式
英文:

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)

# 保存图像以进行测试
# ...

输入图像(maxresdefault.jpg):
在饱和区域的灰度图像上的彩色遮罩。

输出图像:
在饱和区域的灰度图像上的彩色遮罩。

英文:

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, and False 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)

Input image (maxresdefault.jpg):
在饱和区域的灰度图像上的彩色遮罩。

Output image:
在饱和区域的灰度图像上的彩色遮罩。

huangapple
  • 本文由 发表于 2023年3月10日 01:04:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687811.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定