【问题标题】:Apply a colormap only to unmasked region (excluding the black mask)仅将颜色图应用于未蒙版区域(不包括黑色蒙版)
【发布时间】:2021-03-19 10:43:50
【问题描述】:

我对 cv2 和 python 还是很陌生,所以如果这是基本的还是重复的,请原谅我。我试过搜索但无济于事。我有一张图像,比如penguin,我使用cv2.inRange() 函数掩盖了它。然后我尝试将 Viridis 颜色图应用于图像,但它适用于所有内容,包括蒙版。我希望颜色图应用于未屏蔽区域以突出值的细微差异。本质上,我希望将未屏蔽区域中的最小值映射到 Viridis 的紫色,将未屏蔽区域中的最大值映射到 Viridis 的黄色,并将两者之间的值线性映射。

这是我的尝试和resulting image。请注意,先前为黑色的蒙版区域是如何包含在映射中的,现在是紫色的。我什至不确定这是否可能。也许需要自定义颜色图?

import cv2
import numpy as np 

img = cv2.imread('penguin.jpg') #Read in image
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #Change to HSV

# define range of white color in HSV
lower_white = np.array([0,0,210])
upper_white = np.array([255,255,255])


mask = cv2.inRange(img, lower_white, upper_white) # Create the mask
bitwise_mask = cv2.bitwise_and(img,img,mask=mask) # Apply mask
masked_core = cv2.cvtColor(bitwise_mask, cv2.COLOR_HSV2BGR) #Change to BGR

#But how do I get it to apply only to unmasked area?
not_desired = cv2.applyColorMap(masked_core, cv2.COLORMAP_VIRIDIS) #Viridis Colormap

#Display and write image
cv2.imwrite('penguin_masked.jpg', not_desired)
cv2.imshow('penguin', not_desired)
cv2.waitKey()

【问题讨论】:

    标签: python numpy opencv image-processing opencv-python


    【解决方案1】:

    响应您的评论,也许这就是您在 Python/OpenCV 中想要的。我的答案几乎相同,除了我如何计算要进行颜色映射的灰度图像。我将您的低颜色和高颜色转换为强度值。然后将彩色图像转换为强度灰度。然后将您的 [0,0,210] 等效强度拉伸为黑色,将您的 [255,255,255] 等效强度 (255) 拉伸为白色,所有值在两者之间线性拉伸。

    输入:

    import cv2
    import numpy as np 
    from skimage.exposure import rescale_intensity
    
    img = cv2.imread('penguin.jpg') #Read in image
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #Change to HSV
    
    # define range of white color in HSV
    lower_white = np.array([0,0,210])
    upper_white = np.array([255,255,255])
    
    mask = cv2.inRange(hsv, lower_white, upper_white) # Create the mask
    
    # Y = 0.299 R + 0.587 G + 0.114 B
    # convert [0,0,210] to intensity = 0.299*210 = 63
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #Change to gray (intensity)
    gray = rescale_intensity(gray, in_range=(63,255), out_range=(0,255)).astype(np.uint8) # linearly stretch 63 to black and 255 to white
    
    colormap = cv2.applyColorMap(gray, cv2.COLORMAP_VIRIDIS) #Viridis Colormap to gray image
    
    img_masked = cv2.bitwise_and(img, img, mask=mask) # Apply mask to img
    
    colormap_masked = cv2.bitwise_and(colormap, colormap, mask=(255-mask)) # Apply inverse mask to colormapped
    
    result = cv2.add(img_masked, colormap_masked) # Merge original and colormapped using mask
    
    #Display and write image
    cv2.imwrite('penguin_mask.jpg', mask)
    cv2.imwrite('penguin_colormapped2.jpg', colormap)
    cv2.imwrite('penguin_result.jpg', result)
    
    cv2.imshow('mask', mask)
    cv2.imshow('colormapped2', colormap)
    cv2.imshow('result', result)
    cv2.waitKey()
    

    面具:

    彩色映射图像:

    结果:

    【讨论】:

      【解决方案2】:

      这是在 Python/OpenCV 中执行此操作的一种方法。

      • 阅读图片
      • 转换为 HSV
      • 使用 inRange() 设置 HSV 阈值以制作掩码
      • 将图像转换为灰度
      • 将颜色图应用于灰度图像
      • 将蒙版应用于输入图像
      • 将逆映射应用于彩色映射图像
      • 将两个蒙版图像加在一起以获得结果
      • 保存结果

      输入:

      import cv2
      import numpy as np 
      
      img = cv2.imread('penguin.jpg') #Read in image
      hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) #Change to HSV
      
      # define range of white color in HSV
      lower_white = np.array([0,0,210])
      upper_white = np.array([255,255,255])
      
      mask = cv2.inRange(hsv, lower_white, upper_white) # Create the mask
      print(mask.shape, np.amax(mask))
      
      gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #Change img to GRAY
      
      colormap = cv2.applyColorMap(gray, cv2.COLORMAP_VIRIDIS) #Viridis Colormap to gray image
      
      img_masked = cv2.bitwise_and(img, img, mask=mask) # Apply mask to img
      
      colormap_masked = cv2.bitwise_and(colormap, colormap, mask=(255-mask)) # Apply inverse mask to colormapped
      
      result = cv2.add(img_masked, colormap_masked) # Merge original and colormapped using mask
      
      #Display and write image
      cv2.imwrite('penguin_mask.jpg', mask)
      cv2.imwrite('penguin_colormapped.jpg', colormap)
      cv2.imwrite('penguin_result.jpg', result)
      
      cv2.imshow('mask', mask)
      cv2.imshow('colormapped', colormap)
      cv2.imshow('result', result)
      cv2.waitKey()
      

      蒙版图片:

      彩色映射图像:

      结果:

      注意:如果我误解了,并且您想要企鹅颜色映射,那么只需在 bitwise_and 操作中交换掩码和反掩码即可。

      【讨论】:

      • 不完全是我所追求的,但我认为那是因为我不知道如何问这个问题。我希望颜色映射使用in.Range() 的下限 [0,0,210] 并为其分配颜色 #440154ff,然后将上限 [255,255,255] 分配为颜色 #fde725ff,然后在这两个点之间分配值线性插值。本质上,我想用颜色来展示价值的细微差别。不确定这是否有意义。我尝试在 GIMP 中重新创建,但运气不佳。也许我从根本上误解了一个关键概念。
      • inRange 结果是二进制的。包括但不限于您的 [0,0,210] 和所有较暗的颜色,以及您的 [255,255,255] 最亮的颜色。所以 [0,0,210] 不是黑色的唯一颜色。你只是想让你的面具中的黑色去#440154ff,白色去#fde725ff,这样你就只有颜色图中的两种颜色了吗?如果是这样,有更简单的方法可以做到这一点。对不起,我还是不明白你想要什么。您要为哪个图像着色 - 输入还是掩码?
      猜你喜欢
      • 2023-03-04
      • 1970-01-01
      • 2019-10-24
      • 2012-05-15
      • 1970-01-01
      • 2019-07-23
      • 2013-04-15
      • 1970-01-01
      相关资源
      最近更新 更多