Life2Coding
Cropping Polygon or Non Rectangular Region from Image using OpenCV Python

This post will be helpful in learning OpenCV using Python programming. Here I will show how to implement OpenCV functions and apply them in various aspects using some great examples. Then the output will be visualized along with the comparisons.

We will also discuss the basic of image processing and provide the detail explanation related to the OpenCV functions.

Requirements:

First, you need to setup your Python Environment with OpenCV. You can easily do it by following Life2Coding’s tutorial on YouTube: Linking OpenCV with Python 3

Goals:

The goal is to crop non-rectangular or polygon region from images using OpenCV python.

Documentation:

imread()

retval=cv.imread(filename[, flags])

Loads an image from a file.

Parameters
filename Name of file to be loaded.
flags Flag that can take values of cv::ImreadModes

drawContours()

image=cv.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])

Draws contours outlines or filled contours.

Parameters
image Destination image.
contours All the input contours. Each contour is stored as a point vector.
contourIdx Parameter indicating a contour to draw. If it is negative, all the contours are drawn.
color Color of the contours.
thickness Thickness of lines the contours are drawn with. If it is negative (for example, thickness=FILLED ), the contour interiors are drawn.
lineType Line connectivity. See LineTypes
hierarchy Optional information about hierarchy. It is only needed if you want to draw only some of the contours (see maxLevel ).
maxLevel Maximal level for drawn contours. If it is 0, only the specified contour is drawn. If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This parameter is only taken into account when there is hierarchy available.
offset Optional contour shift parameter. Shift all the drawn contours by the specified \(\texttt{offset}=(dx,dy)\) .

fillPoly()

img=cv.fillPoly(img, pts, color[, lineType[, shift[, offset]]])
img=cv.fillPoly(img, pts, color[, lineType[, shift[, offset]]])

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Fills the area bounded by one or more polygons.

Parameters
img Image.
pts Array of polygons where each polygon is represented as an array of points.
color Polygon color.
lineType Type of the polygon boundaries. See LineTypes
shift Number of fractional bits in the vertex coordinates.
offset Optional offset of all points of the contours.

bitwise_and()

dst=cv.bitwise_and(src1, src2[, dst[, mask]])

computes bitwise conjunction of the two arrays (dst = src1 & src2) Calculates the per-element bit-wise conjunction of two arrays or an array and a scalar.

Parameters
src1 first input array or a scalar.
src2 second input array or a scalar.
dst output array that has the same size and type as the input arrays.
mask optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed.

boundingRect()

retval=cv.boundingRect(array)

Calculates the up-right bounding rectangle of a point set or non-zero pixels of gray-scale image.

Parameters
array Input gray-scale image or 2D point set, stored in std::vector or Mat.

bitwise_not()

dst=cv.bitwise_not(src[, dst[, mask]])

Inverts every bit of an array.

Parameters
src input array.
dst output array that has the same size and type as the input array.
mask optional operation mask, 8-bit single channel array, that specifies elements of the output array to be changed.

imshow()

None=cv.imshow(winname, mat)

Displays an image in the specified window.

Parameters
winname Name of the window.
mat Image to be shown.

waitKey()

retval=cv.waitKey([, delay])

Waits for a pressed key.

Parameters
delay Delay in milliseconds. 0 is the special value that means “forever”.

destroyAllWindows()

None=cv.destroyAllWindows()

Destroys all of the HighGUI windows.

Steps:

  • Open an image using cv2.imread()
  • Create a black background image of the same shape of original image using np.zeros()
  • Define the polygon points
  • Draw the mask based on the points using cv2.drawContours()
  • You can also use cv2.fillPoly() to draw mask for those points
  • Get only the croped polygon portion of the mask from the image using cv2.bitwsie_and()
  • Get the bounding rect of the cropped region using cv2.boundingRect()
  • Draw an white background image of the same size of original image using np.ones_like() and multiply it with 255 for white
  • Get the white background for the region except the masked region using cv2.bitwise_not()
  • Overlap the cropped region and white region
  • Display all the images using cv2.imshow()
  • Wait for keyboard button press using cv2.waitKey()
  • Exit window and destroy all windows using cv2.destroyAllWindows()

Example Code:

import numpy as np
import cv2


if __name__ == '__main__':

    img = cv2.imread("./image/hanif.jpg")

    mask = np.zeros(img.shape[0:2], dtype=np.uint8)
    points = np.array([[[100,350],[120,400],[310,350],[360,200],[350,20],[25,120]]])

    #method 1 smooth region
    cv2.drawContours(mask, [points], -1, (255, 255, 255), -1, cv2.LINE_AA)

    #method 2 not so smooth region
    # cv2.fillPoly(mask, points, (255))

    res = cv2.bitwise_and(img,img,mask = mask)
    rect = cv2.boundingRect(points) # returns (x,y,w,h) of the rect
    cropped = res[rect[1]: rect[1] + rect[3], rect[0]: rect[0] + rect[2]]

    ## crate the white background of the same size of original image
    wbg = np.ones_like(img, np.uint8)*255
    cv2.bitwise_not(wbg,wbg, mask=mask)
    # overlap the resulted cropped image on the white background
    dst = wbg+res

    cv2.imshow('Original',img)
    cv2.imshow("Mask",mask)
    cv2.imshow("Cropped", cropped )
    cv2.imshow("Samed Size Black Image", res)
    cv2.imshow("Samed Size White Image", dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Output:

5dbf960cae2ea Cropping Polygon or Non Rectangular Region from Image using OpenCV Python
life2coding_icon [] Cropping Polygon or Non Rectangular Region from Image using OpenCV Python

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.