Make an image contour black and white using open CV and Python
<p>I'm trying to paint part of an image as black and white using OpenCV2 and Python3. This is the code I'm trying:</p>

<pre><code>(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x,y), (x+w,y+h),0,0)
sub_face = frame[y:y+h, x:x+w]
# apply a gaussian blur on this new recangle image
# sub_face = cv2.GaussianBlur(sub_face,(9, 9), 30, borderType = 0)
sub_face = cv2.cvtColor(sub_face, cv2.COLOR_BGR2GRAY)

# merge this blurry rectangle to our final image
result_frame[y:y+sub_face.shape[0], x:x+sub_face.shape[1]] = sub_face
</code></pre>

<p>When I apply the GaussianBlur method, it works properly, but when I try the cvtColor method it fails with a message (on the last line): could not broadcast input array from shape (268,182) into shape (268,182,3). What am I doing wrong?</p>

<p>The <strong><em>c</em></strong> variable in first line is a contour (from motion detection).</p>

<p>I'm new into Python and OpenCV.</p>

<p>Thanks!</p>

<p>You are trying to assign a single channel that results from your <code>cv2.cvtColor</code> call to three channels at once as <code>result_frame</code> is a RGB / three channel image.  You are probably wanting to assign the single channel to all three channels.  One way to do this cleanly is to exploit <a href="http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html" rel="nofollow">NumPy broadcasting</a> by creating a singleton channel in the third dimension, then broadcasting the result over all channels.  Since you are using the <code>cv2</code> interface to OpenCV, the native datatype used for manipulating images is a NumPy array:</p>

<pre><code># merge this blurry rectangle to our final image
result_frame[y:y+sub_face.shape[0], x:x+sub_face.shape[1]] = sub_face[:,:,None]
</code></pre>

<p>The <code>:</code> operation in this context accesses all values in a particular dimension.  In this case, we want the first and second dimensions.  Therefore, <code>sub_face[:,:,None]</code> will make your single channel image 3D with the third dimension being a singleton (i.e. 1).  Using NumPy broadcasting will then <strong>broadcast</strong> this single channel image to all channels simultaneously.</p>

<p>Note that I didn't have to explicitly access the third dimension when assigning to <code>result_frame</code>.  That is because <code>result_frame[y:y+sub_face.shape[0], x:x+sub_face.shape[1]]</code> and <code>result_frame[y:y+sub_face.shape[0], x:x+sub_face.shape[1],:]</code> are the same thing as dropping indexing after the last dimension you specify implicitly assumes <code>:</code>.</p>

python opencv image-processing