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

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

Mask of color on gray scale image for saturated areas

问题

我从相机获取类型为 'numpy.uint16' 的图像,然后将其转换为 255 位,如下所示:

  1. imax2 = np.amax(self.data)
  2. if imax2 > 0:
  3. imul2 = int(65535/imax2)
  4. self.data = self.data*imul2
  5. data2 = (self.data/256).astype('u2')

其中,self.data 是图像的 NumPy 数组,我将其显示在一个名为 liveMain 的 tkinter 标签上,方法如下:

  1. img = Image.fromarray(data2)
  2. imgtk = ImageTk.PhotoImage(image=img)
  3. self.liveMain.imgtk = imgtk
  4. self.liveMain.config(image=imgtk)

我想在饱和像素上显示一个红色蒙版,但我不知道如何做。欢迎任何建议。谢谢。

英文:

i get images from a camera in type 'numpy.uint16' that i transform to 255 bits like so:

  1. imax2 = np.amax(self.data)
  2. if imax2 > 0:
  3. imul2 = int(65535/imax2)
  4. self.data = self.data*imul2
  5. 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:

  1. img = Image.fromarray(data2)
  2. imgtk = ImageTk.PhotoImage(image=img)
  3. self.liveMain.imgtk = imgtk
  4. 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表示非饱和:
  1. sat_mask = data > saturation_threshold
  • 将图像从单通道(灰度)转换为RGB(3个颜色通道),其中红色=绿色=蓝色(假设输入是灰度图像):
  1. data2_rgb = np.dstack((data2, data2, data2))
  • 在遮罩为True的位置放置红色:
  1. data2_rgb[sat_mask] = np.array([255, 0, 0], np.uint8) # [255, 0, 0]表示红色,如果图像是uint16,则使用[65535, 0, 0]。

代码示例(请阅读注释):

  1. from PIL import Image
  2. import numpy as np
  3. # 创建一个uint16灰度Tiff图像,用于测试。
  4. # ...
  5. # 读取输入图像(uint16灰度)
  6. # ...
  7. # 选择一个阈值,高于该阈值,像素被视为饱和
  8. saturation_threshold = 50000
  9. # 创建一个遮罩,其中True表示图像饱和,False表示非饱和
  10. sat_mask = data > saturation_threshold
  11. # 将图像从单通道(灰度)转换为RGB,其中红色=绿色=蓝色
  12. data2_rgb = np.dstack((data2, data2, data2))
  13. # 在遮罩为True的位置放置红色
  14. data2_rgb[sat_mask] = np.array([255, 0, 0], np.uint8)
  15. # 保存图像以进行测试
  16. # ...

输入图像(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:

    1. 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):

    1. data2_rgb = np.dstack((data2, data2, data2))
  • Put red color where mask is True:

    1. 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):

  1. from PIL import Image
  2. import numpy as np
  3. # Build uint16 grayscale Tiff image out of uint8 JPEG image, for testing.
  4. ################################################################################
  5. img8 = Image.open('maxresdefault.jpg').convert('L') # Read image and convert to Grayscale.
  6. img16 = Image.fromarray(np.asarray(img8).astype(np.uint16)*255)
  7. img16.save('uint16_img.tif')
  8. ################################################################################
  9. uint16_img = Image.open('uint16_img.tif') # Read input image (uint16 grayscale)
  10. data = np.asarray(uint16_img) # Convert to NumPy array - assume data applies self.data from the question
  11. # Select a threshold, that above it, a pixel is considered saturated
  12. # The threshold is specific to the camera (may by 4000 for example - we can't know from the correct value from question).
  13. saturation_threshold = 50000
  14. # Build a mask (NumPy array) with True where images is saturated, and False where not.
  15. sat_mask = data > saturation_threshold
  16. imax2 = np.amax(data) # 64770
  17. if imax2 > 0:
  18. scale = 255.0/imax2
  19. #data2 = (data.astype(float) * scale).astype('u2')
  20. # For making the solution less confusing, convert data2 to uint8 type
  21. # 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).
  22. data2 = (data.astype(float) * scale).astype('uint8')
  23. else:
  24. data2 = data2.astype('uint8')
  25. # Converting from single channel (grayscale) to RGB (3 color channels) where red=green=blue (we need RGB for marking with red).
  26. data2_rgb = np.dstack((data2, data2, data2))
  27. #sat_mask = np.dstack((sat_mask, sat_mask, sat_mask))
  28. # Put red color where mask is True
  29. 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].
  30. Image.fromarray(np.asarray(data2_rgb)).save('data2_rgb.png') # Save image for testing
  31. if False:
  32. # Display the image in tkinter...
  33. img = Image.fromarray(data2_rgb)
  34. imgtk = ImageTk.PhotoImage(image=img)
  35. self.liveMain.imgtk = imgtk
  36. 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:

确定