图像处理中的伪彩色图与模式转换:P模式、L模式及语义分割标签可视化实践

1. 伪彩色图

伪彩色(pseudo-color)图像是一种图像处理技术,用于将灰度图像或单通道图像映射到彩色空间,以便通过颜色差异来增强图像的视觉表现。在伪彩色图像中,不同的灰度级或数据值被赋予不同的颜色,从而创建出一个彩色的图像表示。

伪彩色图每个像素值实际上是一个索引值或代码,该代码值作为色彩查找表CLUT(Color Look-Up Table)中某一项的入口地址,根据该地址可查找出包含实际R、G、B的强度值。这种用查找映射的方法产生的色彩称为伪彩色,生成的图像为伪彩色图像。

伪彩色图查找表是一个预先定义好的映射表,它将原始图像的灰度值(或某个特定范围内的灰度值)映射到特定的颜色值。每个条目通常包含红、绿、蓝(RGB)三个颜色通道的值,以及可能的透明度(Alpha)信息。

需要注意的是,伪彩色图像并不是真正的彩色图像,而是通过对灰度图像或单通道图像进行颜色映射得到的。因此,在解释伪彩色图像时,需要注意颜色所代表的实际含义。

2. 图像模式

图像模式是指图像中像素的存储和表示方式,不同的模式对应不同的颜色深度和存储需求。在PIL中,常见的图像模式包括:

  • “1”:二值图像
  • “L”:灰度图像
  • “P”:调色板图像
  • “RGB”:红绿蓝三通道彩色图像
  • “RGBA”:红绿蓝及透明度四通道彩色图像
  • “CMYK”:印刷色彩模式,包括青、洋红、黄和黑色
  • “YCbCr”:用于JPEG压缩的颜色空间
  • “I”:32位整型图像
  • “F”:32位浮点型图像
from PIL import Image
img = Image.open('test.png')
mode = img.mode
print(mode)  # 输出可能是'L', 'RGB', 'RGBA'等

如果你输入的是彩色图,那么输出是RGB。在cv2中没有直接的输出图像模式的方法。

3. P模式与L模式

上面介绍了图像模式,这里主要介绍语义分割中用到的标签的图像的模式。

3.1 P模式(Pseudocolor mode)

  • 在P模式下,灰度图像的每个像素值会被映射到一个特定的颜色上
  • 映射函数可以是线性的,也可以是非线性的,取决于所选的伪彩色变换方法
  • 伪彩色图可以用于突出显示图像中的特定特征,如边缘、纹理或特定类型的图像数据(例如医学成像中的不同组织类型)
  • P模式下的伪彩色图通常用于科学可视化,其中不同的颜色可以帮助解释和理解数据

3.2 L模式(Luminance mode)

  • L模式通常指的是亮度模式,它是一种将灰度图像转换为具有单一颜色通道的图像的方法
  • 在L模式下,图像的每个像素值被转换为相同的颜色(通常是白色或其他单一颜色),然后通过调整亮度来区分不同的像素值
  • 这种方法通常用于创建高对比度的图像,使得图像中的不同区域或特征通过亮度的变化来区分,而不是颜色的变化
  • L模式下的图像可能不如P模式那样丰富和多彩,但它们可以提供一种简单而有效的方式来强调图像中的亮度差异

这里对标签掩码灰度图及伪彩色掩码图进行测试(从左至右分别是原图,labelme得到的标签伪彩色掩码图label.png,单通道灰度图pic.png):

import cv2
import numpy as np
from PIL import Image

# 测试L模式图像
img = Image.open('pic.png')
mode = img.mode
print(mode)  # L
print(np.unique(img))  # [0 1 2]

print("-" * 30)

# 测试P模式图像
img = Image.open('label.png')
mode = img.mode
print(img.getpalette())  # PIL的P模式默认调色板RGB颜色及顺序[0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 0, 0, 0, 128, 128, 0, 128, 0, 128, 128, 128, 128, ...]
print(mode)  # P
print(np.unique(img))  # [0 1 2]

print("-" * 30)

# 使用cv2读取图片测试
img = cv2.imread('label.png', 0)  # 以灰度读取伪彩色标签图
print(np.unique(img))  # [ 0 38 75]

img = cv2.imread('label.png', 1)  # 以彩色读取伪彩色标签图
print(np.unique(img))  # [  0 128]

img = cv2.imread('pic.png', 0)
print(np.unique(img))  # [0 1 2]

img = cv2.imread('pic.png', 1)
print(np.unique(img))  # [0 1 2]

上述代码中,np.unique是用来测试图像的像素值有哪些。很显然cv2对于P模式的伪彩色标签图,会以三通道彩色图去读取,无法读取到实际的标签种类。

4. P模式与L模式相互转换

4.1 P模式转L模式

from PIL import Image

# 读取伪彩色P模式图像
img = Image.open('pseudo_color_image.png')

# 检查图像模式
print(f"原始图像模式: {img.mode}")

# 如果图像不是RGB模式,先转换为RGB模式(这里假设图像已经是P模式)
if img.mode != 'RGB':
    img = img.convert('RGB')

# 将RGB图像转换为灰度图像
gray_img = img.convert('L')

# 保存灰度图像
gray_img.save('gray_image.jpg')

# 检查转换后的图像模式
print(f"转换后图像模式: {gray_img.mode}")

4.2 L模式转P模式

from PIL import Image

# 打开L模式图像
image = Image.open("pic.png")

# 将L模式转换为P模式,并设置调色板
p_image = image.convert("P")  # 这里的palette参数实际上是被忽略的

# 自定义一个包含5种颜色的调色板
colors = [128, 128, 0, 0, 255, 0, 0, 0, 255, 0, 0, 255, 255, 255, 255]
p_image.putpalette(colors)

# 保存带有自定义调色板的P模式图像
p_image.save("converted_palette_image.png")

# 验证图像模式
print(f"转换后图像模式: {p_image.mode}")

5. Alpha透明通道与自定义语义分割标签生成

使用如下代码在原图上,利用掩码标注的区域,添加彩色,通过设置两者叠加的权重达到透明可视效果。

5.1 基础叠加方法

import cv2
import numpy as np

image_path = r'images\img.png'  # 三通道彩色图
mask_path = r'images\pic.png'  # 单通道灰度图掩码

# 读取原图
image = cv2.imread(image_path)
print(image.shape)  # (500, 800, 3)

mask = cv2.imread(mask_path, cv2.IMREAD_UNCHANGED)  # 读取图像时保留所有通道,包括透明度通道
print(mask.shape)

# 创建一个空白的彩色掩码叠加图 (与原图相同大小)
overlay = np.zeros_like(image, dtype=np.uint8)
colors = {
    0: (0, 0, 0),        # 背景 - 无色(其实不用添加)
    1: (0, 0, 255),      # 类1 - 红色
    2: (0, 128, 255)     # 类2 - 绿色
}

"""
颜色说明:
0: (0, 0, 0),        # 背景 - 无色(其实不用添加)
1: (0, 0, 128),      # 类1 - 浅红色
2: (0, 128, 0)       # 类2 - 浅绿色
"""

# 遍历掩码中的每个类别,为每个类别设置颜色
for value, color in colors.items():
    overlay[mask == value] = color

# 设置透明度(alpha 透明度值)
alpha = 0.25  # 0.0完全透明,1.0完全不透明

# 将透明的彩色叠加图与原图结合
result = cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0)

# 保存结果
cv2.imwrite('overlayed_image.png', result)

效果对比:

  • 叠加彩色的图
  • 原图

5.2 增加Alpha透明通道

import cv2
import numpy as np

image_path = r'images\img.png'  # 三通道彩色图
mask_path = r'images\pic.png'  # 单通道灰度图掩码

# 读取原图
image = cv2.imread(image_path)
print(image.shape)  # (500, 800, 3)

mask = cv2.imread(mask_path, cv2.IMREAD_UNCHANGED)  # 读取图像时保留所有通道,包括透明度通道
print(mask.shape)

# 创建一个空白的彩色叠加图 (与原图相同大小,但包含透明度通道)
overlay = np.zeros((image.shape[0], image.shape[1], 4), dtype=np.uint8)
colors = {
    0: (0, 0, 0, 0),        # 背景 - 透明(完全透明)
    1: (0, 0, 255, 128),    # 类1 - 半透明红色
    2: (0, 255, 0, 128)     # 类2 - 半透明绿色
}

# 遍历掩码中的每个类别,为每个类别设置颜色
for value, color in colors.items():
    overlay[mask == value] = color

# 将原图像转换为包含透明度通道的格式
image_bgra = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)

# 将透明的彩色叠加图与原图结合
combined = cv2.addWeighted(overlay, 0.3, image_bgra, 1, 0)

# 保存结果
cv2.imwrite('overlayed_image2.png', combined)

效果对比:

  • 叠加彩色的图
  • 原图

5.3 添加图例

import cv2
import numpy as np

def add_legend(image, colors, labels, alpha=0.8):
    """
    在图像的右上角添加图例,使用固定的尺寸。

    :param image: 输入的BGR图像。
    :param colors: 颜色字典,键是类值,值是颜色元组(B, G, R)。
    :param labels: 标签字典,键是类值,值是标签文本。
    :param alpha: 叠加透明度。
    :return: 带图例的图像。
    """
    # 图像尺寸
    height, width = image.shape[:2]

    # 固定图例尺寸和参数
    legend_height = 60
    legend_width = 150
    legend_padding = 10
    color_box_size = 15
    text_offset = 20
    text_font_scale = 0.5
    text_thickness = 1
    line_height = 20  # 每一行的高度

    # 创建图例的背景
    legend = np.zeros((legend_height * len(labels) + legend_padding * 2, legend_width, 3), dtype=np.uint8)

    for idx, (key, color) in enumerate(colors.items()):
        # 设置图例的颜色框
        top_left = (legend_padding, idx * line_height + legend_padding)
        bottom_right = (legend_padding + color_box_size, idx * line_height + legend_padding + color_box_size)
        cv2.rectangle(legend, top_left, bottom_right, color[::1], -1)  # 颜色需要从 BGR 转换为 RGB

        # 添加标签文本
        text_position = (legend_padding + color_box_size + text_offset, top_left[1] + color_box_size)
        cv2.putText(legend, labels[key], text_position, cv2.FONT_HERSHEY_SIMPLEX, text_font_scale, (255, 255, 255),
                    text_thickness)

    # 计算图例位置
    legend_x = width - legend_width - legend_padding
    legend_y = legend_padding

    # 将图例叠加到原图像右上角
    overlay = image.copy()
    overlay[legend_y:legend_y + legend.shape[0], legend_x:legend_x + legend.shape[1]] = legend

    # 透明混合
    result = cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0)

    return result


image_path = r'images\img.png'  # 三通道彩色图
mask_path = r'images\pic.png'  # 对应的单通道灰度图标签掩码

# 读取原图
image = cv2.imread(image_path)
print(image.shape)  # (500, 800, 3)

mask = cv2.imread(mask_path, cv2.IMREAD_UNCHANGED)  # 读取图像时保留所有通道,包括透明度通道
print(mask.shape)

# 创建一个空白的彩色叠加图 (与原图相同大小,但包含透明度通道)
overlay = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)

colors = {
    0: (0, 0, 0),        # 背景
    1: (0, 0, 255),      # 类1 - 红色
    2: (0, 255, 0)       # 类2 - 绿色
}

colors_legend = {
    1: (0, 0, 255),      # 类1 - 红色
    2: (0, 255, 0)       # 类2 - 绿色
}

labels = {
    1: 'Class 1',
    2: 'Class 2'
}

# 遍历掩码中的每个类别,为每个类别设置颜色
for value, color in colors.items():
    overlay[mask == value] = color

combined = cv2.addWeighted(overlay, 0.3, image, 1, 0)

# 添加图例到右上角
result_with_legend = add_legend(combined, colors_legend, labels, alpha=0.5)

# 保存结果
cv2.imwrite('overlayed_image3_legend.png', result_with_legend)

本文详细介绍了图像处理中的伪彩色图概念、P模式与L模式的特性及相互转换方法,并提供了完整的语义分割标签可视化实践代码。通过设置浅色的红色与绿色叠加,可以近似达到添加Alpha透明通道设置低值的效果,为图像分割任务提供了实用的可视化解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值