用NumPy的np.tile()替换MATLAB的repmat()

时间:2018-06-06 04:28:13

标签: python matlab numpy

我正在尝试移植以下函数,以便将图像从MATLAB阈值化为Python。但是我无法转换以下MATLAB代码:

maskedRGBImage(repmat(~BW,[1 1 3])) = 0

到Python。此代码将图像maskedRGBImage中的所有背景像素设置为零,BWFalse

这是完整的MATLAB代码:

function [BW,maskedRGBImage] = createMask(RGB)    

I = rgb2hsv(RGB);

% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.985;
channel1Max = 0.460;

% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.264;
channel2Max = 1.000;

% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.000;
channel3Max = 1.000;

% Create mask based on chosen histogram thresholds
sliderBW = ( (I(:,:,1) >= channel1Min) | (I(:,:,1) <= channel1Max) ) & ...
    (I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
    (I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;

% Initialize output masked image based on input image.
maskedRGBImage = RGB;

% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;

end

这就是我到目前为止将代码转换为Python和NumPy的方式:

def createMask( image ):
    maskedRGBImage = image
    image = cv2.cvtColor( image, cv2.COLOR_RGB2HSV )

    channel1Min = 0.985;
    channel1Max = 0.460;

    channel2Min = 0.264;
    channel2Max = 1.000;

    channel3Min = 0.000;
    channel3Max = 1.000;

    sliderBW = ((image[:,:,0] >= channel1Min) | (image[:,:,0] <= channel1Max) ) & (image[:,:,1] >= channel2Min ) & (image[:,:,1] <= channel2Max) & (image[:,:,2] >= channel3Min ) & (image[:,:,2] <= channel3Max)
    BW = sliderBW
    maskedRGBImage[(np.array([np.tile(~BW, (1,1)) for i in range(3)]))] = 0

我尝试使用如图所示的np.tile函数,但这不起作用并在最后一行返回以下错误:

  

ValueError:操作数无法与形状(1024,768,3) (3,1024,768)

一起广播

maskedRGBImage的形状为(1024,768,3)BW的形状为(1024,768),但我无法将BW转换为正确的形状。如何用repmat或任何其他Python函数替换MATLAB的np.tile函数?

1 个答案:

答案 0 :(得分:0)

正如您在评论中写的那样,问题出在以下几行:

maskedRGBImage[(np.array([np.tile(~BW, (1,1)) for i in range(3)]))] = 0

首先,请注意np.tile(~BW, (1, 1))什么都不做:np.tile相当于MATLAB的repmat(),它会按照您指定的次数重复矩阵,只有一次。所以你返回~BW。您可以通过调用

来验证
np.all(np.tile(~BW, (1, 1)) == ~BW)

返回True,表示这实际上等于~BW

其次,您手动尝试使用列表解析重新创建repmat()功能:

np.array([np.tile(~BW, (1,1)) for i in range(3)])

但请注意,这会返回一个大小为(3, 1024, 768)的数组,而您的图片的形状为(1024, 768, 3)。这实际上是错误消息所说的内容。

可能的解决方案是删除列表理解并使用np.tile作为repmat()替换。实际上,您希望以np.tile作为参数调用(1, 1, 3),在第三维中将输入数组平铺三次。

虽然在MATLAB中这是开箱即用的,但NumPy要求您在三维空间中输入数组BW,即将其从维(1024, 768)更改为(1024, 768, 1)。这是使用np.newaxis

完成的
np.tile(~BW[:, :, np.newaxis], (1, 1, 3))

使用该索引编制maskedRGBImage变量应该可以正常工作:

maskedRGBImage[np.tile(~BW[:, :, np.newaxis], (1, 1, 3))] = 0