13

I have an image I load with:

im = cv2.imread(filename)

I want to keep data that is in the center of the image. I created a circle as a mask of the area I want to keep.

I created the circle with:

height,width,depth = im.shape
circle = np.zeros((height,width))
cv2.circle(circle,(width/2,height/2),280,1,thickness=-1)

How can I mask out the data outside of the circle from the original image?

masked_data = im * circle

does not work.

3
  • do you want to crop circle ? Commented Aug 1, 2014 at 7:03
  • Yes. I want to keep everything within the circle. Commented Aug 1, 2014 at 7:17
  • So is this just a question of numpy broadcasting? Commented Aug 1, 2014 at 7:25

4 Answers 4

24

Use cv2.bitwise_and and pass the circle as mask.

im = cv2.imread(filename)
height,width,depth = im.shape
circle_img = np.zeros((height,width), np.uint8)
cv2.circle(circle_img,(width/2,height/2),280,1,thickness=-1)

masked_data = cv2.bitwise_and(im, im, mask=circle_img)

cv2.imshow("masked", masked_data)
cv2.waitKey(0)
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot for your answer @Froyo. The color parameter has to be 255 for me to work. So the code should becv2.circle(circle_img,(width/2,height/2),280,255,thickness=-1)
(width/2,height/2) gives the position of the circle (hopefully the center) on the image while 280 is the size (hopefully the radius) of the circle. Does this positioning directly translate to the x,y cordinate positioning?
width and height are backwards in np.zeros, and the circle fill color should be 255
5

circle is just a 2D array with 1.0s and 0.0s. Numpy needs help to understand what you want to do with the third dimension of your im so you must give it an extra axis and then your line would work.

masked_data = im * circle[..., np.newaxis]

But note that the masking is simply setting the color to (0, 0, 0) for things outside the circle according to your code if the image lacks an alpha-channel.

However you have another potential problem: circle will be of the default data-type (which probably will be float64 or float32. That's not good for your image, so you should change the line where you create circle to

circle = np.zeros((height, width), dtype=im.dtype)

Comments

1

Using NumPy assignment to an indexed array:

im[circle == 0] = [0, 0, 0]

1 Comment

This is a community wiki for a similar question answered by @unutbu.
0

In this case if you want to have a circular image you must write a new algorithm and first you must be able to access to the coordinates of the pixels. Then you can simply compare pixels that are not within the scope of that circle or not and replace them with some value (or NULL if it's accepted with your image format criteria).

Here is an example:

import cv2
import numpy as np
im = cv2.imread('sss.png')


def facechop(im):

 height,width,depth = im.shape
 #circle = np.zeros((height,width))
 #print circle
 x=width/2
 y=height/2
 circle=cv2.circle(im,(width/2,height/2),180,1,thickness=1)
 #newcameramtx, roi=cv2.getOptimalNewCameraMatrix(im,10,(w,h),1,(w,h))
 cv2.rectangle(im,(x-180,y-180),(x+180,y+180),(0,0,255),2)
 crop_img = im[y-180:y+180,x-180:x+180]
 lastim=np.equal(crop_img,circle)
 #dd=np.logical_and(crop_img,circle)

 for i in range(len(last_im)) :
     if last_im[i].all()==False:
         crop_img[i]=[0,0,0]


 cv2.imshow('im',crop_img)
if __name__ == '__main__':
    facechop(im)
    while(True):
        key = cv2.waitKey(20)
        if key in [27, ord('Q'), ord('q')]:
            break

1 Comment

this is awful code, awful approaches/tactics, slow and inefficient, not using the facilities that either of the libraries provide. maybe you should revise this 10 years later, just to make sure nobody tries to learn bad patterns from this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.