简体   繁体   中英

How to fill a contour plot mask and retain data inside the contour and blackout the rest

I have an image like so, 在此处输入图像描述

By using the following code,

 import numpy as np import cv2 # load the image image = cv2.imread("frame50.jpg", 1) #color boundaries [B, G, R] lower = [0, 3, 30] upper = [30, 117, 253] # create NumPy arrays from the boundaries lower = np.array(lower, dtype="uint8") upper = np.array(upper, dtype="uint8") # find the colors within the specified boundaries and apply # the mask mask = cv2.inRange(image, lower, upper) output = cv2.bitwise_and(image, image, mask=mask) ret,thresh = cv2.threshold(mask, 50, 255, 0) if (int(cv2.__version__[0]) > 3): contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) else: im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) if len(contours):= 0, # find the biggest countour (c) by the area c = max(contours. key = cv2,contourArea) x,y,wh = cv2:boundingRect(c) ROI = image[y,y+h: x.x+w] cv2,imshow('ROI'.ROI) cv2.imwrite('ROI,png'.ROI) cv2.waitKey(0)

I get the following cropped image,

在此处输入图像描述

I would like to retain all data within the orange hand-drawn boundary including the boundary itself and blackout the rest. In the image above the data outside the orange boundary is still there. I do not want that. How do i fill the mask which is like this now so that i can retain data inside the orange boundary,

在此处输入图像描述

I would still like to retain other properties like the rectangular bounding box. I don't want anything else to change. How do I go about this? Thanks.

Here is one way to do that in Python/OpenCV.

  • Read the input
  • Threshold on the orange color
  • Find the (largest) contour and get its bounding box
  • Draw a white filled contour on a black background as a mask
  • Create a copy of the input with an alpha channel
  • Copy the mask into the alpha channel
  • Crop the ROI
  • Save the results

Input:

在此处输入图像描述

import numpy as np
import cv2

# load the image
image = cv2.imread("frame50.jpg")

#color boundaries [B, G, R]
lower = (0, 70, 210)
upper = (50, 130, 255)

# threshold on orange color
thresh = cv2.inRange(image, lower, upper)

# get largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
x,y,w,h = cv2.boundingRect(big_contour)

# draw filled contour on black background
mask = np.zeros_like(image)
cv2.drawContours(mask, [big_contour], 0, (255,255,255), -1)

# put mask into alpha channel of input
new_image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
new_image[:,:,3] = mask[:,:,0]

# crop 
ROI = new_image[y:y+h, x:x+w]
   
# save result 
cv2.imwrite('frame50_thresh.jpg',thresh)
cv2.imwrite('frame50_mask.jpg',mask)
cv2.imwrite('frame50_new_image.jpg',new_image)
cv2.imwrite('frame50_roi.png',ROI)

# show images
cv2.imshow('thresh',thresh)
cv2.imshow('mask',mask)
cv2.imshow('new_image',new_image)
cv2.imshow('ROI',ROI)
cv2.waitKey(0)

Threshold image:

在此处输入图像描述

Mask Image:

在此处输入图像描述

New image with mask in alpha channel:

在此处输入图像描述

Cropped ROI

在此处输入图像描述

As you desire (in your comments to my previous answer) to have the outer region to be black rather than transparent, you can do that as follows in Python/OpenCV with a couple of lines changed to multiply the mask by the input rather than put the mask into the alpha channel.

Input:

在此处输入图像描述

import numpy as np
import cv2

# load the image
image = cv2.imread("frame50.jpg")

#color boundaries [B, G, R]
lower = (0, 70, 210)
upper = (50, 130, 255)

# threshold on orange color
thresh = cv2.inRange(image, lower, upper)

# get largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
x,y,w,h = cv2.boundingRect(big_contour)

# draw filled contour on black background
mask = np.zeros_like(image)
cv2.drawContours(mask, [big_contour], 0, (255,255,255), -1)

# apply mask to input image
new_image = cv2.bitwise_and(image, mask)

# crop 
ROI = new_image[y:y+h, x:x+w]
   
# save result 
cv2.imwrite('frame50_thresh.jpg',thresh)
cv2.imwrite('frame50_mask.jpg',mask)
cv2.imwrite('frame50_new_image2.jpg',new_image)
cv2.imwrite('frame50_roi2.jpg',ROI)

# show images
cv2.imshow('thresh',thresh)
cv2.imshow('mask',mask)
cv2.imshow('new_image',new_image)
cv2.imshow('ROI',ROI)
cv2.waitKey(0)

new_image after applying the mask:

在此处输入图像描述

cropped roi image:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM