I am trying to detect the position of the ball throughout a video. In the beginning, I crop the video because my original clip has some random things at the top. I don't know why but the program doesn't capture all the frames - it sort of stops after the first frame. I tried it on another computer and it works. I have no idea what's wrong.
import cv2
import numpy as np
# Open the video
cap = cv2.VideoCapture('video-4.mp4')
while(1):
success, frame = cap.read()
# Take each frame
if success:
crop_img = frame[100:3000, 100:3000].copy()
gray = cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=1.5, minDist=505,param1=75, param2=30, minRadius=8, maxRadius=10)
# ensure at least some circles were found
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
# loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
print(x,y,r)
# draw the circle in the output image, then draw a rectangle
# corresponding to the center of the circle
cv2.circle(crop_img, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(crop_img, (x - 5, y - 5),
(x + 5, y + 5), (0, 128, 255), -1)
cv2.namedWindow("hi", cv2.WINDOW_NORMAL)
cv2.imshow('hi', crop_img)
cv2.waitKey(0)
else:
break
cv2.destroyAllWindows()
You are using y without initialising it.
You are using cv2.CAP_PROP_FRAME_WIDTH as though it is the width but it isn't. It is just a "define" to tell an OpenCV function what to return.
You are indexing frame by width first, when you should use height as the first index.
Related
HI i m trying to detect concentric circles in drilled aluminum sheet
below is the code which I'm using but it not detecting inner circle or outer circle. can anyone please help
import numpy as np
import cv2
image = cv2.imread("/Users/n/Downloads/New_Images/crop5.jpeg",0)
output = cv2.imread("/Users/n/Downloads/New_Images/crop5.jpeg",1)
cv2.imshow("Original image", image)
cv2.waitKey()
blurred = cv2.GaussianBlur(image,(11,11),0)
cv2.imshow("Blurred image", blurred)
cv2.waitKey()
setItem=set()
previous=0;
minR=4
for maxR in range(9,300,9):
# Finds circles in a grayscale image using the Hough transform
circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1, 100,
param1=100,param2=100,minRadius=minR,maxRadius=maxR)
minR+=4
# cv2.HoughCircles function has a lot of parameters, so you can find more about it in documentation
# or you can use cv2.HoughCircles? in jupyter nootebook to get that
# Check to see if there is any detection
if circles is not None:
# If there are some detections, convert radius and x,y(center) coordinates to integer
circles = np.round(circles[0, :]).astype("int")
for (x, y, r) in circles:
# Draw the circle in the output image
cv2.circle(output, (x, y), r, (0,255,0), 1)
# Draw a rectangle(center) in the output image
cv2.rectangle(output, (x - 2, y - 2), (x + 2, y + 2), (0,255,0), -1)
setItem.add(r)
lst=sorted(setItem)
print("Length of List =", len(lst))
for item in lst:
print(item)
cv2.imshow("Detections",output)
cv2.imwrite("CirclesDetection.jpg",output)
cv2.waitKey()
I have been trying to write a program that can detect circles on my screen.
This is my screen before code processing
As you can see on the image, there are three circles that the code should detect. I am using HoughCircles function from OpenCV library to achieve this task. My code is below.
ss = gui.screenshot()
img = cv2.cvtColor(np.array(ss), cv2.COLOR_RGB2BGR)
output = img.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 100)
if circles is not None:
print("circles found", len(circles))
circles = np.round(circles[0, :]).astype("int")
for (x, y, r) in circles:
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
cv2.imshow("output", np.hstack([gray, output]))
cv2.waitKey(0)
cv2.imshow("output", gray)
cv2.waitKey(0)
I am first taking screenshot of my screen. Then, I convert it to use it for opencv.
However, this code does not detect any circles for the screenshot shown in the first picture. I know this because when ran, my program does not print "circles found". Moreover, to show that I have been taking screenshots and transforming them to grayscale properly, I have this image taken from the last two lines of my code.
picture in a gray scale
To show that my code works with other circle images, here is a picture of a regular circle:
before detection
after detection
Any help would be very appreciated!
Here's an alternative solution to detect the circles without using the Hough Transform. As your input image has a very distinct blue hue to the blobs of interest, you can try to create a segmentation mask based on their HSV values. Then, detect contours and approximate each contour using a circle. The last step can be implemented using the cv2.minEnclosingCircle, which, as its name suggest, can compute the Minimum Enclosing Circle of a contour.
Let's see the code:
# image path
path = "D://opencvImages//"
fileName = "XUzFw.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Create a deep copy of the input for results:
inputImageCopy = inputImage.copy()
# Convert the image to the HSV color space:
hsvImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2HSV)
# Set the HSV values:
lowRange = np.array([78, 0, 158])
uppRange = np.array([125, 255, 255])
# Create the HSV mask
mask = cv2.inRange(hsvImage, lowRange, uppRange)
This generates the following segmentation mask:
As you can see, the only blobs that remain are the circles. Now, let's compute the contours and find the minimum enclosing circle:
# Find the circle blobs on the binary mask:
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Use a list to store the center and radius of the target circles:
detectedCircles = []
# Look for the outer contours:
for i, c in enumerate(contours):
# Approximate the contour to a circle:
(x, y), radius = cv2.minEnclosingCircle(c)
# Compute the center and radius:
center = (int(x), int(y))
radius = int(radius)
# Draw the circles:
cv2.circle(inputImageCopy, center, radius, (0, 0, 255), 2)
# Store the center and radius:
detectedCircles.append([center, radius])
# Let's see the results:
cv2.namedWindow("Circles", cv2.WINDOW_NORMAL)
cv2.imshow("Circles", inputImageCopy)
cv2.waitKey(0)
This is the result of the detection:
Additionally, you can check out the data stored in the detectedCircles list:
# Check out the detected circles:
for i in range(len(detectedCircles)):
# Get circle data:
center, r = detectedCircles[i]
# Print it:
print("i: "+str(i)+" x: "+str(center[0])+" y: "+str(center[1])+" r: "+str(r))
Which yields:
i: 0 x: 395 y: 391 r: 35
i: 1 x: 221 y: 391 r: 36
i: 2 x: 567 y: 304 r: 35
These are the parameters of houghCircles that works for me. You should also consider running a gaussian blur over the image before trying to find the circles.
I'm not a huge fan of houghCircles. I find it to be really finicky and I don't like how much of what it does is hidden inside the function. It makes tuning it mostly trial-and-error. These parameters work for this particular image, but I wouldn't count on this continuing to work under different lighting conditions or for different colors.
import cv2
import numpy as np
# load image
img = cv2.imread("spheres.png");
# grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
gray = cv2.GaussianBlur(gray,(5,5),0);
# circles
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp = 1, minDist = 100, param1=65, param2=20, minRadius=20, maxRadius=50)
# draw circles
if circles is not None:
# round to ints
circles = np.uint16(np.around(circles));
for circle in circles[0, :]:
# unpack and draw
x, y, radius = circle;
center = (x,y);
cv2.circle(img, center, radius, (255, 0, 255), 3);
# show
cv2.imshow("Image", img);
cv2.imshow("Gray", gray);
cv2.waitKey(0);
I'm working with this code, link code font
import cv2
import numpy as np
img = cv2.imread('opencv_logo.png',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv2.imshow('detected circles',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()
Probably is so easy but can somebody help me to understand the for loop?
Thanks!
Every i in for i in circles[0,:]: is a list representing a circle. i is made up of three values: the x-coordinate of it's center, y-coordinate of it's center and its radius.
If you look at the documentation for cv2.circle you will see how the center and radius was used to draw the circles.
Check out this link here with a working example of Hough Circles.
https://www.pyimagesearch.com/2014/07/21/detecting-circles-images-using-opencv-hough-circles/
I'm not familiar with them myself, but I did take a Computer Vision class a few semesters ago and found this site very helpful in general.
In the article, he provides some code with comments. It seems like circles is a list of all the circles detected in the image. It appears that a circle is an object containing the coordinates of the circle center along with the radius.
# detect circles in the image
circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1.2, 100)
# ensure at least some circles were found
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
# loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
# draw the circle in the output image, then draw a rectangle
# corresponding to the center of the circle
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
# show the output image
cv2.imshow("output", np.hstack([image, output]))
cv2.waitKey(0)
About your code, for more details about the value of i, try printing i as well as getting the type, and that should give you a hint.
print i
print type(i)
I'm trying to detect circles from the image using hough transform
my code :
import numpy as np
import cv2
image = cv2.imread("C:/Users/Anmol/Desktop/your_file.bmp")
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2,10)
cv2.waitKey(0)
print (circles)
# ensure at least some circles were found
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
# loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
# draw the circle in the output image, then draw a rectangle
# corresponding to the center of the circle
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(output, (x -5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
# show the output image
cv2.imshow("output", np.hstack([image, output]))
cv2.waitKey(0)
stops at the line
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2,10)
I left my code running for about 5 hours but still its not going ahead of this line. It is not giving any error.
Plzz guide me what to do.
I suggest downscaling the input image if it's really large, and running a blur filter. Both of these will speed up Hough tremendously.
I want to detect a circle from a given image. But it just doesn't work the way I want it to. I implemented a circle detection algorithm, which works on some images with a circle but not on the one I want. I tweaked with the parameters, but couldn't get it to work.
import cv2
import numpy as np
# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread("damn-circle.png")
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# detect circles in the image
blur = cv2.GaussianBlur(gray,(5,5),0)
circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, 2, 120)
cv2.imshow("output", np.hstack([blur]))
cv2.waitKey(0)
print circles
# ensure at least some circles were found
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
# loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
# draw the circle in the output image, then draw a rectangle
# corresponding to the center of the circle
cv2.circle(output, (x, y), r, (0, 255, 0), 4)
cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
# show the output image
cv2.imshow("output", np.hstack([output]))
cv2.waitKey(0)
You're code is almost perfect. It's just that the method CV_HOUGH_GRADIENT sits inside a package, cv (at least for opencv version: 2.4.13). I changed that one line to mention the package and it worked well. You'll have to put specific versions for OpenCV and NumPy if you're still not getting the right result on this simple image. Change your line to be like this:
circles = cv2.HoughCircles(blur, cv2.cv.CV_HOUGH_GRADIENT, 2, 120)
You should get a nice result. At least I just did. image with found Hough circle shown
Edited:
Ah, I didn't understand which image the question was about. I changed parameters for several items particularly the Canny detector param and the radius min/max and the accumulator resolution. I think these params will find what you want:
circles = cv2.HoughCircles(blur, method = cv2.cv.CV_HOUGH_GRADIENT, minDist = 90 , dp = 1, param1 = 3, param2 = 12 , minRadius = 30, maxRadius = 50)
My found image now looks like this: another image with found circle