Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Mask an image using Numpy/OpenCV?

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.

like image 662
Hidden Name Avatar asked Aug 01 '14 06:08

Hidden Name


People also ask

How do you mask in image processing?

How it is done. The general process of filtering and applying masks is consists of moving the filter mask from point to point in an image. At each point (x,y) of the original image, the response of a filter is calculated by a pre defined relationship. All the filters values are pre defined and are a standard.

How to do masking With OpenCV?

Use cv2.bitwise_and () to do masking with OpenCV. cv2.bitwise_and () is a function that performs bitwise AND processing as the name suggests. The AND of the values for each pixel of the input images src1 and src2 is the pixel value of the output image. Here, a grayscale image is used as a mask image for src2.

How do I mask pixel values in a NumPy array?

Use clip () to clip pixel values to the range 0 to 255. Note that unexpected results occur when saving as an image file if there is a value exceeding the maximum value 255 of uint8. Masking is easy with NumPy's array operations. The arithmetic operations of arrays of the same shape are operations for each pixel at the same position.

Can OpenCV do alpha blending with NumPy?

In addition to cv2.bitwise_and (), OpenCV also includes cv2.bitwise_or (), cv2.bitwise_xor () and cv2.bitwise_not () for performing OR, XOR and NOT operation. Since NumPy can easily perform arithmetic operations for each pixel of the array, alpha blending can also be realized with a simple expression.

How to reshape an array of images using NumPy?

shape of the original array is unpacked and passed to reshape (). Another way is to use np.newaxis instead of reshape (). In the example of the alpha blend above, the image was composited at a uniform ratio over the entire surface of the image, but using NumPy, it is possible to composite based on another image (array).


4 Answers

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)
like image 171
Froyo Avatar answered Oct 22 '22 21:10

Froyo


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)
like image 5
deinonychusaur Avatar answered Oct 22 '22 20:10

deinonychusaur


Using NumPy assignment to an indexed array:

im[circle == 0] = [0, 0, 0]
like image 1
Delgan Avatar answered Oct 22 '22 20:10

Delgan


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
like image 1
Mazdak Avatar answered Oct 22 '22 19:10

Mazdak