尝试对屏蔽数组执行 skimage.equalize_hist 时出错

Error while trying to perform skimage.equalize_hist over a masked array

我有一个表示为 numpy 掩码数组的图像。图片由前景和背景组成,我对背景不感兴趣,所以我把它遮住了。这是一张对比度很差的图像,我想使用 skimage.exposure.equalize_hist

增加前景的对比度

我注意到 equalize_hist 函数采用命名参数 mask,以忽略未屏蔽的数据。

我的代码是这样的

import numpy as np
import skimage.exposure as ske

import matplotlib.pyplot as plt

# doesn't really exist
from proprietary import openImage, findForeground

imagePath = "...." # path to the image file
# image format is proprietary, so we have a custom function open it for us
# it returns a regular numpy uint16 2d array
# print(type(img), img.dtype, img.shape) shows
# `
# <class 'numpy.ndarray'> float64 (2688, 1151)
# `
img = openImage(imagePath)
foreground = findForeground(img) # this function sets all background pixels to white

# 65535 == white for a uint16 array
masked_img = np.ma.masked_where(foreground==65535, foreground)

# plotting this `masked_img` using plt.imshow works perfectly, the background is completely white
# and the foreground is shown as it is supposed to

# this goes wrong
mask = np.ma.getmask(masked_img)
equalized = ske.equalize_hist(masked_img, mask=mask)

ske.equalize_hist 调用生成此错误,我不确定原因。

    ---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-e2b4f8e60ef9> in <module>()
     37         print(type(mask))
     38         print(mask)
---> 39         equalized = ske.equalize_hist(fg, mask=mask)
     40         plt.imshow(equalized, cmap=cmap)
     41         plt.set_title("Equalized histogram with colormap {cmap}".format(cmap=cmap))

C:\Users\myuser\AppData\Local\Continuum\Anaconda3\lib\site-packages\skimage\exposure\exposure.py in equalize_hist(image, nbins, mask)
    165         cdf, bin_centers = cumulative_distribution(image[mask], nbins)
    166     else:
--> 167         cdf, bin_centers = cumulative_distribution(image, nbins)
    168     out = np.interp(image.flat, bin_centers, cdf)
    169     return out.reshape(image.shape)

C:\Users\myuser\AppData\Local\Continuum\Anaconda3\lib\site-packages\skimage\exposure\exposure.py in cumulative_distribution(image, nbins)
    125     True
    126     """
--> 127     hist, bin_centers = histogram(image, nbins)
    128     img_cdf = hist.cumsum()
    129     img_cdf = img_cdf / float(img_cdf[-1])

C:\Users\myuser\AppData\Local\Continuum\Anaconda3\lib\site-packages\skimage\exposure\exposure.py in histogram(image, nbins)
     86         return hist[idx:], bin_centers[idx:]
     87     else:
---> 88         hist, bin_edges = np.histogram(image.flat, bins=nbins)
     89         bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2.
     90         return hist, bin_centers

C:\Users\myuser\AppData\Local\Continuum\Anaconda3\lib\site-packages\numpy\lib\function_base.py in histogram(a, bins, range, normed, weights, density)
    495             mn, mx = 0.0, 1.0
    496         else:
--> 497             mn, mx = a.min() + 0.0, a.max() + 0.0
    498     else:
    499         mn, mx = [mi + 0.0 for mi in range]

TypeError: unsupported operand type(s) for +: 'MaskedIterator' and 'float'

有人知道为什么会这样吗?我很茫然。

正如@hpaulij 建议的那样,当您计划传递数据时,请尽可能远离屏蔽数组。鉴于您在此处显示的用法,没有特别的理由不只维护一个单独的掩码:

import numpy as np
import skimage.exposure as ske

import matplotlib.pyplot as plt

# doesn't really exist
from proprietary import openImage, findForeground

imagePath = "...." # path to the image file
# image format is proprietary, so we have a custom function open it for us
# it returns a regular numpy uint16 2d array
# print(type(img), img.dtype, img.shape) shows
# `
# <class 'numpy.ndarray'> float64 (2688, 1151)
# `
img = openImage(imagePath)
foreground = findForeground(img) # this function sets all background pixels to white

# 65535 == white for a uint16 array
mask = (foreground != 65536)

# plotting this `masked_img` using plt.imshow works perfectly, the background is completely white
# and the foreground is shown as it is supposed to

# foreground should work as well as the original img here
equalized = ske.equalize_hist(img, mask=mask)

还要记住,掩码数组的掩码与 equalize_hist is expecting. numpy.ma.MaskedArray sets invalid elementsTrue 的意义相反,而 equalize_hist 期望 valid 元素为 True.

proprietary.findForeground 只是 return 一个蒙版可能对您有益,而不是弄乱原始图像。这样做的好处是不会将掩码值绑定到图像的 dtype,而不是将 运行 绑定到饱和前景像素的问题上。如果您有能力做到这一点,您的代码将类似于:

mask = findForeground(img) # Now returns a boolean array of the correct size
...
equalized = ske.equalize_hist(img, mask=mask)

如您所见,这将从您的流程中删除步骤。