How can I get only the mask of an image? - python

Hi I am trying to get a mask of a T-shirt.
Here is what I am getting:
However, I would like to only receive the garment's shape without the print in the middle. How can I do that?
Thanks!
Here is the code:
import cv2
import numpy as np
# load image whose you want to create mask
img = cv2.imread('01430_00.jpg')
# convert to graky
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold input image as mask
mask = cv2.threshold(gray,220,220, cv2.THRESH_BINARY)[1]
# negate mask
mask = 255 - mask
# apply morphology to remove isolated extraneous noise
# use borderconstant of black since foreground touches the edges
kernel = np.ones((3,3), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# anti-alias the mask -- blur then stretch
# blur alpha channel
mask = cv2.GaussianBlur(mask, (0,0), sigmaX=2, sigmaY=2, borderType =
cv2.BORDER_DEFAULT)
# linear stretch so that 127.5 goes to 0, but 255 stays 255
mask = (2*(mask.astype(np.float32))-255.0).clip(0,255).astype(np.uint8)
# Show Image in Opencv Windows
cv2.imshow("Original", img)
cv2.imshow("MASK", mask)
# Save mask Image
cv2.imwrite("Mask2.jpg",mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

You already have a large contour for "garment". You can fill inside of the largest contour with the following code
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(contours, key = cv2.contourArea)
cv2.drawContours(mask,[cnt],0,255,-1)

Related

How can I remove the bright glare regions in image

I have some tomato images with bright shadow on tomatoes. I want to remove/reduce these bright shadow points. Is there any suggestion?
I tried below code but It did not solve my problem:
def decrease_brightness(img, value=30):
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
lim = 255 - value
v[v >= lim] -= value
final_hsv = cv2.merge((h, s, v))
img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
return img
image = decrease_brightness(image, value=50)
Here is how to do the inpainting in Python/OpenCV.
Note that shadows are dark. You want to remove the bright glare regions. Please use the correct terms so that you do not confuse others on the forum. Refer to a dictionary.
Read the input
Threshold on the gray background using cv2.inRange()
Apply morphology to close and dilate
Floodfill the outside with black to make a mask image
Use the mask to do the inpainting (two methods)
Save the results
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('tomato.jpg')
hh, ww = img.shape[:2]
# threshold
lower = (150,150,150)
upper = (240,240,240)
thresh = cv2.inRange(img, lower, upper)
# apply morphology close and open to make mask
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=1)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25,25))
morph = cv2.morphologyEx(morph, cv2.MORPH_DILATE, kernel, iterations=1)
# floodfill the outside with black
black = np.zeros([hh + 2, ww + 2], np.uint8)
mask = morph.copy()
mask = cv2.floodFill(mask, black, (0,0), 0, 0, 0, flags=8)[1]
# use mask with input to do inpainting
result1 = cv2.inpaint(img, mask, 101, cv2.INPAINT_TELEA)
result2 = cv2.inpaint(img, mask, 101, cv2.INPAINT_NS)
# write result to disk
cv2.imwrite("tomato_thresh.jpg", thresh)
cv2.imwrite("tomato_morph.jpg", morph)
cv2.imwrite("tomato_mask.jpg", mask)
cv2.imwrite("tomato_inpaint1.jpg", result1)
cv2.imwrite("tomato_inpaint2.jpg", result2)
# display it
cv2.imshow("IMAGE", img)
cv2.imshow("THRESH", thresh)
cv2.imshow("MORPH", morph)
cv2.imshow("MASK", mask)
cv2.imshow("RESULT1", result1)
cv2.imshow("RESULT2", result2)
cv2.waitKey(0)
Threshold Image:
Morphology and Floodfill Image:
Mask Image:
Inpaint Telea:
Inpaint Navier-Stokes:

How to remove bell curved shape from image using opencv

I hope you are doing well. I want to remove the bell-curved shape in the image. I have used OpenCV. I have implemented the following code which detects the curve shape, Now How can remove that curve shape and save the new image in the folder.
Input Image 1
I want to remove the area shown in the image below
Area i want to remove
import cv2
import numpy as np
# load image as grayscale
cell1 = cv2.imread("/content/savedImage.jpg",0)
# threshold image
ret,thresh_binary = cv2.threshold(cell1,107,255,cv2.THRESH_BINARY)
# findcontours
contours, hierarchy = cv2.findContours(image =thresh_binary , mode = cv2.RETR_TREE,method = cv2.CHAIN_APPROX_SIMPLE)
# create an empty mask
mask = np.zeros(cell1.shape[:2],dtype=np.uint8)
# loop through the contours
for i,cnt in enumerate(contours):
# if the contour has no other contours inside of it
if hierarchy[0][i][2] == -1 :
# if the size of the contour is greater than a threshold
if cv2.contourArea(cnt) > 10000:
cv2.drawContours(mask,[cnt], 0, (255), -1)
fig, ax = plt.subplots(1,2)
ax[0].imshow(cell1,'gray');
ax[1].imshow(mask,'gray');
Ouput Image after the above Code
How can I process to remove that curve shape?
Here is one way to do that in Python/OpenCV.
Get the external contours. Then find the one that has the largest w/h aspect ratio. Draw that contour filled on a black background as a mask. Dilate it a little. Then invert it and use it to blacken out that region.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('the_image.jpg')
ht, wd = img.shape[:2]
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# get external contours
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
max_aspect=0
for cntr in contours:
x,y,w,h = cv2.boundingRect(cntr)
aspect = w/h
if aspect > max_aspect:
max_aspect = aspect
max_contour = cntr
# create mask from max_contour
mask = np.zeros((ht,wd), dtype=np.uint8)
mask = cv2.drawContours(mask, [max_contour], 0, (255), -1)
# dilate mask
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, kernel)
# invert mask
mask = 255 - mask
# mask out region in input
result = img.copy()
result = cv2.bitwise_and(result, result, mask=mask)
# save resulting image
cv2.imwrite('the_image_masked.png',result)
# show thresh and result
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result:

Identify and count objects different from background

I try to use python, NumPy, and OpenCV to analyze the image below and just draw a circle on each object found. The idea here is not to identify the bug only identify any object that is different from the background.
Original Image:
Here is the code that I'm using.
import cv2
import numpy as np
img = cv2.imread('per.jpeg', cv2.IMREAD_GRAYSCALE)
if cv2.__version__.startswith('2.'):
detector = cv2.SimpleBlobDetector()
else:
detector = cv2.SimpleBlobDetector_create()
keypoints = detector.detect(img)
print(len(keypoints))
imgKeyPoints = cv2.drawKeypoints(img, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
status = cv2.imwrite('teste.jpeg',imgKeyPoints)
print("Image written to file-system : ",status)
But the problem is that I'm getting only a greyscale image as result without any counting or red circle, as shown below:
Since I'm new to OpenCV and object recognition world I'm not able to identify what is wrong, and any help will be very appreciated.
Here is one way in Python/OpenCV.
Threshold on the bugs color in HSV colorspace. Then use morphology to clean up the threshold. Then get contours. Then find the minimum enclosing circle around each contour. Then bias the radius to make a bit larger and draw the circle around each bug.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('bugs.jpg')
# convert image to hsv colorspace
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# threshold on bugs color
lower=(0,90,10)
upper=(100,250,170)
thresh = cv2.inRange(hsv, lower, upper)
# apply morphology to clean up
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (6,6))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
# get external contours
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
result = img.copy()
bias = 10
for cntr in contours:
center, radius = cv2.minEnclosingCircle(cntr)
cx = int(round(center[0]))
cy = int(round(center[1]))
rr = int(round(radius)) + bias
cv2.circle(result, (cx,cy), rr, (0, 0, 255), 2)
# save results
cv2.imwrite('bugs_threshold.jpg', thresh)
cv2.imwrite('bugs_cleaned.jpg', morph)
cv2.imwrite('bugs_circled.jpg', result)
# display results
cv2.imshow('thresh', thresh)
cv2.imshow('morph', morph)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold Image:
Morphology Cleaned Image:
Resulting Circles:

reduce shape of image by removing whiteness arround

from pdf2image import convert_from_path
import cv2,numpy,os
def pil_to_cv2(image):
open_cv_image = numpy.array(image)
return open_cv_image[:, :, ::-1].copy()
images = convert_from_path('test.pdf')
cv_h=[pil_to_cv2(i) for i in images]
for img in cv_h:
#function_to_crop()
cv2.imwrite('modified.png', img)
How can I remove the extra whiteness from the image (top,sideways,under) without actually intercepting the drawing, The drawings from pdf are from different sizes so I can't crop the images by a fixed number.
Ideally,the output would look like this
Here is another way to do that in Python/OpenCV.
Read the image
Convert to gray and invert the polarity
Threshold
Apply morphology close to fill in holes and make one solid region
Get the outer contour and its bounding box
Use the bounding box to crop the image using Numpy slicing
Save the result
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('multipower.png')
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# invert gray image
gray = 255 - gray
# threshold
thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]
# apply close and open morphology
kernel = np.ones((75,75), np.uint8)
mask = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# get contours (presumably just one around the nonzero pixels)
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
cntr = contours[0]
x,y,w,h = cv2.boundingRect(cntr)
# draw contour on input
contour_img = img.copy()
cv2.drawContours(contour_img,[cntr],0,(0,0,255),3)
# crop to bounding rectangle
crop = img[y:y+h, x:x+w]
# save cropped image
cv2.imwrite('multipower_thresh.png',thresh)
cv2.imwrite('multipower_mask.png',mask)
cv2.imwrite('multipower_contour.png',contour_img)
cv2.imwrite('multipower_cropped.png',crop)
# show the images
cv2.imshow("THRESH", thresh)
cv2.imshow("MASK", mask)
cv2.imshow("CONTOUR", contour_img)
cv2.imshow("CROP", crop)
cv2.waitKey(0)
cv2.destroyAllWindows()
Thresholded Image:
Morphology closed image:
Contour image:
Result:
import cv2 as cv
import numpy as np
frame = cv.imread('7dcoI.png')
frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
mask=cv.threshold(frame_gray, 85, 255, cv.THRESH_BINARY )[1]
rows, cols = mask.shape
non_empty_columns = np.where(mask.min(axis=0)==0)[0]
non_empty_rows = np.where(mask.min(axis=1)==0)[0]
cropBox = (min(non_empty_rows), min(max(non_empty_rows), rows), min(non_empty_columns), min(max(non_empty_columns), cols))
cropped = frame[cropBox[0]:cropBox[1]+1, cropBox[2]:cropBox[3]+1 , :]
cv.imwrite('out_mask.png', cropped)

Python OpenCV: Crop image to contents, and make background transparent

I have the following image:
I want to crop the image to the actual contents, and then make the background (the white space behind) transparent. I have seen the following question: How to crop image based on contents (Python & OpenCV)?, and after looking at the answer, and trying it, I got the following code:
img = cv.imread("tmp/"+img+".png")
mask = np.zeros(img.shape[:2],np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (55,55,110,110)
cv.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv.GC_INIT_WITH_RECT)
mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]
plt.imshow(img),plt.colorbar(),plt.show()
But when I try this code, I get the following result:
Which isn't really the result I'm searching for, expected result:
Here is one way to do that in Python/OpenCV.
As I mentioned in my comment, your provided image has a white circle around the cow and then a transparent background. I have made the background fully white as my input.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('cow.png')
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# invert gray image
gray = 255 - gray
# threshold
thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]
# apply close and open morphology to fill tiny black and white holes and save as mask
kernel = np.ones((3,3), np.uint8)
mask = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
# get contours (presumably just one around the nonzero pixels)
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
cntr = contours[0]
x,y,w,h = cv2.boundingRect(cntr)
# make background transparent by placing the mask into the alpha channel
new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
new_img[:, :, 3] = mask
# then crop it to bounding rectangle
crop = new_img[y:y+h, x:x+w]
# save cropped image
cv2.imwrite('cow_thresh.png',thresh)
cv2.imwrite('cow_mask.png',mask)
cv2.imwrite('cow_transparent_cropped.png',crop)
# show the images
cv2.imshow("THRESH", thresh)
cv2.imshow("MASK", mask)
cv2.imshow("CROP", crop)
cv2.waitKey(0)
cv2.destroyAllWindows()
Thresholded image:
Mask:
Cropped result with transparent background:
Given that the background to be converted to transparent has its BGR channels white (like in your image), you can do:
import cv2
import numpy as np
img = cv2.imread("cat.png")
img[np.where(np.all(img == 255, -1))] = 0
img_transparent = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
img_transparent[np.where(np.all(img == 0, -1))] = 0
cv2.imshow("transparent.png", img_transparent)
Input image:
Output image:
We can tell the second image is transparent by clicking on it; the transparent background will show up a grey (in Firefox, at least).
What worked to me is:
original_image = cv2.imread(path)
#Converting the bgr image to an image with the alpha channel
original_image = cv2.cvtColor(original_image, cv2.BGR2BGRA)
#Transforming every alpha pixel to a transparent pixel.
original_image[np.where(np.all(original_image == 255, -1))] = 0
And then writing the image.

Categories

Resources