How to convert 1-channel numpy matrix to 4-channel monochromatic image
<p>I am working on a pyqt project with numpy and cv2. Basically, I want to use a binary numpy mask <code>(1024, 1024)</code> to create a 4 channel monochromatic image <code>(1024, 1024, 4)</code>, where all 1s from the mask are pink and all 0s are invisible. Then I convert the image and show it as overlay in my QScene to highlight some pixels in another image.</p>

<p>My current approach does the job, but is too slow and I'm sure that numpy provides something more convenient.</p>

<pre><code>color = (255, 0, 238, 100)
r = (mask * color[0]).reshape((w*h))
g = (mask * color[1]).reshape((w*h))
b = (mask * color[2]).reshape((w*h))
a = (mask * color[3]).reshape((w*h))

rgba = np.dstack((r, g, b, a)).reshape((w, h, 4))
transposed = np.transpose(rgba, axes=[1, 0, 2])
</code></pre>

<p>Is there a better way to show a mask overlay? I don't insist on using numpy, however, it is important that I can set the color, as I will be needing several colors.</p>

<p>Yes! Use <a href="http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html" rel="nofollow"><code>NumPy broadcasting</code></a> to clean it up and have a <code>one-liner</code>, like so -</p>

<pre><code>transposed = mask.T[...,None]*color
</code></pre>

<p><strong>Explanation:</strong></p>

<ol>
<li>Use <code>mask.T</code> to do the <code>np.transpose</code> operation done at the end.</li>
<li>Use <code>[...,None]</code> on the transposed array to basically push all its dimensions to the front and create a singleton dim (dim with <code>length=1</code>) as the last axis. For introducing this new axis, we have used an alias for <a href="http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#numpy.newaxis" rel="nofollow"><code>np.newaxis</code></a> - <code>None</code>. Thus, we would achieve broadcasting for the transposed array along its last axis aligned with the elements of <code>color</code>.</li>
<li>Finally, we perform the element-wise multiplication itself, which in fact would be a <code>broadcasted</code> operation.</li>
</ol>

<hr>

<p>You can perform the creation of new axis part at the start and then use <code>np.transpose</code> or <code>np.swapaxes</code> and this would be closer to your original code. So, alternatively we could have :</p>

<pre><code>transposed = mask[:,:,None].transpose(1,0,2)*color
</code></pre>

<p>and, </p>

<pre><code>transposed = mask[:,:,None].swapaxes(0,1)*color
</code></pre>

python numpy pyqt4