numpy - 为什么 MinMaxScaler 会向图像添加线条?

标签 numpy image-processing machine-learning scikit-learn

我想将每个 channel (R、G、B)的图像像素值标准化到范围 [0, 1]。

最小示例

#!/usr/bin/env python

import numpy as np
import scipy
from sklearn import preprocessing

original = scipy.misc.imread('Crocodylus-johnsoni-3.jpg')
scipy.misc.imshow(original)

transformed = np.zeros(original.shape, dtype=np.float64)

scaler = preprocessing.MinMaxScaler()
for channel in range(3):
    transformed[:, :, channel] = scaler.fit_transform(original[:, :, channel])
scipy.misc.imsave("transformed.jpg", transformed)

发生了什么

服用https://commons.wikimedia.org/wiki/File:Crocodylus-johnsoni-3.jpg , 我得到以下“标准化”结果:

enter image description here

正如您所看到的,右侧有从上到下的线条。那里发生了什么?在我看来,正常化出了问题。如果是这样:我该如何解决它?

最佳答案

在 scikit-learn 中,形状为 (m, n) 的二维数组通常被解释为 m 个样本的集合,每个样本都有 >n 个功能。

MinMaxScaler.fit_transform() 转换每个特征,因此数组的每一列都独立于其他列进行转换。这会导致图像中出现垂直“条纹”。

看起来您打算独立缩放每个颜色 channel 。要使用 MinMaxScaler 实现此目的,请重新调整输入的形状,使每个 channel 变成一列。也就是说,如果原始图像的形状为 (m, n, 3),则在将其传递给 fit_transform() 方法之前将其 reshape 为 (m*n, 3),然后恢复形状创建转换后的数组的结果。

例如,

ascolumns = original.reshape(-1, 3)
t = scaler.fit_transform(ascolumns)
transformed = t.reshape(original.shape)

有了这个,转换看起来像这样:

image

该图像看起来与原始图像一模一样,因为事实证明,在数组 original 中,每个 channel 的最小值和最大值分别为 0 和 255:

In [41]: original.min(axis=(0, 1))
Out[41]: array([0, 0, 0], dtype=uint8)

In [42]: original.max(axis=(0, 1))
Out[42]: array([255, 255, 255], dtype=uint8)

因此,在这种情况下,fit_transform 所做的就是将所有输入值统一转换为浮点范围 [0.0, 1.0]。如果其中一个 channel 的最小值或最大值不同,则变换后的图像看起来会有所不同。

<小时/>

顺便说一句,使用纯 numpy 执行转换并不困难。 (我使用的是 Python 3,因此在下面,除法会自动将结果转换为浮点型。如果您使用的是 Python 2,则需要将参数之一转换为浮点型,或者使用 from __future__ 导入部门。)

In [58]: omin = original.min(axis=(0, 1), keepdims=True)

In [59]: omax = original.max(axis=(0, 1), keepdims=True)

In [60]: xformed = (original - omin)/(omax - omin)

In [61]: np.allclose(xformed, transformed)
Out[61]: True

(该方法的一个潜在问题是,如果其中一个 channel 恒定,它将生成错误,因为这样 omax - omin 中的值之一将为 0。)

关于numpy - 为什么 MinMaxScaler 会向图像添加线条?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37751717/

相关文章:

python - 使用 Python 对 bool 数据进行快速索引和位翻转

python - 在 python 中安装 scipy 模块时出错

python - 模糊图像的一部分并将其与背景混合

opencv - 如何在ubuntu(或其他linux env)中将realsense RGB帧转换为cv::Mat?

machine-learning - F1 分数不是精确率和召回率的调和平均值的原因可能是什么

Python:将代码应用于整个数据框列

python - Pandas 的百分位排名

image-processing - RGB 的 Gamma 校正算法与灰度的 Gamma 校正算法相同吗?

python - 两个文件之间的Classification_report

machine-learning - 结构化预测中的推理