Slicing image with findContours(cv2) - python

I cant post the image because of the reputation thing so here is the link to the image I downloaded:
https://www.amvplaygrounds.co.uk/pub/media/catalog/product/a/m/amv_f4-pm-017-shapes-circle-square-rectangle-star-triangle-200mm-2-sq-3d.jpg
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = cv2.imread(r'C:\Users\User\Desktop\shapes.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 200, 255, 0)
contours, hier = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
shape = thresh[y:y+h,x:x+w]
plt.imshow(shape)
It only returns one contour instead of 6 as you can see in the picture.
What am I doing wrong ?

findContours() looks for white objects on a black background, so you need to threshold like this:
ret, thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)
and you need to find the contours like this:
im2, contours, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Related

OpenCV - How to identify multiple unknown images inside a larger image?

Template matching doesn't work here I don't think because the smaller images are unknown, so I was thinking using contour detection, but it seems to be picking up too much noise and not the exact contour of the images. This is my code so far:
img = cv2.imread('input.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY)
img2, contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours, hierarchy = cv2.findContours(image=thresh, mode=cv2.RETR_TREE,
method=cv2.CHAIN_APPROX_NONE)
image_copy = img.copy()
cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
cv2.imwrite("output.jpg", image_copy)
This is the input image:
This is what Im currently getting:
This would be the ideal output:

How to find contours in dotted text captcha image

I am newbie to OpenCV. I'm trying to find the contours of the captcha image. It does not work only when my captcha image contains the dotted text.
I have done following code for that:
import numpy as np
import cv2 as cv
import imgaug.augmenters as iaa
im = cv.imread('dataset/1.jpg')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
imgray = cv.threshold(imgray, 127, 255, 0)[1]
dst = cv.Canny(imgray,0,150)
blured = cv.blur(dst,(5,5),0)
img_thresh = cv.adaptiveThreshold(blured,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 11, 2)
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3,3))
threshed = cv.morphologyEx(img_thresh,cv.MORPH_CLOSE,kernel)
contours, hierarchy = cv.findContours(dst, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
print(len(contours))
# cv.drawContours(im, contours, -1, (0, 255, 0), 3)
cv.imshow("img_thresh",img_thresh)
cv.imshow("dst",dst)
cv.imshow("threshed",threshed)
cv.waitKey(0)
cv.destroyAllWindows()
Can anyone help in this? Is there any way to find contours in this image?
Here is my code and output
'''
contours
'''
import numpy as np
import cv2
#read image as gray
pic = r'C:\Users\balaji\Desktop\captcha.jpg'
img_color = cv2.imread(pic)
cv2.imshow('CAPTCHA preview',img_color)
cv2.waitKey(0)
img_gray = cv2.cvtColor(img_color,cv2.COLOR_BGR2GRAY)
#Apply thresholding to the image
ret, thresh = cv2.threshold(img_gray, 127, 255, cv2.THRESH_OTSU)
cv2.imshow('Thresholded image', thresh)
cv2.waitKey(0)
#Dilated image - to connect the dots
krn = np.ones((3,3), np.uint8)
img_dilated = cv2.dilate(cv2.bitwise_not(thresh), kernel=krn, iterations=1)
cv2.imshow('Dilated image', img_dilated)
cv2.waitKey(0)
# Finding and draw Contours
contours, hierarchy = cv2.findContours(img_dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
black_canvas = np.zeros_like(img_color)
cv2.drawContours(black_canvas, contours, -1, (0, 255, 0), 1)
cv2.imshow('Contoured image', black_canvas)
cv2.waitKey(0)

How to extract ID document region of interest from image with OpenCV?

I am trying to segment this image because I need only to obtain the document.
Applying some filters I got this result:
I am trying to get the outline of the white rectangle but I get this result:
Anyone have any idea how to do better?
this is my code :/
import cv2
image = cv2.imread('roberto.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
_, binary = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('test', binary)
cv2.waitKey(0)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2:]
idx = 0
for cnt in contours:
idx += 1
x,y,w,h = cv2.boundingRect(cnt)
roi=binary[y:y+h,x:x+w]
cv2.rectangle(image,(x,y),(x+w,y+h),(200,0,0),2)
cv2.imshow('img',image)
cv2.waitKey(0)
You're almost there, you just need to obtain the x,y,w,h bounding rectangle coordinates using cv2.boundingRect then you can extract/save the ROI using Numpy slicing. Here's the result
import cv2
# Load image, grayscale, threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)[1]
# Get bounding box and extract ROI
x,y,w,h = cv2.boundingRect(thresh)
ROI = image[y:y+h, x:x+w]
cv2.imshow('thresh', thresh)
cv2.imshow('ROI', ROI)
cv2.waitKey()

How to blur/ feather the edges of an object in an image using Opencv?

The objective is to blur the edges of a selected object in an image.
I've done the steps to obtain the contours of the object by using the following code:
image = cv2.imread('path of image')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)[1]
im, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
I am also able to plot the contour using:
cv2.drawContours(image, contours, -1, (0, 255, 0), 2)
Now I want to make use of the points stored in contours to blur / feather the edge of the object, perhaps using gaussian blur. How am I able to achieve that?
Thanks so much!
Similar to what I have mentioned here, you can do it in the following steps:
Load original image and find contours.
Blur the original image and save it in a different variable.
Create an empty mask and draw the detected contours on it.
Use np.where() method to select the pixels from the mask (contours) where you want blurred values and then replace it.
import cv2
import numpy as np
image = cv2.imread('./asdf.jpg')
blurred_img = cv2.GaussianBlur(image, (21, 21), 0)
mask = np.zeros(image.shape, np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)[2]
contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(mask, contours, -1, (255,255,255),5)
output = np.where(mask==np.array([255, 255, 255]), blurred_img, image)

removing largest contour from an image

I have an image such as this
I am trying to detect and remove the arrow from this image so that I end up with an image that just has the text.
I tried the below approach but it isn't working
image_src = cv2.imread("roi.png")
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY)
canny=cv2.Canny(gray,50,200,3)
ret, gray = cv2.threshold(canny, 10, 255, 0)
contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
largest_area = sorted(contours, key=cv2.contourArea)[-1]
mask = np.ones(image_src.shape[:2], dtype="uint8") * 255
cv2.drawContours(mask, [largest_area], -1, 0, -1)
image = cv2.bitwise_and(image_src, image_src, mask=mask)
The above code seems to give me back the same image WITH the arrow.
How can I remove the arrow?
The following will remove the largest contour:
import numpy as np
import cv2
image_src = cv2.imread("roi.png")
gray = cv2.cvtColor(image_src, cv2.COLOR_BGR2GRAY)
ret, gray = cv2.threshold(gray, 250, 255,0)
image, contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
mask = np.zeros(image_src.shape, np.uint8)
largest_areas = sorted(contours, key=cv2.contourArea)
cv2.drawContours(mask, [largest_areas[-2]], 0, (255,255,255,255), -1)
removed = cv2.add(image_src, mask)
cv2.imwrite("removed.png", removed)
Note, the largest contour in this case will be the whole image, so it is actually the second largest contour.

Categories

Resources