Mar*_*oma 4 numpy machine-learning image-processing scikit-learn
I want to normalize the pixel values of an image to the range [0, 1] for each channel (R, G, B).
#!/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)
Run Code Online (Sandbox Code Playgroud)
Taking https://commons.wikimedia.org/wiki/File:Crocodylus-johnsoni-3.jpg, I get the following "normalized" result:
As you can see there are lines from top to bottom at the right side. What happened there? It seems to me that the normalization went wrong. If so: How do I fix it?
在 scikit-learn 中,形状为(m, n)的二维数组通常被解释为m 个样本的集合,每个样本具有n 个特征。
MinMaxScaler.fit_transform()转换每个特征,因此数组的每一列都独立于其他列进行转换。这会导致图像中出现垂直的“条纹”。
看起来您打算独立缩放每个颜色通道。为此,请使用MinMaxScaler重塑输入,使每个通道成为一列。即如果原始图像有形状(m, n, 3),则在将其传递给fit_transform()方法之前将其reshape为(m*n, 3) ,然后恢复结果的形状以创建变换后的数组。
例如,
ascolumns = original.reshape(-1, 3)
t = scaler.fit_transform(ascolumns)
transformed = t.reshape(original.shape)
Run Code Online (Sandbox Code Playgroud)
有了这个,transformed看起来像这样:
该图像看起来与原始图像完全一样,因为事实证明,在数组中original,每个通道中的最小值和最大值分别为 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)
Run Code Online (Sandbox Code Playgroud)
所以fit_transform在这种情况下所做的就是将所有输入值统一转换为浮点范围 [0.0, 1.0]。如果其中一个通道中的最小值或最大值不同,则转换后的图像看起来会有所不同。
顺便说一句,使用纯 numpy 执行转换并不难。(我使用的是 Python 3,所以在下面,除法会自动将结果转换为浮点数。如果您使用的是 Python 2,则需要将参数之一转换为浮点数,或使用from __future__ import division.)
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
Run Code Online (Sandbox Code Playgroud)
(该方法的一个潜在问题是,如果其中一个通道是常量,它将产生错误,因为其中一个值omax - omin将为 0。)
| 归档时间: |
|
| 查看次数: |
1270 次 |
| 最近记录: |