【问题标题】:Python numpy array assignment to integer indexed flat slicePython numpy数组分配给整数索引平面切片
【发布时间】:2017-02-21 04:08:58
【问题描述】:

在学习 numpy 的过程中,我编写了 LSB(隐写术)加密的代码:

def str2bits_nparray(s):
    return np.array(map(int, (''.join(map('{:07b}'.format, bytearray(s))))), dtype=np.bool)

def LSB_encode(img, msg, channel):
    msg_bits = str2bits_nparray(msg)
    xor_mask = np.zeros_like(img, dtype=np.bool)
    xor_mask[:, :, channel].flat[:len(msg_bits)] = np.ones_like(msg_bits, dtype=np.bool)
    img[xor_mask] = img[xor_mask] >> 1 << 1 | msg_bits


msg = 'A' * 1000
img_name = 'screenshot.png'
chnl = 2
img = imread(img_name)
LSB_encode(img, msg, chnl)

代码工作正常,但是当我尝试制作chnl = [2, 1] 时:

xor_mask[:, :, channel].flat[:len(msg_bits)] = np.ones_like(msg_bits, dtype=np.bool)

不使用

xor_mask 赋值

xor_mask[:, :,[2, 1]].flat[:len(msg_bits)]

有没有办法解决这个问题?

我尝试了通过通道进行 for 循环的解决方案:

for ch in channel:
    xor_mask[:, :, ch].flat[:len(msg_bits)] = np.ones_like(msg_bits, dtype=np.bool)

但这不是我想要的

xor_mask[:, :,[2, 1]].flat[:len(msg_bits)] = np.ones_like(msg_bits, dtype=np.bool)

【问题讨论】:

    标签: python arrays python-2.7 numpy slice


    【解决方案1】:

    IIUC,这是一种获取线性索引的方法,然后切片到 no 的长度。需要设置的元素数量,然后执行设置-

    m,n,r = xor_mask.shape  # Store shape info
    
    # Create range arrays corresponding to those shapes
    x,y,z = np.ix_(np.arange(m),np.arange(n),channel)
    
    # Get the indices to be set and finaally perform the setting
    idx = (x*n*r + y*r + z).ravel()[:len(msg_bits)]
    xor_mask.ravel()[idx] = 1
    

    示例运行 -

    In [180]: xor_mask
    Out[180]: 
    array([[[25, 84, 37, 96, 72, 84, 91],
            [94, 56, 78, 71, 48, 65, 98]],
    
           [[33, 56, 14, 92, 90, 64, 76],
            [71, 71, 77, 31, 96, 36, 49]]])
    
    In [181]: # Other inputs
         ...: channel = np.array([2,1])
         ...: msg_bits = np.array([2,3,6,1,4])
         ...: 
    
    In [182]: m,n,r = xor_mask.shape  # Store shape info
         ...: x,y,z = np.ix_(np.arange(m),np.arange(n),channel)
         ...: idx = (x*n*r + y*r + z).ravel()[:len(msg_bits)]
         ...: xor_mask.ravel()[idx] = 1
         ...: 
    
    In [183]: xor_mask # First 5 elems from flattend version
                       # of xor_mask[:,:,channel] set as 1 
                       # as len(msg_bits) = 5.
    Out[183]: 
    array([[[25,  1,  1, 96, 72, 84, 91],
            [94,  1,  1, 71, 48, 65, 98]],
    
           [[33, 56,  1, 92, 90, 64, 76],
            [71, 71, 77, 31, 96, 36, 49]]])
    

    相反,如果您尝试在3D 输入数组中沿channel 中的第一个:2 然后沿第二个1 等设置所有元素,我们需要以不同的方式创建 idx,就像这样 -

    idx = (x*n*r + y*r + z).transpose(2,0,1).ravel()[:len(msg_bits)]
    

    【讨论】:

      猜你喜欢
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      • 2017-03-06
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 2017-06-24
      • 2015-05-28
      相关资源
      最近更新 更多