I am currently working on a project detecting defects on an image.
The contours are not connected...I don't know why they're discrete point
Here is my code:
ret, thresh1 = cv2.threshold(img, 95, 255, cv2.THRESH_BINARY)
cnts= cv2.findContours(thresh1,cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)[-2]
cv2.drawContours(img, cnts, -1, (255,255,0), 3)
Also the len(cnts) function isn't return the right number of white point...
It is possible that find contours is picking holes as well. Try this one out and see if it fixes your problem.
ret, thresh1 = cv2.threshold(img, 95, 255, cv2.THRESH_BINARY)
cnts= cv2.findContours(thresh1,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
cv2.drawContours(img, cnts, -1, (255,255,0), 3)
Related
I have a image consisting N almost 90 times but I am getting 105 contours using below code:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#cv2.imshow("Image", gray)
#cv2.waitKey(0)
blurred = cv2.GaussianBlur(gray, (5, 5), 0) #blur to reduce noise
#cv2.imshow("Image", blurred)
#cv2.waitKey(0)
# perform edge detection, find contours in the edge map, and sort the
# resulting contours from left-to-right
edged = cv2.Canny(blurred, 30, 150) #30, 150
#cv2.imwrite("test.png", edged)
#cv2.imshow("Image", edged)
#cv2.waitKey(0)
#find contours of characters(objects) in images
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
if cnts:
cnts = sort_contours(cnts, method="left-to-right")[0]
cv2.drawContours(image, cnts, -1, (0, 0, 255), 2)
cv2.imwrite("all_contours.jpg", image)
I have tried different combinations in Canny and findContours function but cant get the contours equal to the number of N in image.
My image:
image with contours:
Looking at the contours image, I cant see where is the problem.
Any help or hint will be appreciated.
P.S : this image is an ideal image for testing. In real scenario, image will be taken from webcam.
Try without Bluring image.
import cv2
image = cv2.imread("n.png")
image = cv2.resize(image, (800, 800))
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, threshold = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.putText(image, "contours found in image : " + str(len(contours)), (20, 20), cv2.FONT_HERSHEY_PLAIN, 1, (255, 0, 0),1)
cv2.drawContours(image, contours, -1, (0, 0, 255), -1)
cv2.imshow("contour_image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
I have foreground mask, like this
If I use findContours method I receive this result
I want to find only main contours on hand without trash. How can I do it?
thresh = 100
# get threshold image
ret, thresh_img = cv.threshold(fgMask, thresh, 255, cv.THRESH_BINARY)
# find contours
contours, hierarchy = cv.findContours(thresh_img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# create an empty image for contours
img_contours = np.zeros(img.shape)
# draw the contours on the empty image
cv.drawContours(img_contours, contours, -1, (0, 255, 0), 3)
cv.imwrite("img.png", fgMask)
cv.imwrite("img1.png", img_contours)
Maybe you can try blurring image before threshold to reduce the noise.
However, your foreground mask is quite bad actually for this purpose. Since I cannot see what you have done before, it is generally better to use HSV color space if you want to achieve human skin. Because
The color of human skin is created by a combination of blood (red) and
melanin (yellow, brown). Skin colors lie between these two extreme
hues and are somewhat saturated.
HSV: (Hue-Saturation-Value) defined in a way that is similar to how
humans perceive color.
img_path = "hand.jpg"
img = cv.imread(img_path)
# define the upper and lower boundaries of the HSV pixel intensities
# to be considered 'skin'
hsvim = cv.cvtColor(img, cv.COLOR_BGR2HSV)
lower = np.array([0, 48, 80], dtype="uint8")
upper = np.array([20, 255, 255], dtype="uint8")
skinMask= cv.inRange(hsvim, lower, upper)
# blur the mask to help remove noise
skinMask= cv.blur(skinMask, (2, 2))
# get threshold image
ret, thresh = cv.threshold(skinMask, 100, 255, cv.THRESH_BINARY)
cv.imshow("thresh", thresh)
# draw the contours on the empty image
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
contours = max(contours, key=lambda x: cv.contourArea(x))
cv.drawContours(img, [contours], -1, (255, 255, 0), 2)
cv.imshow("contours", img)
cv.waitKey()
should resulted better like
Code Reference
What I have tried is drawing the external contour using the following lines
cnts, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(orig, cnts, -1, (0, 255, 0), 3) # this draws the external contour
Referring the below
[![enter image description here][1]][1]
How can I arrive at the answer below?
[![enter image description here][2]][2]
I don't know how it is solved in the links but you can use a blank mask on which you can draw your contour and then use cv2.dilate to expand it using a kernel size of the number of pixels you require between them. Once that is done find contours on the mask and draw the second one onto your original image.
import cv2
import numpy as np
img = cv2.imread('contour.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, cnts, -1, (0, 255, 0), 3)
mask = np.zeros(img.shape[:2], dtype=np.uint8)
cv2.drawContours(mask, cnts, -1, 255, 1)
kernel = np.ones((100, 100), np.uint8)
mask = cv2.dilate(mask, kernel, iterations = 1)
cnts, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, cnts, 1, (255, 0, 0), 3)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
i need to find contours of brown regions. but befıre that, i tried to draw all contours. but i can't see any contour on
i tried this:
contours, hierarchy = cv2.findContours(thresh_dummy, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(thresh_dummy, contours, -1, (0, 255, 0), 3)
I think the reason why you are not seeing contours in the output image is because you are drawing contours with (0, 255, 0), which would not be visible on a grayscale image (thresh_dummy happens to be a grayscale image). What you could do is convert thresh_dummy to RGB before drawing the contours or you could just use a random color like (128, 255, 128) which would be visible on the specific example you have.
contours, hierarchy = cv2.findContours(thresh_dummy, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
thresh_color = cv2.cvtColor(thresh_dummy, cv2.COLOR_GRAY2RGB)
cv2.drawContours(thresh_color, contours, -1, (0, 255, 0), 3)
cv2.imwrite("thresh_color.jpg", thresh_color)
I am trying to focus on a Region of Interest on the face by using Numpy cropping. For large images, I have no trouble. But for smaller ones, I can find the face and find the matching bounding box, but when I try to crop it and show the image, I get a gray background to the right of the image. I wouldn't mind it, but when I try to apply contours to the image, the bottom and right edges are picked up as contour edges. How do I make sure that the gray padding doesn't affect my contour?
Here is my function:
def head_ratio(self):
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
faces = face_cascade.detectMultiScale(self.gray, 1.3, 5)
m_height, m_width, channels = self.image.shape
x, y, w, h = faces[0]
ROI = self.image[y:y+h,x:x+w]
kernel = np.ones((5,5), np.float32)/10
blurred = cv2.filter2D(self.gray[y:y+h, x:x+w], -1, kernel)
ret, thresh = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY)
_,contours,_ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(ROI, contours, -1, (255, 255, 255), 3)
cv2.imshow("output", ROI)
cv2.waitKey(0)
cv2.destroyAllWindows()
return 1
Thank you for your help. I have been trying to look for an answer to this but was having trouble with what to search for.