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?
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 try to find the contour of the object using this code
import cv2
import numpy as np
# Let's load a simple image with 3 black squares
image = cv2.imread('C://Users//gfg//shapes.jpg')
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)
cv2.waitKey(0)
print("Number of Contours found = " + str(len(contours)))
# Draw all contours
# -1 signifies drawing all contours
cv2.drawContours(image, contours, -1, (0, 255, 0), 3)
cv2.imshow('Contours', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
I try to make a userframe so that contours is relative to new userframe (right now contour is relative to camera frame-0-640 and 0-480)
the new frame can be 5,5 - 10,6 - 7,10 - 15,12
I have been at this all day, how to we remove the small back noise in the red circle? I would need it to work on other samples of pictures like this.
The idea I used is to findContours and then add a mask with all the small black noise that is less than a certain area (trial and error).
Removing noise in red ellipse
image = cv2.imread("11_Image_after_noise_removal.png")
# copy image
img = image.copy()
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0, cv2.THRESH_BINARY)
thresh = 255 - thresh
# Use cv2.CCOMP for two level hierarchy
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP,
cv2.CHAIN_APPROX_SIMPLE) # Use cv2.CCOMP for two level hierarchy
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)
cv2.imshow("First detection", img)
# loop through the contours
for i, cnt in enumerate(contours):
# if the contour has no other contours inside of it
if hierarchy[0][i][3] != -1: # basically look for holes
# if the size of the contour is less than a threshold (noise)
if cv2.contourArea(cnt) < 70:
# Fill the holes in the original image
cv2.drawContours(img, [cnt], 0, (0, 0, 0), -1)
# display result
# Visualize the image after the Otsu's method application
cv2.imshow("Image after noise removal", img)
cv2.waitKey(0)
cv2.destroyAllWindows().destroyAllWindows()
You might check the contour area using area = cv.contourArea(cnt) and if it is below some threshold, ignore it.
Here is the OpenCV documentations:
https://docs.opencv.org/4.3.0/dd/d49/tutorial_py_contour_features.html
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 have and portrait image. To which I:
Convert to Grayscale
Then convert to binary
Then I used morphological erosion operation.
Then I used morphological dilation operation.
Now, as last process, I am trying to find out the contours and drawing them. However, contours are getting found and drawn too, but, it is only getting drawn in white color, which made it looked like, contours is not drawn at all. What am I doing wrong??
Here is my code:
import numpy as np
import cv2
img = cv2.imread("Test1.jpg")
image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("GrayScaled", image)
cv2.waitKey(0)
ret, thresh = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("Black&White", thresh)
cv2.waitKey(0)
kernel1 = np.ones((2,2),np.uint8)
erosion = cv2.erode(thresh,kernel1,iterations = 4)
cv2.imshow("AfterErosion", erosion)
cv2.waitKey(0)
kernel2 = np.ones((1,1),np.uint8)
dilation = cv2.dilate(erosion,kernel2,iterations = 5)
cv2.imshow("AfterDilation", dilation)
cv2.waitKey(0)
contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(dilation, contours, -1, (255, 0, 0), 2)
cv2.imshow("Contours", dilation)
cv2.waitKey(0)
cv2.destroyAllWindows()
Here are images step by step:
Original Image:
GrayScaled Image:
Binary Image:
After Erosion:
After Dilation:
Contour:
I am defining the color of the contours boundary to be red in above code. So, why is it not showing red boundaries??