I have an input image where I have drawn the green boundaries which I need to mask.
I am able to identify the boundary, but my mask is all black with baground is black. how can I fill the boundary region with different color. May be keep the background white and mask region as black
Input image
im = cv2.imread(imagePath)
plt.imshow(im)
#color boundaries [B, G, R]
lower = np.array([0,120,0])
upper = np.array([200,255,100])
# threshold on green color
thresh = cv2.inRange(im, lower, upper)
plt.imshow(thresh)
# 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(im)
cv2.drawContours(mask, [big_contour], 0, (255,255,255), cv2.FILLED)
plt.imshow(mask)
# apply mask to input image
new_image = cv2.bitwise_and(im, mask)
Generated Output
I am expecting the green countor will be filled with some different color. May be white background with black countour. or transparent background
To fill the contours drawn on the mask you should use the opencv's fillPoly function :
im = cv2.imread(imagePath)
plt.imshow(im)
#color boundaries [B, G, R]
lower = np.array([0,120,0])
upper = np.array([200,255,100])
# threshold on green color
thresh = cv2.inRange(im, lower, upper)
plt.imshow(thresh)
# 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(im)
# cv2.drawContours(mask, [big_contour], 0, (255,255,255), cv2.FILLED)
mask = cv2.fillPoly(mask, pts =[big_contours], color=(255,255,255)) # fill the polygon
plt.imshow(mask)
# apply mask to input image
new_image = cv2.bitwise_and(im, mask)
This code generated canny image and then generates contours, then it generates mask and after this all it shows the output as the mixture of original and the mask image:
import cv2
import numpy as np
image = cv2.imread('image.png')
cv2.waitKey(0)
# Grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Find Canny edges
edged = cv2.Canny(gray, 30, 200)
cv2.waitKey(0)
# Finding Contours
# Use a copy of the image e.g. edged.copy()
# since findContours alters the image
contours, hierarchy = cv2.findContours(edged,
cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.imshow('Canny Edges After Contouring', edged)
print("Number of Contours found = " + str(len(contours)))
# Draw all contours
# -1 signifies drawing all contours
cv2.drawContours(image, contours, -1, (0, 0, 255), 2)
mask = np.zeros_like(image)
# cv2.drawContours(mask, [big_contour], 0, (255,255,255), cv2.FILLED)
cv2.fillPoly(mask, pts =contours, color=(0,255,0)) # fill the polygon
new_image = cv2.bitwise_and(image, mask)
while True:
cv2.imshow('Contours', image)
cv2.imshow('mask', mask)
cv2.imshow('new_image', new_image)
cv2.waitKey(1)
# cv2.destroyAllWindows()
Original image:
Edged image:
contours found:
mask:
Final image:
Also you can change color of the mask fill.
Related
i am new with CV2 with python.
i have many images, they have many big and small curvy structures.
and i have to get the biggest big one contour among all.
but i failed.
my codes and images are below...
import cv2 as cv
img_color = cv.imread('ex1.png')
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
#dbg contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
_, contours, hierarchy = cv.findContours(img_binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for cnt in contours:
cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3) # blue
#dbg cv.imshow("result", img_color)
#dbg cv.waitKey(0)
cv.imwrite('save_image1.png', img_color)
for cnt in contours:
hull = cv.convexHull(cnt)
cv.drawContours(img_color, [hull], 0, (0, 0, 255), 5)
#dbg cv.imshow("result", img_color)
#dbg cv.waitKey(0)
cv.imwrite('save_image2.png', img_color)
example of input image ("ex1.png") is like...
the result output image ("save_image2.png") is like...
...
but,
what i want to retrieve is like below... (any of blue or red, i can use them ;)
i mean, the result contour must be just big one which includes everything.
thank you for reading util here(; )
You asked for outline/contour of all regions rather than just the largest. So here is how to do that in Python/OpenCV.
Read the input
Convert to gray
Threshold to binary
Get all the points where the value is greater than 0 and transpose (since numpy use y,x convention and OpenCV wants x,y)
Compute the convex hull of the points
Draw a poly line on a copy of the input
Draw a white filled polygon on a black image
Get the contour of the white filled polygon
Draw the contour on a copy of the input
Save results
Input:
import cv2
import numpy as np
img_color = cv2.imread('ex1.png')
img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY)
img_binary = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# get convex hull
points = np.column_stack(np.where(img_binary.transpose() > 0))
hull = cv2.convexHull(points)
# draw convex hull on input image in green
result = img_color.copy()
cv2.polylines(result, [hull], True, (0,0,255), 2)
# draw white filled hull polygon on black background
mask = np.zeros_like(img_binary)
cv2.fillPoly(mask, [hull], 255)
# get the largest contour from result2
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
# draw contour on copy of input
contr = img_color.copy()
contr = cv2.drawContours(contr, [big_contour], 0, (0,0,255), 2)
# save result2
cv2.imwrite('ex1_convex_hull.png', result)
cv2.imwrite('ex1_convex_hull_contour.png', contr)
# show result2
cv2.imshow('result', result)
cv2.imshow('contr', contr)
cv2.waitKey(0)
cv2.destroyAllWindows()
Resulting convex hull:
Contour of convex hull:
Here is one way to do that in Python/OpenCV.
Use max(contours, key=cv2.contourArea) to get the largest one.
Input:
import cv2
img_color = cv2.imread('ex1.png')
img_gray = cv2.cvtColor(img_color, cv2.COLOR_BGR2GRAY)
img_binary = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
contours = cv2.findContours(img_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
img_contour = img_color.copy()
cv2.drawContours(img_contour, [big_contour], 0, (0,0,255), 2)
cv2.imwrite('ex1_contour.png', img_contour)
cv2.imshow('img_contour', img_contour)
cv2.waitKey(0)
cv2.destroyAllWindows()
I have the following image of a lego board with some bricks on it
Now I am trying to detect the thick black lines (connecting the white squares) with OpenCV. I have already experimented a lot with HoughLinesP, converted the image to gray or b/w before, applied blur, ...
Nonthing led to usable results.
# Read image
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# Resize Image
img = cv2.resize(img, (0,0), fx=0.25, fy=0.25)
# Initialize output
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
# Median blurring to get rid of the noise; invert image
img = cv2.medianBlur(img, 5)
# Adaptive Treshold
bw = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY,15,8)
# HoughLinesP
linesP = cv2.HoughLinesP(bw, 500, np.pi / 180, 50, None, 50, 10)
# Draw Lines
if linesP is not None:
for i in range(0, len(linesP)):
l = linesP[i][0]
cv2.line(out, (l[0], l[1]), (l[2], l[3]), (0,0,255), 3, cv2.LINE_AA)
The adaptive treshold lets you see edges quite well, but with HoughLinesP you don't get anything usable out of it
What am I doing wrong?
Thanks, both #fmw42 and #jeru-luke for your great solutions to this problem! I liked isolating / masking the green board, so I combined both:
import cv2
import numpy as np
img = cv2.imread("image.jpg")
scale_percent = 50 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_component = lab[:,:,1]
# binary threshold the a-channel
th = cv2.threshold(a_component,127,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
# numpy black
black = np.zeros((img.shape[0],img.shape[1]),np.uint8)
# function to obtain the largest contour in given image after filling it
def get_region(image):
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)
mask = cv2.drawContours(black,[c],0,255, -1)
return mask
mask = get_region(th)
# turning the region outside the green block white
green_block = cv2.bitwise_and(img, img, mask = mask)
green_block[black==0]=(255,255,255)
# median blur
median = cv2.medianBlur(green_block, 5)
# threshold on black
lower = (0,0,0)
upper = (15,15,15)
thresh = cv2.inRange(median, lower, upper)
# apply morphology open and close
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (29,29))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# filter contours on area
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
result = green_block.copy()
for c in contours:
area = cv2.contourArea(c)
if area > 1000:
cv2.drawContours(result, [c], -1, (0, 0, 255), 2)
# view result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Here I am presenting a repeated segmentation approach using color.
This answer is based on the usage of LAB color space
1. Isolating the green lego block
img = cv2.imread(image_path)
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_component = lab[:,:,1]
# binary threshold the a-channel
th = cv2.threshold(a_component,127,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
th
# function to obtain the largest contour in given image after filling it
def get_region(image):
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
c = max(contours, key = cv2.contourArea)
black = np.zeros((image.shape[0], image.shape[1]), np.uint8)
mask = cv2.drawContours(black,[c],0,255, -1)
return mask
mask = get_region(th)
mask
# turning the region outside the green block white
green_block = cv2.bitwise_and(img, img, mask = mask)
green_block[black==0]=(255,255,255)
green_block
2. Segmenting the road
To get an approximate region of the road, I subtracted the mask and th.
cv2.subtract() performs arithmetic subtraction, where cv2 will take care of negative values.
road = cv2.subtract(mask,th)
# `road` contains some unwanted spots/contours which are removed using the function "get_region"
only_road = get_region(road)
only_road
Masking only the road segment with the original image gives
road_colored = cv2.bitwise_and(img, img, mask = only_road)
road_colored[only_road==0]=(255,255,255)
road_colored
From the above image only the black regions (road) are present, which is easy to segment:
# converting to grayscale and applying threshold
th2 = cv2.threshold(road_colored[:,:,1],127,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
# using portion of the code from fmw42's answer, to get contours above certain area
contours = cv2.findContours(th2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
result = img.copy()
for c in contours:
area = cv2.contourArea(c)
if area > 1000:
cv2.drawContours(result, [c], -1, (0, 0, 255), 4)
result
Note:
To clean up the end result, you can apply morphological operations on th2 before drawing contours.
Here is one way to do that in Python/OpenCV.
Read the image
Apply median blur
Threshold on black color using cv2.inRange()
Apply morphology to clean it up
Get contours and filter on area
Draw contours on input
Save the result
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('black_lines.jpg')
# median blur
median = cv2.medianBlur(img, 5)
# threshold on black
lower = (0,0,0)
upper = (15,15,15)
thresh = cv2.inRange(median, lower, upper)
# apply morphology open and close
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (29,29))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# filter contours on area
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
result = img.copy()
for c in contours:
area = cv2.contourArea(c)
if area > 1000:
cv2.drawContours(result, [c], -1, (0, 0, 255), 2)
# save result
cv2.imwrite("black_lines_threshold.jpg", thresh)
cv2.imwrite("black_lines_morphology.jpg", morph)
cv2.imwrite("black_lines_result.jpg", result)
# view result
cv2.imshow("threshold", thresh)
cv2.imshow("morphology", morph)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold image:
Morphology image:
Result:
I am new in computer vision, and I want to create a program which helps me to detect box in the image and save as an image.
and etc...
I tried some code but did not get my desired result.
here is my code and its output.
import cv2
# Load iamge, grayscale, adaptive threshold
image = cv2.imread('image.jpeg')
result = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,51,9)
# Fill rectangular contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(thresh, [c], -1, (255,255,255), -1)
# Morph open
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=4)
# Draw rectangles
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 3)
cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('image', image)
cv2.waitKey()
output:
All you need to do is simply first remove the outermost white area, that is, make it black so that we can detect the boxes without any issues using the cv2.RETR_EXTERNAL flag as they are not touching. Then we'll just extract the boxes one by one.
To remove the outmost area, I have used the point polygon test of the contours. If the point (1, 1) lies inside or on a contour, it is not drawn and every other contour will be drawn on a new image. From this new image, I have read the box contours and extracted them.
import cv2
import numpy as np
img = cv2.imread("2lscp.png", cv2.IMREAD_GRAYSCALE)
ret, img = cv2.threshold(img, 50, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
Contours = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2]
newImg = np.zeros(img.shape, dtype=np.uint8)
for Contour in Contours:
if cv2.pointPolygonTest(Contour, (1, 1), False) == -1:
cv2.drawContours(newImg, [Contour], -1, 255, 1)
Contours = cv2.findContours(newImg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
for Contour in Contours:
[x, y, w, h] = cv2.boundingRect(Contour)
cv2.imshow("box extracted", img[y:y+h, x:x+w])
cv2.waitKey(0)
cv2.destroyAllWindows()
This case seems particularly simple because the image is quasi-binary. Detect the contours of the white regions and select those that have an area like 10 to 15% of the whole image. These are the desired boxes. Then fit a rectangle or rotated rectangle.
No need for additional processing.
Here is solution
try this:
import cv2
import numpy as np
#Read input image
img = cv2.imread('hw_data.png')
#convert from BGR to HSV color space
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#apply threshold
thresh = cv2.threshold(gray, 30, 255, cv2.THRESH_BINARY)[1]
# find contours and get one with area about 180*35
# draw all contours in green and accepted ones in red
contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
#area_thresh = 0
min_area = 0.95*180*44
max_area = 1.05*180*44
print(min_area)
print(max_area)
result = img.copy()
i = 1
for c in contours:
# print(c)
area = cv2.contourArea(c)
cv2.drawContours(result, [c], -1, (0, 255, 0), 1)
x,y,w,h = cv2.boundingRect(c)
# crop region of img using bounding box
region = result[y:y+h, x:x+w]
# save region to new image
print(region.shape,' i ',i)
# cv2.imwrite("black_region_{0}.png".format(i), region)
i = i + 1
if region.shape[0]>70 and region.shape[1]<100:
cv2.imwrite("black_region_{0}.png".format(i), region)
# break
# if area > min_area and area < max_area:
# cv2.drawContours(result, [c], -1, (0, 0, 255), 1)
# break
# save result
# cv2.imwrite("box_found.png", result)
# show images
# cv2.imshow("GRAY", gray)
# cv2.imshow("THRESH", thresh)
# cv2.imshow("RESULT", result)
# cv2.waitKey(0)
I am using the following code to crop image currently
def crop_image(image):
image = cv2.imread(image)
original_img = image.copy()
hsv_img = convert_hsv(image)
lower_blue = np.array([0, 0, 120])
upper_blue = np.array([180, 38, 255])
masked_image = mask_img(hsv_img, lower_blue, upper_blue)
result = cv2.bitwise_and(image, image, mask=masked_image)
contours = cv2.findContours(masked_image.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
cv2.drawContours(masked_image, contours, -1, (0, 255, 0), 3)
max_area_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(max_area_contour)
cv2.rectangle(result, (x, y), (x+w, y+h), (0, 255, 0), 3)
cont_filename = generate_contours_filename()
cv2.imwrite(cont_filename, np.hstack([image, result]))
logger.info('Successfuly saved file : %s' % cont_filename)
img = image[y:y+h, x:x+w]
filename = generate_filename()
cv2.imwrite(filename, img)
logger.info('Successfully saved cropped file : %s' % filename)
return img, filename
Following are theimages before and after:
This is original image
This is resulting image
I need image that crops paper part only
Thanks in advance
Here is one way to do that in Python/Opencv.
Read the input
Convert to grayscale
Threshold
Apply morphology to clean it of small regions
Get contours and filter to keep the largest one
Get the bounding box
Draw the largest contour filled on a black background as a mask
Apply the mask to blacken out the background of the paper
Use the bounding box to crop the masked input
Save the results
Input:
import cv2
import numpy as np
# read image as grayscale
img = cv2.imread('paper.jpg')
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 190, 255, cv2.THRESH_BINARY)[1]\
# apply morphology
kernel = np.ones((7,7), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
kernel = np.ones((9,9), np.uint8)
morph = cv2.morphologyEx(morph, cv2.MORPH_ERODE, kernel)
# get largest contour
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours = contours[0] if len(contours) == 2 else contours[1]
area_thresh = 0
for c in contours:
area = cv2.contourArea(c)
if area > area_thresh:
area_thresh = area
big_contour = c
# get bounding box
x,y,w,h = cv2.boundingRect(big_contour)
# draw filled contour on black background
mask = np.zeros_like(gray)
mask = cv2.merge([mask,mask,mask])
cv2.drawContours(mask, [big_contour], -1, (255,255,255), cv2.FILLED)
# apply mask to input
result1 = img.copy()
result1 = cv2.bitwise_and(result1, mask)
# crop result
result2 = result1[y:y+h, x:x+w]
# view result
cv2.imshow("threshold", thresh)
cv2.imshow("morph", morph)
cv2.imshow("mask", mask)
cv2.imshow("result1", result1)
cv2.imshow("result2", result2)
cv2.waitKey(0)
cv2.destroyAllWindows()
# save result
cv2.imwrite("paper_thresh.jpg", thresh)
cv2.imwrite("paper_morph.jpg", morph)
cv2.imwrite("paper_mask.jpg", mask)
cv2.imwrite("paper_result1.jpg", result1)
cv2.imwrite("paper_result2.jpg", result2)
Thresholded image:
Morphology cleaned image:
Mask image from largest contour:
Result of masking the input:
Result of cropping previous image:
I have contours which i want to delete from the image, What is the best way to do it ?
image = cv2.imread(path)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
retr , thresh = cv2.threshold(gray_image, 190, 255, cv2.THRESH_BINARY_INV)
contours, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
if cv2.contourArea(c) > 20:
x, y, w, h = cv2.boundingRect(c)
##### how to continue from here ?
Create an empty mask in the size of the image:
mask = np.zeros(image.shape[:2], dtype=image.dtype)
Next draw all the contours / boundingrect you want to keep on this mask:
cv2.drawContours(mask, [cnt], 0, (255), -1)
Alternatively you can instead draw the contours you don't want and inverse the mask (this may be more suitable in some situations):
mask= cv2.bitwise_not(mask)
Use the mask on the main image:
result = cv2.bitwise_and(image,image, mask= mask)
Edit: added code after comment.
I assumed this is about the image in your other question, so I applied the code to that image.
Result:
Code:
import numpy as np
import cv2
# load image
image = cv2.imread('image.png')
# create grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# perform threshold
retr , thresh = cv2.threshold(gray_image, 190, 255, cv2.THRESH_BINARY_INV)
# find contours
ret, contours, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# create emtpy mask
mask = np.zeros(image.shape[:2], dtype=image.dtype)
# draw all contours larger than 20 on the mask
for c in contours:
if cv2.contourArea(c) > 20:
x, y, w, h = cv2.boundingRect(c)
cv2.drawContours(mask, [c], 0, (255), -1)
# apply the mask to the original image
result = cv2.bitwise_and(image,image, mask= mask)
#show image
cv2.imshow("Result", result)
cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()