我正在尝试聚合来自图像像素的颜色信息,在这种情况下并考虑Python环境,我有几个由同一台相机生成的具有相同图像大小的.jpg图像,我可以在支持的任何颜色空间中读取这些图像Python(RGB、HSL、HSV、CIELAB、CMYK,...)。每个图像上都有由二值掩模标记的某些分段。一旦我有了这个颜色空间和那个二进制掩码,我就会尝试提取分段对象的一些“平均颜色”。一旦我获得了该图像的所有分段对象的平均颜色,我就会将该信息聚合为单个颜色值。这可能看起来是一个荒谬的问题,但为了正确的颜色信息聚合需要处理某些点,这增加了这种情况的复杂性:
为了用平均值对某些内容进行分组,+ 和 - 运算需要具有数学意义,以便颜色空间中任何位置的相同几何距离反映相同数量的感知色差。例如,RGB 中的平均值总是倾向于生成棕色(就像当您绘画时,在没有任何标准的情况下混合大量颜色,最终会产生一些棕色的无意义颜色)
为了使用中值对某些内容进行分组,您需要颜色空间遵循一定的逻辑顺序才能提取中值。例如,在 RGB 中,您不能简单地求中值,因为您无法判断 RGB 值 [120, 100, 127] 是在 [120, 111, 126] 之前还是之后。
与分割对象的真实颜色相比,jpg 图像格式的压缩以及相机传感器可能会改变捕获的图像颜色。
考虑到这一点,我的问题如下:
我一直在做的一些尝试可以总结为以下函数:
def aggregate_rgb(binary_mask, image):
# Change bgr to rgb
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Convert mask to boolean
binary_mask = binary_mask.astype(bool)
# Extract region inside the mask
masked_image = rgb_image[binary_mask]
# Calculate mode RGB values
mode_rgb = np.zeros(3, dtype=np.uint8)
# Reshape the masked image to a 2D array where each row represents a pixel and each column represents a channel
reshaped_masked_image = masked_image.reshape(-1, 3)
# Compute mode for each channel simultaneously
channel_modes = mode(reshaped_masked_image, axis=0)
# Calculate the custom RGB average
num_pixels = np.sum(binary_mask)
r = np.sum(masked_image[:, 0].astype('uint16') ** 2)
g = np.sum(masked_image[:, 1].astype('uint16') ** 2)
b = np.sum(masked_image[:, 2].astype('uint16') ** 2)
# Calculate aggregate of RGB values
mean_rgb = np.round(np.mean(masked_image, axis=0)).astype('uint8')
median_rgb = np.round(np.median(masked_image, axis=0)).astype('uint8')
mode_rgb = np.round(channel_modes.mode).astype('uint8')
custom_mean_rgb = np.sqrt(np.array([r, g, b]) / num_pixels).astype('uint8')
return mean_rgb, median_rgb, mode_rgb, custom_mean_rgb
这些试验的问题主要在于所选择的色彩空间 (RGB),它往往会给出信息量不大的棕色颜色。我还设法使用此行 cv2.cvtColor(image, cv2.COLOR_BGR2Lab) 读取 CIELAB 颜色空间中的图像,但我再次不知道是否应该单独执行通道的平均值、中值和模式,或者是否有考虑到 L、A 和 B 通道在几何上形成球体,请遵循一定的方程 (https://www.ulprospector.com/knowledge/wp-content/uploads/2024/01/1.-CIELAB-Color-Space .jpg)
我使用 cv2 库进行图像显示和色彩空间读数,我的 Python 版本是 3.9.13,在 Windows 10 上的 Visual Studio Code 上运行
对于我在这个问题的格式方面可能犯的任何错误,我事先表示歉意,如果您觉得还需要其他内容,我会很乐意添加它。预先感谢您!
我在询问之前检查过的一些有趣的链接:
在讨论感知时,总是很难就某些定义达成一致,所以我会采用更物理世界的解决方案。
理想的色彩空间是颜色模型 RGB(即 RGB、XYZ 等)。注意:线性版本(所以没有常用的 sRGb,它是伽玛校正)。
如果您保留浮点数学,或者只是允许负值和正值高于颜色空间的正常限制,那么您选择哪个颜色空间(在这种线性颜色模型内)并不重要,结果将是相同(在转换回所需的目标色彩空间之后)。
这种色彩空间很好地描述了物理光,因此您的眼睛平均值(例如,在无法分辨所有像素的距离下)与数学平均值相同。 (再次强调:这仅适用于 RGB(或 XYZ)线性空间。
我建议使用 XYZ (CIE XYZ),因为它经常被用作中间色彩空间,所以你应该有公式来转换它。