我正在尝试操纵像素值而不剪裁它们
I am trying to manipulate the pixel values without clipping them
我有一张图像,其最大像素值 - 287.4976094062538
和最小像素值 - -41.082841881780645
我试图将它们置于 0-255
之间的范围内
我做了什么:-
- 我将所有像素值除以最大像素值,然后乘以 255
- 这使我的最高像素值变为 1,但我的最小像素值仍为负像素值
-0.14
。
这是一张医学图像,所以我想保留每个像素的强度,所以我不想将它们剪裁在 0-255 之间
但是我怎样才能在不剪裁的情况下将它们带到那个范围内(这会破坏图像结构)。
使用 matplotlib
或 PIL
等库加载它们会自动剪切像素值。
您仅对图像的正范围进行归一化,忽略负值。
您想将以下等式应用于您的值:
mx = np.amax(img)
mn = np.amin(img)
img = (img - mn) / (mx - mn) * 255
我们先减去最小值,使图像中的最小值变为0。接下来我们除以将最大值设置为1。
mx-mn
是你的数据的全部范围,因此在将最小值设置为 0 后数据中的最大值。
Scikit-image 有这个功能:
https://scikit-image.org/docs/dev/api/skimage.exposure.html#skimage.exposure.rescale_intensity
最好将其重新缩放到范围 (0,1),以 float 格式进行所有处理并在保存前转换为 int8。
In [1]: from skimage.exposure import rescale_intensity
In [2]: from skimage import img_as_ubyte
In [3]: import numpy as np
In [4]: im = np.random.uniform(low=-100, high=400, size=(3,3))
In [5]: im
Out[5]:
array([[351.2177509 , 313.89196632, 241.73850855],
[-21.12284801, 97.84166107, -66.925235 ],
[267.75593733, -15.78767759, 252.63980599]])
In [6]: im = rescale_intensity(im, in_range='image', out_range=(0,1))
In [7]: im
Out[7]:
array([[1. , 0.9107344 , 0.7381775 ],
[0.10953762, 0.39404439, 0. ],
[0.80039887, 0.12229682, 0.76424824]])
In [8]: im = img_as_ubyte(im) # 8bit
In [9]: im
Out[9]:
array([[255, 232, 188],
[ 28, 100, 0],
[204, 31, 195]], dtype=uint8)
如果这是灰度超过 256 级的黑白图像,我建议使用 16 位 PNG 格式并将其重新缩放到范围 (0, 65535)。
如果你有更多相似的图片,你可以使用自定义 in_range,这样所有图片的缩放比例都是一致的,正如 Guang 所建议的那样。
import numpy as np
from skimage.exposure import rescale_intensity
from skimage import img_as_uint
from imageio import imwrite
im = np.linspace(-40,288,10000).reshape(100,100)
im = rescale_intensity(im, in_range=(-100,400), out_range=(0,1))
im = img_as_uint(im) # 16bit
imwrite("image.png", im)
编辑:如果你不想使用 scikit-image,你可以像这样定义类似的函数:
def rescale_intensity(arr, in_range=None, out_range=(0, 1)):
"""Normalize numpy array.
Returns: float array
"""
imin, imax = in_range if in_range is not None else (np.min(arr), np.max(arr))
omin, omax = out_range
if imin == imax:
raise ValueError("Cannot rescale array, imin == imax")
else:
z = omin + omax * ((arr - imin) / (imax - imin))
return np.clip(z, a_min=omin, a_max=omax)
我有一张图像,其最大像素值 - 287.4976094062538
和最小像素值 - -41.082841881780645
我试图将它们置于 0-255
我做了什么:-
- 我将所有像素值除以最大像素值,然后乘以 255
- 这使我的最高像素值变为 1,但我的最小像素值仍为负像素值
-0.14
。
这是一张医学图像,所以我想保留每个像素的强度,所以我不想将它们剪裁在 0-255 之间
但是我怎样才能在不剪裁的情况下将它们带到那个范围内(这会破坏图像结构)。
使用 matplotlib
或 PIL
等库加载它们会自动剪切像素值。
您仅对图像的正范围进行归一化,忽略负值。
您想将以下等式应用于您的值:
mx = np.amax(img)
mn = np.amin(img)
img = (img - mn) / (mx - mn) * 255
我们先减去最小值,使图像中的最小值变为0。接下来我们除以将最大值设置为1。
mx-mn
是你的数据的全部范围,因此在将最小值设置为 0 后数据中的最大值。
Scikit-image 有这个功能:
https://scikit-image.org/docs/dev/api/skimage.exposure.html#skimage.exposure.rescale_intensity
最好将其重新缩放到范围 (0,1),以 float 格式进行所有处理并在保存前转换为 int8。
In [1]: from skimage.exposure import rescale_intensity
In [2]: from skimage import img_as_ubyte
In [3]: import numpy as np
In [4]: im = np.random.uniform(low=-100, high=400, size=(3,3))
In [5]: im
Out[5]:
array([[351.2177509 , 313.89196632, 241.73850855],
[-21.12284801, 97.84166107, -66.925235 ],
[267.75593733, -15.78767759, 252.63980599]])
In [6]: im = rescale_intensity(im, in_range='image', out_range=(0,1))
In [7]: im
Out[7]:
array([[1. , 0.9107344 , 0.7381775 ],
[0.10953762, 0.39404439, 0. ],
[0.80039887, 0.12229682, 0.76424824]])
In [8]: im = img_as_ubyte(im) # 8bit
In [9]: im
Out[9]:
array([[255, 232, 188],
[ 28, 100, 0],
[204, 31, 195]], dtype=uint8)
如果这是灰度超过 256 级的黑白图像,我建议使用 16 位 PNG 格式并将其重新缩放到范围 (0, 65535)。
如果你有更多相似的图片,你可以使用自定义 in_range,这样所有图片的缩放比例都是一致的,正如 Guang 所建议的那样。
import numpy as np
from skimage.exposure import rescale_intensity
from skimage import img_as_uint
from imageio import imwrite
im = np.linspace(-40,288,10000).reshape(100,100)
im = rescale_intensity(im, in_range=(-100,400), out_range=(0,1))
im = img_as_uint(im) # 16bit
imwrite("image.png", im)
编辑:如果你不想使用 scikit-image,你可以像这样定义类似的函数:
def rescale_intensity(arr, in_range=None, out_range=(0, 1)):
"""Normalize numpy array.
Returns: float array
"""
imin, imax = in_range if in_range is not None else (np.min(arr), np.max(arr))
omin, omax = out_range
if imin == imax:
raise ValueError("Cannot rescale array, imin == imax")
else:
z = omin + omax * ((arr - imin) / (imax - imin))
return np.clip(z, a_min=omin, a_max=omax)