0

I want to track a moving cap of a coke bottle in the webcam Feed with OpenCV in Python (or C++). I tried to search for all the red in the frame and then I used some kind of HOUGH TRANSFORM to search for circles. I cant find the right radius for the circle and fix it so it doesn't change every frame.the process time is not so important I dont want a real time detection but I do want a precise red circle detection.

This is what I have so far:

import cv2
import numpy as np
import cv2.cv as cv
cap = cv2.VideoCapture(0)
while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # define range of blue color in HSV 
    lower_red = np.array([160,140,50]) 
    upper_red = np.array([180,255,255])

    imgThreshHigh = cv2.inRange(hsv, lower_red, upper_red)

    imgray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    thresh = 18
    edges = cv2.Canny(imgray,thresh,thresh*3)

    circles = cv2.HoughCircles(imgThreshHigh, cv.CV_HOUGH_GRADIENT, 1, 500, 25, 75, 5, 15)
    maxRadius= 0
    xc = 0.00
    yc = 0.00
    found = False 
    if circles is not None:
        found = True
        for i in circles[0,:3]:
            if i[2] < 100:
                if i[2] > maxRadius:
                    maxRadius = i[2]
                    if maxRadius > 1.0:
                        # draw the outer circle
                        cv2.circle(frame,(i[0],i[1]),maxRadius,(0,0,255),2)
                        # draw the center of the circle
                        cv2.circle(frame,(i[0],i[1]),1,(0,0,255),3)
                        xc = i[0]
                        yc = i[1] 
    if found: 
        print "ball detected at position:",xc, ",", yc, " with radius:", maxRadius
    else: 
        print "no ball" 
    cv2.imshow('frame',frame)
    cv2.imshow('edges',edges)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break
cv2.destroyAllWindows()

I dont think HOUGH TRANSFORM works for this. So I want to use the edges. How can I use an equation like (X-Xc)^2 + (Y-Yc)^2 =R^2 and the contours to find circles?

Also if there is an improvement for Hough Transform I will appreciate it if you share with me

Contours:

contours,hierarchy=cv2.findContours(edges,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

My example image: ---> this is not my example Image.this is the object I want to find in videos.

enter image description here

user5556814
  • 13
  • 1
  • 6

1 Answers1

0

Well for the color you have to find the right range, for the human eye the bottle cap is red, but for the camera could be orange or something like that. Also is affected by the light so the camera could get some white. I learned this on the hard way haha. You could do a code with trackbars and hsv values to get the exact rang for your objet.

Now, are you looking for the center (x,y)? You can try with cv2.moments() and for

Here is an example

For your code is something like this

import cv2
import numpy as np
import cv2.cv as cv
cap = cv2.VideoCapture(0)

coords = []
while(1):

    # Take each frame
    _, frame = cap.read()

    # Convert BGR to HSV

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # define range of blue color in HSV 
    lower_red = np.array([160,140,50]) 
    upper_red = np.array([180,255,255])

    imgThreshHigh = cv2.inRange(hsv, lower_red, upper_red)
    thresh = imgThreshHigh.copy()

    countours,_ = cv2.findContours(thresh, cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

    for cnt in countours:
        area = cv2.contourArea(cnt)
        if area > max_area:
        max_area = area
        best_cnt = cnt

    M = cv2.moments(best_cnt)
    cx,cy = int(M['m10']/M['m00']), int(M['m01']/M['m00'])
    coord = cx, cy #This are your coordinates for the circle
    # area = moments['m00'] save the object area
    #perimeter = cv2.arcLength(best_cnt,True) is the object perimeter

    #Save the coords every frame on a list
    #Here you can make more conditions if you don't want repeated coordinates
    points.append(coord) 

    cv2.imshow('frame',frame)
    cv2.imshow('Object',thresh)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break
cv2.destroyAllWindows()

With moments you don't have the raidius hough transform that you mentioned because calculate the relative center of the object every time.

Here is the code I use to know which is the exact value, hope it helps you HSV detection code

Ellebkey
  • 2,201
  • 3
  • 22
  • 31
  • that was helpful but im looking to find the cap in many different backgrounds with so many noise .something like [Coca Cola can detection](http://stackoverflow.com/questions/10168686/algorithm-improvement-for-coca-cola-can-shape-recognition) but for the cap(or any red circle). – user5556814 Nov 23 '15 at 03:49
  • With the coca cola can, as you can see, they use a lot of different methods to detect the "Coca Cola" phrase.For example I'm working on something like that trying to detect figure using Hu Moment applying a Cany Boder and Histogram Comparansion. Only using color is the easiest way to detect an object. Telling more about your project can give us an idea what you really need. – Ellebkey Nov 23 '15 at 04:17
  • I have 1/4 of a A4 paper(background is white) and I draw a red circle in the middle of the paper.there is a moving toy car in a race circuit and the paper is on its back.Also camera is filming from top. I want to track this car movements to calculate velocity and acceleration with different engine and gears – user5556814 Nov 23 '15 at 06:56
  • I need the coordinates of the center of red circle(x,y) in every frame then I can calculate velocity easily(x=vt).with hough transform the radius changes every time.I can isolate red completely when there is lots of lights and track with my code but the radius is not precise so the coordinates are so messy – user5556814 Nov 23 '15 at 07:00
  • I dont understand you but that link helped a lot thank you. But what if there is another red(for example a red rectangle) in the frame?How can I chose the circle? – user5556814 Nov 23 '15 at 19:11
  • The tracking goes with the object that is moving or bigger are, but if you really need to ignore the rest, try using backgroud subtraction. Opencv has some methods that you can use like cv2.createBackgroundSubtractorMOG() – Ellebkey Nov 23 '15 at 21:05
  • I cant understand you !Do you use google translate for this? – user5556814 Nov 24 '15 at 08:16
  • No, sorry for my terrible english :( – Ellebkey Nov 24 '15 at 16:47