Caxis自动等同于OpenCV Python或Pillow?

时间:2017-12-08 10:57:31

标签: python matlab opencv

MATLAB具有函数caxis auto,如果它们具有低对比度并且看起来几乎是黑色的,它可以用来查看图像。

在Matlab中它的工作原理如下:

figure;imshow(I);caxis auto

我知道如何在OpenCV Python中调整对比度,例如:

 img = cv2.imread('someimage.jpg',0)
 equ = cv2.equalizeHist(img)

 #Showing image
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

然而,这与caxis auto的实现不同,后者自适应地改变了照明。

1 个答案:

答案 0 :(得分:3)

OpenCV不使用色彩图来显示单通道图像。在Matlab中,caxis设置了色彩映射限制。换句话说,如果您的图像的值介于0.5和1.0之间,则可以设置显示的颜色限制,以便将0.5呈现为,就好像它 0.0,然后按这种方式缩放。 OpenCV只是按原样显示图像值。

这意味着如果您想要对值进行不同的缩放,您只需在显示的数组中更改它们。

使用OpenCV,您可以使用normType=cv2.NORM_MINMAX cv2.normalize()轻松完成此缩放。

img = np.random.rand(500, 500, 3)*0.2
cv2.imshow('Low contrast image', img)
cv2.waitKey()

Random image

img_scaled = cv2.normalize(img, None, alpha=0.0, beta=1.0, norm_type=cv2.NORM_MINMAX)
cv2.imshow('Scaled colors for display', img_scaled)
cv2.waitKey()

Scaled for display

请注意,这适用于灰度和彩色图像。

但是,如果您只有一个灰度图像,另一个选项是使用Matplotlib显示它们。 MPL将自动将单通道图像缩放到最小/最大显示值。

from matplotlib import pyplot as plt

img = np.random.rand(500, 500)*0.2
plt.imshow(img, cmap='gray')
plt.show()

MPL scaling

请注意,我添加了cmap='gray'参数,因为单个通道图像的默认色图是 Viridis ,而不是灰度。您可以阅读有关Matplotlib colormaps here的更多信息。一般来说,如果您正在寻找与Matlab类似的语法,Matplotlib已经涵盖了它 - 它最初适用于从Matlab进入Python的人,所以它具有类似的功能和语法。

最后一个选项是在numpy中手动缩放。如果您的图像是无符号整数类型,则只需将图像移动到其最低值为0,然后相乘,使其最大值为数据类型的最大值即可。请注意,当您乘以图像时,您将转换为浮点数,因此您需要重新制作它。例如,如果您有uint16图片,则值范围为0到65535,因此您可以执行以下操作:

img_scaled = img.copy() - np.min(img)
img_scaled = np.uint16(img_scaled*(65535/np.max(img)))

或者,如果您想自动执行此操作,可以使用np.iinfo()从图像中获取数据类型信息(包括数据类型中可能的最小值和最大值),以根据需要自动缩放和转换。这是一个将任何(有符号或无符号)整数或浮点图像标准化的函数:

def normalize_minmax(img):
    """Scales an image into an interval [min, max] with the same datatype.

    If img.dtype is a float type, img is scaled into [0.0, 1.0].
    If img.dtype is an integer type, img is scaled into [dtype.min, dtype.max].
    If img.dtype is some other type, the original image is returned.
    """
    dtype = img.dtype
    if np.issubdtype(dtype, np.integer): # scale to [dtype.min, dtype.max]
        dtype_info = np.iinfo(img.dtype)
        img_scaled = img - np.min(img)
        scale = (dtype_info.max - dtype_info.min) / np.max(img_scaled)
        img_scaled = img_scaled * scale + dtype_info.min
        return np.round(img_scaled).astype(dtype)
    elif np.issubdtype(dtype, np.float):  # scale to [0, 1]
        img_scaled = img - np.min(img)
        img_scaled = img_scaled / np.max(img_scaled)
        return img_scaled.astype(dtype)
    return img

它的工作原理很容易描述。对于浮动图像的情况,您只需将其移动以使最低值为零,然后除以最大值以使其在0和1之间。然后只需将其转换回原始类型即可。对于整数数据类型,如果您需要包含有符号整数,则需要花费更多精力。在这种情况下,范围也扩展到负数。您可以通过将最低值移至零来开始相同的操作。但是,您需要进行缩放,以使值跨越数据类型的整个范围(例如(datatype_max - datatype_min)/ max(img))。所以现在你的值将从[0,datatype_max - datatype_min]开始,所以你需要添加datatype_min来获取[datatype_min,datatype_max]。在转换回原始数据类型之前,我还舍入了值而不是截断。