饱和区域的灰度图像颜色掩码

问题描述 投票:0回答:1

我从类型为“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)

我想在图像上的饱和像素上显示一个红色遮罩,但我不知道该怎么做。欢迎任何想法。谢谢。

python image python-imaging-library cv2
1个回答
0
投票

用红色标记饱和像素的方法比较简单
我无法验证该示例是否与您的相机完美匹配,因为您没有共享示例图像(您可能必须选择较低的饱和度阈值)。

以下解决方案主要使用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
):

输出图像:

© www.soinside.com 2019 - 2024. All rights reserved.