Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NumPy/OpenCV 2: how do I crop non-rectangular region?

I have a set of points that make a shape (closed polyline). Now I want to copy/crop all pixels from some image inside this shape, leaving the rest black/transparent. How do I do this?

For example, I have this:

enter image description here

and I want to get this:

enter image description here

like image 930
ffriend Avatar asked Mar 11 '13 14:03

ffriend


People also ask

How do I crop a frame in OpenCV?

There is no specific function for cropping using OpenCV, NumPy array slicing is what does the job. Every image that is read in, gets stored in a 2D array (for each color channel). Simply specify the height and width (in pixels) of the area to be cropped. And it's done!


2 Answers

*edit - updated to work with images that have an alpha channel.

This worked for me:

  • Make a mask with all black (all masked)
  • Fill a polygon with white in the shape of your ROI
  • combine the mask and your image to get the ROI with black everywhere else

You probably just want to keep the image and mask separate for functions that accept masks. However, I believe this does what you specifically asked for:

import cv2 import numpy as np  # original image # -1 loads as-is so if it will be 3 or 4 channel as the original image = cv2.imread('image.png', -1) # mask defaulting to black for 3-channel and transparent for 4-channel # (of course replace corners with yours) mask = np.zeros(image.shape, dtype=np.uint8) roi_corners = np.array([[(10,10), (300,300), (10,300)]], dtype=np.int32) # fill the ROI so it doesn't get wiped out when the mask is applied channel_count = image.shape[2]  # i.e. 3 or 4 depending on your image ignore_mask_color = (255,)*channel_count cv2.fillPoly(mask, roi_corners, ignore_mask_color) # from Masterfool: use cv2.fillConvexPoly if you know it's convex  # apply the mask masked_image = cv2.bitwise_and(image, mask)  # save the result cv2.imwrite('image_masked.png', masked_image) 
like image 149
KobeJohn Avatar answered Sep 29 '22 07:09

KobeJohn


The following code would be helpful for cropping the images and get them in a white background.

import cv2
import numpy as np

# load the image
image_path = 'input image path'
image = cv2.imread(image_path)

# create a mask with white pixels
mask = np.ones(image.shape, dtype=np.uint8)
mask.fill(255)

# points to be cropped
roi_corners = np.array([[(0, 300), (1880, 300), (1880, 400), (0, 400)]], dtype=np.int32)
# fill the ROI into the mask
cv2.fillPoly(mask, roi_corners, 0)

# The mask image
cv2.imwrite('image_masked.png', mask)

# applying th mask to original image
masked_image = cv2.bitwise_or(image, mask)

# The resultant image
cv2.imwrite('new_masked_image.png', masked_image)

Input Image: input image

Mask Image: mask image

Resultant output image: enter image description here

like image 40
Kanish Mathew Avatar answered Sep 29 '22 08:09

Kanish Mathew