matlab中im2double、im2uint8的python实现

matlab中im2double、im2uint8的python实现

  • im2double
    • 源码
    • 验证
  • im2double
    • 源码
    • 验证

im2double

im2double的核心功能是将图像数据转换为双精度浮点数并归一化到[0, 1]范围。

  • 对于uint8类型,除以255,uint16除以65535,
  • 当输入已经是浮点型时,如果值已经在0-1之间,会保持原样
  • 索引图像不适用该函数。应先转换为真彩图像再继续

源码

def im2double(image, mode='dtype_based', decimal_places=8):
    """
    Args:
        image: 输入图像(支持np.ndarray、PIL.Image等)
        mode: 'dtype_based'(按数据类型归一化)或 'dynamic_range'(按像素值范围归一化)
        decimal_places: 浮点数舍入的小数位数(默认8位)
    Returns:
        归一化后的float64图像,范围[0,1]
    """
    img_array = np.array(image, copy=False)
    dtype = img_array.dtype

    if mode == 'dtype_based':
        if dtype == np.uint8:
            normalized = img_array.astype(np.float64) / 255.0
        elif dtype == np.uint16:
            normalized = img_array.astype(np.float64) / 65535.0
        elif dtype == np.bool_:
            return img_array.astype(np.float64)  # 布尔无需舍入
        elif np.issubdtype(dtype, np.integer):
            info = np.iinfo(dtype)
            normalized = (img_array.astype(np.float64) - info.min) / (info.max - info.min)
        else:
            normalized = img_array.astype(np.float64)
    elif mode == 'dynamic_range':
        min_val = np.min(img_array)
        max_val = np.max(img_array)
        if min_val == max_val:
            normalized = np.zeros_like(img_array, dtype=np.float64)  # 全零或自定义处理
        else:
            normalized = (img_array.astype(np.float64) - min_val) / (max_val - min_val)
    else:
        raise ValueError("模式需为 'dtype_based' 或 'dynamic_range'")

    # 对归一化结果执行舍入(除布尔类型外)
    if dtype != np.bool_:
        normalized = np.around(normalized, decimals=decimal_places)
    
    return normalized

验证

# 验证uint8输入
img_uint8 = np.array([0, 127, 255], dtype=np.uint8)
print(im2double(img_uint8))  # 应为 [0.0, 0.498... , 1.0]

# 验证bool输入
img_bool = np.array([True, False, True])
print(im2double(img_bool))   # 应为 [1.0, 0.0, 1.0]

# 验证dynamic_range模式
img_float = np.array([0.0, 0.5, 2.0], dtype=np.float32)
print(im2double(img_float, mode='dynamic_range'))  # 应为 [0.0, 0.25, 1.0]

优势

  • 支持更多整数类型(如int16/uint32)的自动归一化
  • 兼容布尔类型输入
  • 提供两种归一化模式选择(按数据类型或像素范围)

im2double

  • 数据类型自适应
  • 动态范围缩放
  • 自动舍入

源码

import numpy as np

def im2uint8(image, mode='dtype_based', clip=True):
    """
    Args:
        image: 输入图像(支持np.ndarray、PIL.Image等)
        mode: 'dtype_based'(默认,按数据类型处理)或 'dynamic_range'(按像素值范围缩放)
        clip: 是否裁剪超出[0,255]的值(默认True,MATLAB默认行为)
    Returns:
        uint8类型图像,范围[0,255]
    """
    img_array = np.array(image, copy=False)
    dtype = img_array.dtype
    
    if mode == 'dtype_based':
        if dtype == np.uint8:
            return img_array.copy()
        elif dtype == np.bool_:
            return img_array.astype(np.uint8) * 255  # True -> 255, False -> 0
        elif np.issubdtype(dtype, np.integer):
            info = np.iinfo(dtype)
            scaled = (img_array.astype(np.float64) - info.min) / (info.max - info.min) * 255
        elif np.issubdtype(dtype, np.floating):
            scaled = img_array.astype(np.float64) * 255
        else:
            raise TypeError(f"不支持的数据类型: {dtype}")
    elif mode == 'dynamic_range':
        min_val = img_array.min()
        max_val = img_array.max()
        if min_val == max_val:
            scaled = np.zeros_like(img_array, dtype=np.float64)
        else:
            scaled = (img_array.astype(np.float64) - min_val) / (max_val - min_val) * 255
    else:
        raise ValueError("模式需为 'dtype_based' 或 'dynamic_range'")
    
    # MATLAB兼容性四舍五入(非直接截断)
    rounded = np.around(scaled)
    
    # 处理超出范围的值
    if clip:
        rounded = np.clip(rounded, 0, 255)
    
    return rounded.astype(np.uint8)

验证

# 验证bool转uint8
bool_img = np.array([True, False, True])
print(im2uint8(bool_img))  # 输出 [255, 0, 255]

# 验证uint16转uint8(按数据类型缩放)
uint16_img = np.array([0, 32767, 65535], dtype=np.uint16)
print(im2uint8(uint16_img))  # 输出 [0, 127, 255]

# 验证float转uint8(假设输入在[0,1])
float_img = np.array([0.0, 0.6, 1.0])
print(im2uint8(float_img))  # 输出 [0, 153, 255](0.6*255=153.0→153)

# 验证dynamic_range模式
high_range_img = np.array([-100, 0, 100, 200], dtype=np.float64)
print(im2uint8(high_range_img, mode='dynamic_range'))  # 输出 [0, 85, 170, 255]

你可能感兴趣的:(Python,图像处理,Matlab,matlab,python,图像处理)