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:
Related
I'm working in a script using different OpenCV operations for processing an image with solar panels.
Original image:
Final image:
Can anybody help me with the code to detect only the grid lines in the image, removing the other area.
My code is the following:
image = cv2.imread("solar3.jpg")
cv2.imshow("Image", image)
image = cv2.resize(image, (482,406))
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
blur = cv2.GaussianBlur(gray, (0,0), 2)
cv2.imshow("blur", blur)
lap = cv2.Laplacian(blur, cv2.CV_32F)
cv2.imshow("lap",lap)
_,thresh = cv2.threshold(lap, 0, 0, cv2.THRESH_TOZERO)
cv2.imshow("thresh", thresh)
thresh = thresh.astype(np.uint8)
contours, hierachy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
c = 0
for i in contours:
area = cv2.contourArea(i)
if area > 1000/2:
cv2.drawContours(image, contours, c, (0, 255, 0), 2)
c+=1
cv2.imshow("Final Image", image)
cv2.waitKey(0)
Can anybody help me with the code of detecting all the grids in the image.
I have a photo of a finished jigsaw puzzle and I want to get "clean" contours in order to match single puzzle pieces.
Source Image
For the current result I'm using the following steps:
current result
img = cv2.imread("img.jpg", cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 5)
threshold = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 2)
contours, hierarchy = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
blank = np.zeros((img.shape[0], img.shape[1], 4), dtype=np.uint8)
for i in range(len(contours)):
if cv2.contourArea(contours[i]) > 600:
cv2.drawContours(blank, contours, i, (255,255,255), 2)
cv2.imshow("gray", gray)
cv2.imshow("blur", blur)
cv2.imshow("threshold", threshold)
cv2.imshow("contours", blank)
cv2.waitKey(0)
I need to use an adaptive threshold because the full source image has bad light conditions:
Full source image
To clean up most of the noise I'm filtering contours with small areas.
What step am I missing in order to get clean contours without noise?
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()
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)
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)