In the image I would like to have only the lungs in black not the background. The background [Top black and bottom black area of the image] must be white not black. How can I do that in python?. Code that resuls in the image above from an original grayscale image ("image") is:
from skimage.filters import sobel
img = cv2.GaussianBlur(image, (5, 5), 0)
img = cv2.erode(img, None, iterations=2)
img = cv2.dilate(img, None, iterations=2)
elevation_map = sobel(img)
markers = np.zeros_like(image)
markers[image < 70] = 1
markers[image > 254] = 2
segmentation = skimage.morphology.watershed(elevation_map, markers)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('segmentation')
Assuming we have the segmentation image as posted above, and we want to fill the surrounding background with while.
One option is iterating the borders, and apply floodFill where pixel is black:
import cv2
import numpy as np
gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
for x in range(gray.shape[1]):
# Fill dark top pixels:
if gray[0, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, 0), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark bottom pixels:
if gray[-1, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, gray.shape[0]-1), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
for y in range(gray.shape[0]):
# Fill dark left side pixels:
if gray[y, 0] == 0:
cv2.floodFill(gray, None, seedPoint=(0, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark right side pixels:
if gray[y, -1] == 0:
cv2.floodFill(gray, None, seedPoint=(gray.shape[1]-1, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
cv2.imshow('gray', gray)
cv2.waitKey()
cv2.destroyAllWindows()
Other option is use something as MATLAB imfill(BW,'holes').
Fill the center black with white.
In the original image, fill with while where both original and filled image are black:
import cv2
import numpy as np
from skimage.morphology import reconstruction
def imfill(img):
# https://stackoverflow.com/questions/36294025/python-equivalent-to-matlab-funciton-imfill-for-grayscale
# Use the matlab reference Soille, P., Morphological Image Analysis: Principles and Applications, Springer-Verlag, 1999, pp. 208-209.
# 6.3.7 Fillhole
# The holes of a binary image correspond to the set of its regional minima which
# are not connected to the image border. This definition holds for grey scale
# images. Hence, filling the holes of a grey scale image comes down to remove
# all minima which are not connected to the image border, or, equivalently,
# impose the set of minima which are connected to the image border. The
# marker image 1m used in the morphological reconstruction by erosion is set
# to the maximum image value except along its border where the values of the
# original image are kept:
seed = np.ones_like(img)*255
img[ : ,0] = 0
img[ : ,-1] = 0
img[ 0 ,:] = 0
img[ -1 ,:] = 0
seed[ : ,0] = 0
seed[ : ,-1] = 0
seed[ 0 ,:] = 0
seed[ -1 ,:] = 0
fill_img = reconstruction(seed, img, method='erosion')
return fill_img
gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
fill_gray = imfill(gray)
# Fill with white where both gray and fill_gray are zeros
gray[(gray == 0) & (fill_gray == 0)] = 255;
cv2.imshow('gray', gray)
cv2.imshow('fill_gray', fill_gray)
cv2.waitKey()
cv2.destroyAllWindows()
I also thought of solving it using findContours with hierarchy, but it's a bit more coding.
Output:
For removing the black spot in the center (if needed), we may use connectedComponentsWithStats, and fill the small "spot" according to the area.
Edit:
Example for incorporating the above solution with your code:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import skimage.io
import skimage.color
import skimage.filters
from skimage.io import imread
from skimage.color import rgb2gray
from skimage.filters import sobel
import cv2
from skimage import data
image = cv2.imread('/content/drive/MyDrive/Covid_data/Training Set/covid/covid/ct_scan_100/22.jpg')
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('Original Image')
# Image in grayscale
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Blurring the image [img]
img = cv2.GaussianBlur(image, (5, 5), 0)
img = cv2.erode(img, None, iterations=2)
img = cv2.dilate(img, None, iterations=2)
#img = image
elevation_map = sobel(img)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(elevation_map, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('elevation_map')
# we find markers of the background and the coins based on the extreme parts of the histogram of grey values
markers = np.zeros_like(image)
# Choosing extreme parts of the histogram of grey values
markers[image < 70] = 1
markers[image > 254] = 2
#we use the watershed transform to fill regions of the elevation map starting from the markers determined above:
segmentation = skimage.morphology.watershed(elevation_map, markers)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('segmentation')
#gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
# Convert segmentation to uint8 image, where 255 is white and 0 is black (OpenCV style mask).
ret, gray = ret, gray = cv2.threshold(segmentation.astype(np.uint8), 1, 255, cv2.THRESH_BINARY)
for x in range(gray.shape[1]):
# Fill dark top pixels:
if gray[0, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, 0), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark bottom pixels:
if gray[-1, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, gray.shape[0]-1), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
for y in range(gray.shape[0]):
# Fill dark left side pixels:
if gray[y, 0] == 0:
cv2.floodFill(gray, None, seedPoint=(0, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark right side pixels:
if gray[y, -1] == 0:
cv2.floodFill(gray, None, seedPoint=(gray.shape[1]-1, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(gray, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('gray')
Using: ret, gray = cv2.threshold(segmentation.astype(np.uint8), 1, 255, cv2.THRESH_BINARY)
Replaces all the white pixels in segmentation with 255 and all the black pixels with 0.
Related
I want to extract each sticker 5x6 and to total 30 sticker
like below , how do I do so
(expect pic ) https://imgur.com/a/C5CiSxM
(original picture) https://imgur.com/a/V0lvqU3
from below link I come up my code
How extract pictures from an big image in python
following the suggestion:
The black pixels along the top are a distraction, so are the black
pixels of the QR codes. You are only interested in the white stickers.
So, take a copy of your image and threshold at a high value to give
you pure white stickers surrounded by black and with black QR codes
within each sticker. Now find white contours and reject black ones.
Apply the contours found on the thresholded image to your original
image.
I'm doing the Thresholding expecting pure white stickers surrounded by black and with black QR codes within each sticker
import numpy as np
import glob
import matplotlib.pyplot as plt
import skimage.io
import skimage.color
import skimage.filters
from PIL import Image
import pytesseract
import cv2 as cv
import numpy as np
def custom_blur_demo(image):
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) #锐化
dst = cv.filter2D(image, -1, kernel=kernel)
cv.imwrite("/home/joy/桌面/test_11_4/sharpen_images.png", dst)
cv.imshow("custom_blur_demo", dst)
src = cv.imread("/home/joy/桌面/test_11_4/original.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
custom_blur_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
# load the image
image = skimage.io.imread("/home/joy/桌面/test_11_4/sharpen_images.png")[:,:,:3]
# image = imageio.imread(image_name)[:,:,:3]
# img = rgb2gray(image)
fig, ax = plt.subplots()
plt.imshow(image)
# convert the image to grayscale
gray_image = skimage.color.rgb2gray(image)
# blur the image to denoise
blurred_image = skimage.filters.gaussian(gray_image, sigma=1.0)
fig, ax = plt.subplots()
plt.imshow(blurred_image, cmap="gray")
# create a histogram of the blurred grayscale image
histogram, bin_edges = np.histogram(blurred_image, bins=256, range=(0.0, 1.0))
fig, ax = plt.subplots()
plt.plot(bin_edges[0:-1], histogram)
plt.title("Grayscale Histogram")
plt.xlabel("grayscale value")
plt.ylabel("pixels")
plt.xlim(0, 1.0)
# create a mask based on the threshold
t1 = 0.72
t2 = 0.05
binary_mask = blurred_image < t1
fig, ax = plt.subplots()
plt.imshow(binary_mask, cmap="gray")
aaa = plt.imshow(binary_mask, cmap="gray")
plt.show()
plt.savefig("/home/joy/桌面/test_11_4/sharpen_images_del_gray_part.png", aaa)
img = Image.open('/home/joy/桌面/test_11_4/sharpen_images_del_gray_part.png')
text = pytesseract.image_to_string(img, lang='eng')
print("file name" ,"final output", ".png")
print("size")
print(img.size)
print(text)
here is the output for mine Thresholding : https://imgur.com/a/V0lvqU3
the product does after Thresholding but the word on every sticker seems blur (I'm going to OCR image to text every single sticker img later)
not correct yet, I want sticker part only that without gray color part
(pic 5b) in same link is how I reach for now
https://imgur.com/a/V0lvqU3
How to cut them in small piece, the sticker size
(expect pic ) https://imgur.com/a/C5CiSxM
The black pixels along the top are a distraction, so are the black pixels of the QR codes. You are only interested in the white stickers.
So, take a copy of your image and threshold at a high value to give you pure white stickers surrounded by black and with black QR codes within each sticker. Now find white contours and reject black ones.
Apply the contours found on the thresholded image to your original image.
This effort is probably not scientifically generalizable.
Just wanted to show it doesn't need Contour-finding/Binarization. just pixel value comparison might be enough.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
orig_image = cv.imread("sample.png")
gray = cv.cvtColor(orig_image, cv.COLOR_BGR2GRAY)
kernel = np.ones((3,3),np.uint8)
eroded = cv.erode(gray,kernel,iterations = 1)
def show_img(img_bgr):
fig, ax = plt.subplots(figsize=(5, 5))
rgb = cv.cvtColor(img_bgr, cv.COLOR_BGR2RGB)
ax.imshow(rgb)
return fig
def detect_top_bottom(original_img, erodded_img):
"""Detects only top and bottom row number of each row of Qr_Codes.
"""
line_img = original_img.copy()
height, width = erodded_img.shape
top = 0
top_drawn = False
rows_range = []
for row in range(erodded_img.shape[0]):
for col in range(erodded_img.shape[1]):
if np.mean(erodded_img[row,col]) > 190:
if row - top > 3 and not top_drawn:
cv.line(line_img, (0, row), (width, row), (0,255,0), 2)
rows_range.append([row,None])
top_drawn = True
top = row
break
else:
if top_drawn:
cv.line(line_img, (0, row), (width, row), (0,255,0), 2)
rows_range[-1][1] = row
top_drawn = False
return line_img, rows_range
# make original image grayscale
gray = cv.cvtColor(orig_image, cv.COLOR_BGR2GRAY)
# erode image with 3x3 kernel in order to remove small noises
kernel = np.ones((3,3),np.uint8)
eroded = cv.erode(gray,kernel,iterations = 1)
line_img, rows_range = detect_top_bottom(orig_image, eroded)
# Rotate image 90 degs clockwise in order to use same function for detection
eroded_rotated_90 = cv.rotate(eroded, cv.ROTATE_90_CLOCKWISE)
line_img_rotated_90 = cv.rotate(line_img, cv.ROTATE_90_CLOCKWISE)
line_img, cols_range = detect_top_bottom(line_img_rotated_90, eroded_rotated_90)
# finally rotate 90 deg counter clockwise in to get orignal.
line_img= cv.rotate(line_img, cv.ROTATE_90_COUNTERCLOCKWISE)
fig = show_img(line_img)
fig.savefig("original_grid.png")
fig, axs = plt.subplots(len(rows_range), len(cols_range))
for i, row in enumerate(rows_range):
for j, col in enumerate(cols_range):
axs[i,j].axis('off')
# just for sake of visualization conver to RGB
# axs[i,j].imshow(orig_image[row[0]:row[1], :][:,col[0]:col[1]]) probabely is enough
orig_sub_channels = cv.cvtColor(orig_image[row[0]:row[1], :][:,col[0]:col[1]], cv.COLOR_BGR2RGB)
axs[i,j].imshow(orig_sub_channels)
fig.savefig("splitted_grid.png")
I want to remove the text on the edged in the image
I have used the following code but it does not work it also remove the text in the center
Input:
Output:
import cv2
import matplotlib.pyplot as plt
import glob
import os
import numpy as np
def crop_buttom_text(img):
""" Remove the text from the bottom edge of img """
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#blur = cv2.GaussianBlur(gray, (9,9), 0) # No need for blurring
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Create rectangular structuring element and dilate
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 1)) # Use horizontal line as kernel - dilate horizontally.
dilate = cv2.dilate(thresh, kernel, iterations=1)
#kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,10))
#dilate = cv2.morphologyEx(dilate, cv2.MORPH_OPEN, kernel) # No need for opening
# Find contours and draw rectangle
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] # [-2] indexing takes return value before last (due to OpenCV compatibility issues).
#cnts = cnts[0] if len(cnts) == 2 else cnts[1] # [-2] is shorter....
res_img = img.copy() # Copy img to res_img - in case there is no edges text.
for c in cnts:
x, y, w, h = cv2.boundingRect(c)
y2 = y + h # Bottom y coordinate of the bounding rectangle
if (y2 >= img.shape[0]):
# If the rectangle touches the bottom of the img
res_img = res_img[0:y-1, :].copy() # Crop rows from first row to row y-1
return res_img
def remove_lines(image_path,outdir):
image = cv2.imread(image_path)
img1 = crop_buttom_text(image)
img2 = crop_buttom_text(np.rot90(img1)) # Rotate by 90 degrees and crop.
img3 = crop_buttom_text(np.rot90(img2)) # Rotate by 90 degrees and crop.
img4 = crop_buttom_text(np.rot90(img3)) # Rotate by 90 degrees and crop.
output_img = np.rot90(img4)
cv2.imwrite(os.path.join(outdir,os.path.basename(image_path)), output_img)
for jpgfile in glob.glob(r'/content/Dataset/*'):
print(jpgfile)
remove_lines(jpgfile,r'/content/output')
How can i modify the above code to remove the text around the edge
How do you remove the text which is at the edge? Here is a rough way to attack the problem: remove every connected component which touches the border.
To solve this, you can add a 1 pixel border, extract the connected components and then use the one corresponding to the border as a binary mask.
The mask becomes
The result is
Notice how a 7 and few commas get removed as well.
from cv2 import cv2
import numpy as np
# Load original image
img = cv2.imread('kShDc.jpg', cv2.IMREAD_GRAYSCALE)
# Save original dimensions
h, w = img.shape[:2]
# Ensure only bilevel image with white as foreground
_, bimg = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
# Add one pixel border
bimg = cv2.copyMakeBorder(bimg, 1, 1, 1, 1, cv2.BORDER_CONSTANT, None, 255)
# Extract connected components (Spaghetti is the fastest algorithm)
nlabels, label_image = cv2.connectedComponentsWithAlgorithm(bimg, 8, cv2.CV_32S, cv2.CCL_SPAGHETTI)
# Make a mask with the edge label (0 is background, 1 is the first encountered label, i.e. the border)
ccedge = np.uint8((label_image != 1)*255)
cv2.imwrite("mask.png", ccedge, [cv2.IMWRITE_PNG_BILEVEL, 1])
# Zero every pixel touching the border
bimg = cv2.bitwise_and(bimg, ccedge)
# Remove border and invert again
bimg = 255 - bimg[1:h+1, 1:w+1]
# Save result
cv2.imwrite("result.png", bimg, [cv2.IMWRITE_PNG_BILEVEL, 1])
I have plotted a rectangle using matplotlib and would like to place an image in it as shown in the image below. Does anyone have an idea how I can achieve this in python?
Here is one way using Python/OpenCV/Numpy. Do a perspective warp of the panda image using its 4 corners and the 4 corners of the rectangle. Then make a mask of the excess regions, which are black in the warped image. Finally, blend the warped image and background image using the mask.
Input:
Graph Image:
import numpy as np
import cv2
import math
# read image to be processed
img = cv2.imread("panda.png")
hh, ww = img.shape[:2]
# read background image
bck = cv2.imread("rectangle_graph.png")
hhh, www = bck.shape[:2]
# specify coordinates for corners of img in order TL, TR, BR, BL as x,y pairs
img_pts = np.float32([[0,0], [ww-1,0], [ww-1,hh-1], [0,hh-1]])
# manually pick coordinates of corners of rectangle in background image
bck_pts = np.float32([[221,245], [333,26], [503,111], [390,331]])
# compute perspective matrix
matrix = cv2.getPerspectiveTransform(img_pts,bck_pts)
#print(matrix)
# change black and near-black to graylevel 1 in each channel so that no values
# inside panda image will be black in the subsequent mask
img[np.where((img<=[5,5,5]).all(axis=2))] = [1,1,1]
# do perspective transformation setting area outside input to black
img_warped = cv2.warpPerspective(img, matrix, (www,hhh), cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0,0,0))
# make mask for area outside the warped region
# (black in image stays black and rest becomes white)
mask = cv2.cvtColor(img_warped, cv2.COLOR_BGR2GRAY)
mask = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY)[1]
mask = cv2.merge([mask,mask,mask])
mask_inv = 255 - mask
# use mask to blend between img_warped and bck
result = ( 255 * (bck * mask_inv + img_warped * mask) ).clip(0, 255).astype(np.uint8)
# save images
cv2.imwrite("panda_warped.png", img_warped)
cv2.imwrite("panda_warped_mask.png", mask)
cv2.imwrite("panda_in_graph.png", result)
# show the result
cv2.imshow("warped", img_warped)
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Warped Input:
Mask:
Result:
You can use imshow to place the image at a given position. And add a transform to give the image the same rotation as the rectangle.
To steer away from possible copyright issues, the following code uses an image from wikipedia (author: Fernando Revilla):
import matplotlib.pyplot as plt
from matplotlib import transforms
from matplotlib.patches import Rectangle
file = 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Giant_Panda_Tai_Shan.JPG/1200px-Giant_Panda_Tai_Shan.JPG'
img = plt.imread(file, format='jpg')
fig, ax = plt.subplots()
# suppose a rectangle was drawn onto the plot
x, y = 20, 30
width, height = 12, 9
angle = 70
rect = Rectangle((x, y), width, height, angle=angle, ec='black', fc='none', lw=3)
ax.add_patch(rect)
# draw the image using the rectangles position and rotation
tr = transforms.Affine2D().translate(-x, -y).rotate_deg(angle).translate(x, y)
ax.imshow(img, extent=[x, x + width, y, y + height], transform=tr + ax.transData)
ax.set_aspect('equal') # keep right angles
ax.relim()
ax.autoscale()
plt.show()
Here's my code:
def region_of_interest(image):
height = image.shape[0]
polygons = np.array([
[(300, height), (1100, height), (600, 400)] #Dimensions of Polygon
])
mask = np.zeros_like(image)
cv2.fillPoly(mask, polygons, 255)
masked_image = cv2.bitwise_and(image, mask)
return masked_image
I want to shade the area between the polygon, and I've tried changing the RGB color in the cv2.fillPoly line, but that hasn't worked.
I would prefer for the color to be transparent, but a solid gradient is fine too.
here is a working code , if the alpha value is one, there would be no transparency if the value is 0 it will be totally black.
import cv2
import numpy as np
img = cv2.imread("1.jpeg")
height = img.shape[0]
alpha = 0.7
line1 = ((50,50),(50,200))
img = cv2.line(img,line1[0],line1[1],(0,255,0),2)
line2 = ((100,50),(100,200))
img = cv2.line(img,line2[0],line2[1],(0,255,0),2)
# cv2.rectangle(img,(10,1),(50,100),(0,0,255),3)
# img[1:100, 10:50] = img[1:100, 10:50]*0.5
img[line1[0][1]:line2[1][1], line1[1][0]:line2[1][0]] = img[line1[0][1]:line2[1][1],
line1[1][0]:line2[1][0]]*alpha
# img = cv2.fillPoly(img, polygons, 255)
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
you can change it to make it white instead of black if the alpha is 0 and dark if alpha is 1 by subtracting the pixels by 255 like this
img[line1[0][1]:line2[1][1], line1[1][0]:line2[1][0]] = 255-(img[line1[0]
[1]:line2[1][1], line1[1][0]:line2[1][0]]*alpha)
I'm trying to select the green color in an image using OpenCV (the method to do it comes from this website. The image I'm treating is :
Here is the code I tried to write.
import cv2
import matplotlib.pyplot as plt
import numpy as np
greenhsv = (60, 255, 255)
green2hsv=(70,100,170)
g_square = np.full((10, 10, 3), greenhsv, dtype=np.uint8)/255.0
plt.imshow(hsv_to_rgb(g_square))
plt.show()
g1_square = np.full((10, 10, 3), green2hsv, dtype=np.uint8)/255.0
plt.imshow(hsv_to_rgb(g1_square))
plt.show()
nucl = cv2.imread('./Pictures/image_nucleation_essai0.png')
nucl = cv2.cvtColor(nucl, cv2.COLOR_BGR2RGB)
plt.imshow(nucl)
plt.show()
hsv_nucl = cv2.cvtColor(nucl, cv2.COLOR_RGB2HSV)
mask = cv2.inRange(hsv_nucl, greenhsv,green2hsv)
result = cv2.bitwise_and(nucl, nucl, mask=mask)
plt.imshow(mask, cmap="gray")
plt.show()
plt.imshow(result)
plt.show()
The result is :
So the mask did not work.
Your color ranges are not quite right yet. Also the variables in the inRange() function are in the wrong order. It's from-to, so the darker color must be first. Change your code to cv2.inRange(hsv_nucl, green2hsv,greenhsv) You can use/tweak the values in the code below, that works.
Result:
With white background:
import numpy as np
import cv2
# load image
img = cv2.imread("Eding.png")
# convert to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# set lower and upper color limits
lower_val = np.array([50,100,170])
upper_val = np.array([70,255,255])
# Threshold the HSV image to get only green colors
mask = cv2.inRange(hsv, lower_val, upper_val)
# apply mask to original image - this shows the green with black blackground
only_green = cv2.bitwise_and(img,img, mask= mask)
# create a black image with the dimensions of the input image
background = np.zeros(img.shape, img.dtype)
# invert to create a white image
background = cv2.bitwise_not(background)
# invert the mask that blocks everything except green -
# so now it only blocks the green area's
mask_inv = cv2.bitwise_not(mask)
# apply the inverted mask to the white image,
# so it now has black where the original image had green
masked_bg = cv2.bitwise_and(background,background, mask= mask_inv)
# add the 2 images together. It adds all the pixel values,
# so the result is white background and the the green from the first image
final = cv2.add(only_green, masked_bg)
#show image
cv2.imshow("img", final)
cv2.waitKey(0)
cv2.destroyAllWindows()