Example #1
0
def printMat(image):
    """Print out a text representation of an image"""
    for row in range(image.rows):
        print "[",
        for col in range(image.cols):
            print cv.mGet(image, row, col),
        print "]"
    print ""
Example #2
0
def ComputeH(n,p1, p2, H):  
	 #int i  
	 A = cv.CreateMat(2*n, 9, CV_64FC1)  
	 U = cv.CreateMat(2*n, 2*n, CV_64FC1)  
	 D = cv.CreateMat(2*n, 9, CV_64FC1)  
	 V = cv.CreateMat(9, 9, CV_64FC1)  
	 
	 cv.SetZero(A)  
	 #for(i=0  i<n  i++)  
	 for i in range(n):
	 # 2*i row 
		 cv.Mset(A,2*i,3,-p1[i].x)  
		 cv.Mset(A,2*i,4,-p1[i].y)  
		 cv.Mset(A,2*i,5,-1)  
		 cv.Mset(A,2*i,6,p2[i].y*p1[i].x)  
		 cv.Mset(A,2*i,7,p2[i].y*p1[i].y)  
		 cv.Mset(A,2*i,8,p2[i].y)  
		 # 2*i+1 row 
		 cv.Mset(A,2*i+1,0,p1[i].x)  
		 cv.Mset(A,2*i+1,1,p1[i].y)  
		 cv.Mset(A,2*i+1,2,1)  
		 cv.Mset(A,2*i+1,6,-p2[i].x*p1[i].x)  
		 cv.Mset(A,2*i+1,7,-p2[i].x*p1[i].y)  
		 cv.Mset(A,2*i+1,8,-p2[i].x)  
	   
	 
	 # SVD 
	 # The flags cause U and V to be returned transposed 
	 # Therefore, in OpenCV, A = U^T D V 
	 cv.SVD(A, D, U, V, cv.CV_SVD_U_T|cv.CV_SVD_V_T)  
	 
	 # take the last column of V^T, i.e., last row of V 
	 #for(i=0  i<9  i++) 
	 for i in range(9):
	 	cv.Mset(H, i/3, i%3, cv.mGet(V, 8, i))  
Example #3
0
def Normalization(num,p,T):
	 # double scale, tx, ty  
	 # double meanx, meany  
	 # double value  
	 # int i  
	 x = cv.CreateMat(3,1,CV_64FC1)  
	 xp = cv.CreateMat(3,1,CV_64FC1)  
	 
	 meanx = 0  
	 meany = 0  
	 #for(i=0  i<num  i++)  
	 for i in range(num):
		 meanx += p[i].x  
		 meany += p[i].y  
	   
	 meanx /= float(num)  
	 meany /= float(num)  
	 
	 value = 0  
	 #for(i=0  i<num  i++) 
	 for i in range(num):
	 	value += sqrt(pow(p[i].x-meanx, 2.0) + pow(p[i].y-meany, 2.0))  
	 value /= float(num)  
	 
	 scale = sqrt(2.0)/value  
	 tx = -scale * meanx  
	 ty = -scale * meany  
	 
	 cv.SetZero(T)  
	 cv.mSet(T,0,0,scale)   
	 cv.mSet(T,0,2,tx)  
	 cv.mSet(T,1,1,scale)  
	 cv.mSet(T,1,2,ty)  
	 cv.mSet(T,2,2,1.0)  
	 
	 #Transform x' = T*x 
	 #for(i=0  i<num  i++)  
	 for i in range(num):
		 cv.mSet(x,0,0,p[i].x)  
		 cv.mSet(x,1,0,p[i].y)  
		 cv.mSet(x,2,0,1.0)  
		 #cvMatMul(T,x,xp)  
		 cv.matMulDeriv(T,x,xp)
		 p[i].x = cv.mGet(xp,0,0)/cvmGet(xp,2,0)  
		 p[i].y = cv.mGet(xp,1,0)/cvmGet(xp,2,0)  
Example #4
0
def DartLocation(raw_dart_loc):
    try:
        if calibration.calibrationComplete:
            print "Raw dart location:"
            print raw_dart_loc

#            temp_raw_loc = cv.CreateMat(3, 3, cv.CV_32FC1)
#            cv.mSet(temp_raw_loc, 0, 0, float(raw_dart_loc[0]))
#            cv.mSet(temp_raw_loc, 0, 1, float(raw_dart_loc[1]))
#            cv.mSet(temp_raw_loc, 0, 2, 1.0)
#
#            temp_new_loc = cv.CreateMat(3, 3, cv.CV_32FC1)
#
#            cv.Mul(calibration.mapping, temp_raw_loc, temp_new_loc, 1)
#
#            new_dart_loc = []
#            new_dart_loc = (int( cv.mGet(temp_new_loc, 0, 0)/cv.mGet(temp_new_loc, 0, 2) ), int( cv.mGet(temp_new_loc, 0, 1)/cv.mGet(temp_new_loc, 0, 2) ))

            raw_loc_mat = cv.CreateMat(calibration.image.height, calibration.image.width, cv.CV_32FC1)
            new_loc_mat = cv.CreateMat(calibration.image.height, calibration.image.width, cv.CV_32FC1)
            #y comes before x
            cv.mSet( raw_loc_mat, raw_dart_loc[1], raw_dart_loc[0], 1.0 )
            cv.WarpPerspective(raw_loc_mat, new_loc_mat, calibration.mapping)

            for i in range (0, calibration.image.width):
                for j in range(0, calibration.image.height):
                    if not (cv.mGet(new_loc_mat, j, i) == 0.0):
                        new_dart_loc = (i, j)
                        break

            print "New dart location:"
            print new_dart_loc
            return new_dart_loc

    #system not calibrated
    except AttributeError as err1:
        print err1
        return (-1, -1)

    except NameError as err2:
        #not calibrated error
        print err2
        return (-2, -2)
Example #5
0
def getFeatures(R, image, features, threshold):
    global algorithm
    global TOTAL_FEATURES
    global size
    if algorithm == 0:
        size = SSD_WINDOW_SIZE
    if algorithm == 1:
        size = NCC_WINDOW_SIZE
    feature_number = 0
    for i in range(int(size / 2), np.shape(image)[1] - int(size / 2)):
        for j in range(int(size / 2), np.shape(image)[0] - int(size / 2)):
            if cv.mGet(
                    R, i, j
            ) > threshold:  #threshold on the c o rne r re sp on se to prune interest points
                if feature_number < TOTAL_FEATURES:
                    feature_number = feature_number + 1
                    features.append(
                        Feature(i, j)
                    )  #adds the f e a t u r e t o the f e a t u r e l i s t
    print "number of features: ", feature_number
Example #6
0
def harrisCornerDetector(image):
    image_height = np.shape(image)[0]
    image_width = np.shape(image)[1]
    #image d e r i v a t i v e al o n g x
    #    image_der_x = cv.CreateImage ( ( image_width , image_height ) , cv.IPL_DEPTH_32F , 1)
    #image d e r i v a t i v e al o n g y
    #    image_der_y = cv.CreateImage ( ( image_width , image_height ) , cv.IPL_DEPTH_32F , 1)
    #g re y s c a l e
    grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    #A p pli e s S o bel Operator t o g e t the image d e r i v a t i v e s al on g x , y
    #    cv.Sobel ( grayscale_image1 , image_der_x , 1 ,0, 3 )
    image_der_x = cv2.Sobel(grayscale, cv2.CV_32F, 1, 0, 3)
    #    cv.Sobel ( grayscale_image1 , image_der_y , 0, 1, 3 )
    image_der_y = cv2.Sobel(grayscale, cv2.CV_32F, 1, 0, 3)
    #C al c ul a t e s C
    global WINDOW_SIZE  #size o f mask
    C = cv.CreateMat(2, 2, cv.CV_64FC1)
    #v a r i a b l e s f o r SVD
    U = cv.CreateMat(2, 2, cv.CV_64FC1)
    D = cv.CreateMat(2, 2, cv.CV_64FC1)
    I_x = 0
    I_xy = 0
    I_y = 0
    R = cv.CreateMat(image_width, image_height, cv.CV_64FC1)
    cv.Zero(R)
    #C o n s t r u c t s the v a ri a n c e Matrix a t each p i x e l
    #l o o p s through each p i x e l
    print "Calculating the Covariance"
    for i in range(int(WINDOW_SIZE / 2),
                   image_width - int(WINDOW_SIZE / 2 + 1)):
        for j in range(int(WINDOW_SIZE / 2),
                       image_height - int(WINDOW_SIZE / 2 + 1)):
            I_x = 0
            I_xy = 0
            I_y = 0
            for index_x in range(-int(WINDOW_SIZE / 2),
                                 int(WINDOW_SIZE / 2 + 1)):
                for index_y in range(-int(WINDOW_SIZE / 2),
                                     int(WINDOW_SIZE / 2 + 1)):
                    I_x = I_x + image_der_x[
                        j + index_y, i + index_x] * image_der_x[
                            j + index_y, i + index_x] / WINDOW_SIZE
                    I_xy = I_xy + image_der_x[
                        j + index_y, i + index_x] * image_der_y[
                            j + index_y, i + index_x] / WINDOW_SIZE
                    I_y = I_y + image_der_y[
                        j + index_y, i + index_x] * image_der_y[
                            j + index_y, i + index_x] / WINDOW_SIZE
                    cv.mSet(C, 0, 0, I_x)
                    cv.mSet(C, 1, 0, I_xy)
                    cv.mSet(C, 0, 1, I_xy)
                    cv.mSet(C, 1, 1, I_y)
                    #svd
                    cv.SVD(C, D, U, None, 0)
                    lambda1 = cv.mGet(D, 0, 0)
                    lambda2 = cv.mGet(D, 1, 1)
                    #corner Response
                    cv.mSet(
                        R, i, j, lambda1 * lambda2 - 0.04 * np.power(
                            (lambda1 + lambda2), 2))
    R_final = cv.CreateMat(image_width, image_height, cv.CV_64FC1)
    cv.Copy(R, R_final)
    #a p pl y s non maximum s u p p r e s si o n -> el em e n t s o t h e r than maximum v al u e s i n a window are removed
    for i in range(int(WINDOW_SIZE / 2), image_width - int(WINDOW_SIZE / 2)):
        for j in range(int(WINDOW_SIZE / 2),
                       image_height - int(WINDOW_SIZE / 2)):
            for index_x in range(-int(WINDOW_SIZE / 2),
                                 int(WINDOW_SIZE / 2 + 1)):
                for index_y in range(-int(WINDOW_SIZE / 2),
                                     int(WINDOW_SIZE / 2 + 1)):
                    R_value = cv.mGet(R, i, j)
                    R_neighbor_value = cv.mGet(R, i + index_x, j + index_y)
                    if R_value != 0 and R_value < R_neighbor_value:
                        cv.mSet(R_final, i, j, 0)
                        break
    return R_final
Example #7
0
def Calibration():
    global image

    if from_video:
        if from_camera:
            capture = cv.CaptureFromCAM(0)
        else:
            capture = cv.CaptureFromFile(videofile)


##        image = 0
        cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH, 640)
        cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, 480)

        if from_camera:
            ##we wait for 40 frames...the picture at the very start is always kind of weird,
            ##wait for the picture to stabalize
            for n in range(40):
                ##            RetrieveFrame is just GrabFrame and RetrieveFrame combined into 1
                ##            function call
                image = cv.QueryFrame(capture)
    ##            cv.GrabFrame(capture)
    ##            image = cv.CloneImage(cv.RetrieveFrame(capture))

    ## need to clone this image...otherwise once the capture gets released we won't have access
    ## to the image anymore
            image = cv.CloneImage(cv.QueryFrame(capture))
        else:
            ##            if we're capturing from a video file, then just take the first frame
            image = cv.QueryFrame(capture)
    else:
        image = cv.LoadImage(str(r"dartboard_cam1.bmp"),
                             cv.CV_LOAD_IMAGE_COLOR)

    #data we need for calibration:
    #mapping for a perspective transform
    global mapping
    #center of the dartboard in x, y form
    global center_dartboard
    #initial angle of the 20 - 1 points divider
    global ref_angle
    #the radii of the rings, there are 6 of them
    global ring_radius
    global calibrationComplete
    calibrationComplete = False

    #for grabbing the user's clicks
    global points

    #either grab data from file or user
    while calibrationComplete == False:
        #Read calibration file, if exists
        if os.path.isfile("calibrationData.pkl"):
            try:
                #for grabbing key presses in the python window showing the image
                global keyPressEvent
                keyPressEvent = Event()
                global keyPress
                #for synchronizing the image window thread
                global windowReady
                windowReady = Event()
                #for synchronizing the drawing
                global drawingFinished
                drawingFinished = Event()

                #start a fresh set of points
                points = []

                calFile = open('calibrationData.pkl', 'rb')
                calData = CalibrationData()
                calData = pickle.load(calFile)
                #load the data into the global variables
                points.append(calData.top)
                points.append(calData.bottom)
                points.append(calData.left)
                points.append(calData.right)  #index of 3
                init_point_arr = calData.init_point_arr
                center_dartboard = calData.center_dartboard
                ref_angle = calData.ref_angle
                ring_radius = []
                ring_radius.append(calData.ring_radius[0])
                ring_radius.append(calData.ring_radius[1])
                ring_radius.append(calData.ring_radius[2])
                ring_radius.append(calData.ring_radius[3])
                ring_radius.append(calData.ring_radius[4])
                ring_radius.append(
                    calData.ring_radius[5])  #append the 6 ring radii
                #close the file once we are done reading the data
                calFile.close()

                #copy image for old calibration data
                new_image = cv.CloneImage(image)

                #have the image in another window and thread
                t = Thread(target=CalibrationWindowThread2, args=(new_image, ))
                t.start()
                #wait for the image window to setup
                windowReady.wait()

                #now draw them out:
                #*******************1. Transform image******************************
                newtop = (round(new_image.height / 2),
                          round(new_image.height * 0.20))
                newbottom = (round(new_image.height / 2),
                             round(new_image.height * 0.80))
                #Note: the height is smaller than the width
                newleft = (round(new_image.height * 0.20),
                           round(new_image.height / 2))
                newright = (round(new_image.height * 0.80),
                            round(new_image.height / 2))

                mapping = cv.CreateMat(3, 3, cv.CV_32FC1)

                #get a fresh new image
                new_image = cv.CloneImage(image)

                cv.GetPerspectiveTransform(
                    [points[0], points[1], points[2], points[3]],
                    [newtop, newbottom, newleft, newright], mapping)
                cv.WarpPerspective(image, new_image, mapping)
                cv.ShowImage(prev_calibration_window, new_image)
                #*******************************************************************

                #********************2.Draw points dividers*************************
                #find initial angle of the 20-1 divider
                tempX_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
                #correct the point with respect to the center
                cv.mSet(tempX_mat, 0, 0,
                        init_point_arr[0] - center_dartboard[0])
                tempY_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
                #adjust the origin of y
                cv.mSet(
                    tempY_mat, 0, 0, init_point_arr[1] -
                    (new_image.height - center_dartboard[1]))
                init_mag_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
                init_angle_reversed_mat = cv.CreateMat(1, 1, cv.CV_32FC1)

                #each point region is 360/12 = 18 degrees large
                cv.CartToPolar(tempX_mat,
                               tempY_mat,
                               init_mag_mat,
                               init_angle_reversed_mat,
                               angleInDegrees=True)

                #display dividers
                current_point = (int(round(init_point_arr[0])),
                                 int(round(init_point_arr[1])))
                next_angle = cv.CreateMat(1, 1, cv.CV_32FC1)
                cv.mSet(next_angle, 0, 0, 360 - ref_angle)
                temp_angle = 360.0 - ref_angle
                #draw point dividers counterclockwise, just like how angle is calculated, arctan(y/x)
                for i in range(0, 20):
                    cv.Line(new_image, center_dartboard, current_point,
                            cv.CV_RGB(0, 0, 255), 1, 8)
                    #calculate the cartesian coordinate of the next point divider
                    temp_angle = 360.0 - temp_angle
                    temp_angle += 18.0
                    if temp_angle >= 360.0:
                        temp_angle -= 360.0
                    #make temp_angle reversed
                    temp_angle = 360.0 - temp_angle
                    #print temp_angle
                    cv.mSet(next_angle, 0, 0, temp_angle)

                    cv.PolarToCart(init_mag_mat,
                                   next_angle,
                                   tempX_mat,
                                   tempY_mat,
                                   angleInDegrees=True)

                    #current_point = []
                    #adjust the cartesian points
                    current_point = (int(
                        round(cv.mGet(tempX_mat, 0, 0) + center_dartboard[0])),
                                     int(
                                         round(
                                             cv.mGet(tempY_mat, 0, 0) +
                                             (new_image.height -
                                              center_dartboard[1]))))
                    #print current_point

                cv.ShowImage(prev_calibration_window, new_image)
                #*************************************************************************

                #**********************3. Draw rings**************************************
                for i in range(0, 6):
                    #display the rings
                    cv.Circle(new_image, center_dartboard, ring_radius[i],
                              cv.CV_RGB(0, 255, 0), 1, 8)

                cv.ShowImage(prev_calibration_window, new_image)
                #*************************************************************************

                #we are finished drawing, signal
                drawingFinished.set()

                #wait for key press
                print "Previous calibration data detected. Would you like to keep this calibration data? Press 'y' for yes"
                #wait indefinitely for a key press
                keyPressEvent.wait()

                #ASCII 121 is character 'y'
                if keyPress == 121:
                    #we are good with the previous calibration data
                    calibrationComplete = True
                else:
                    calibrationComplete = False
                    #delete the calibration file and start over
                    os.remove("calibrationData.pkl")

            #corrupted file
            except EOFError as err:
                print err

        #Manual calibration
        else:
            #use two events to emulate wait for mouse click event
            global e
            global key
            e = Event()
            key = Event()

            #start a fresh set of points
            points = []

            #copy image for manual calibration
            new_image = cv.CloneImage(image)

            t = Thread(target=CalibrationWindowThread, args=(new_image, ))
            t.start()

            print "Please select the center of the 20 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[0], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the center of the 3 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[1], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the center of the 11 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[2], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the center of the 6 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[3], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            #calculate the desired circle dimensions
            newtop = (round(new_image.height / 2),
                      round(new_image.height * 0.20))
            newbottom = (round(new_image.height / 2),
                         round(new_image.height * 0.80))
            #Note: the height is smaller than the width
            newleft = (round(new_image.height * 0.20),
                       round(new_image.height / 2))
            newright = (round(new_image.height * 0.80),
                        round(new_image.height / 2))

            mapping = cv.CreateMat(3, 3, cv.CV_32FC1)

            #get a fresh new image
            new_image = cv.CloneImage(image)

            cv.GetPerspectiveTransform(
                [points[0], points[1], points[2], points[3]],
                [newtop, newbottom, newleft, newright], mapping)
            cv.WarpPerspective(image, new_image, mapping)
            cv.ShowImage(window_name, new_image)

            print "The dartboard image has now been normalized."
            print ""

            center_dartboard = []
            print "Please select the middle of the dartboard. i.e. the middle of the double bull's eye"
            e.wait()
            e.clear()
            center_dartboard = points[4]
            center_dartboard = (int(round(center_dartboard[0])),
                                int(round(center_dartboard[1])))

            cv.Circle(new_image, center_dartboard, 3, cv.CV_RGB(255, 0, 0), 2,
                      8)
            cv.ShowImage(window_name, new_image)

            init_point_arr = []
            print "Please select the outermost intersection of the 20 points and 1 ponit line."
            e.wait()
            e.clear()
            init_point_arr = points[5]

            cv.Circle(new_image, init_point_arr, 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            #find initial angle of the 20-1 divider
            tempX_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            #correct the point with respect to the center
            cv.mSet(tempX_mat, 0, 0, init_point_arr[0] - center_dartboard[0])
            tempY_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            #adjust the origin of y
            cv.mSet(
                tempY_mat, 0, 0,
                init_point_arr[1] - (new_image.height - center_dartboard[1]))
            init_mag_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            init_angle_reversed_mat = cv.CreateMat(1, 1, cv.CV_32FC1)

            #each point region is 360/12 = 18 degrees large
            cv.CartToPolar(tempX_mat,
                           tempY_mat,
                           init_mag_mat,
                           init_angle_reversed_mat,
                           angleInDegrees=True)

            ref_angle = 360.0 - cv.mGet(init_angle_reversed_mat, 0, 0)
            global ref_mag
            ref_mag = cv.mGet(init_mag_mat, 0, 0)

            #print cv.mGet(init_mag_mat, 0, 0)
            #print "Initial angle"
            #print init_angle_val

            #display dividers
            current_point = (int(round(init_point_arr[0])),
                             int(round(init_point_arr[1])))
            next_angle = cv.CreateMat(1, 1, cv.CV_32FC1)
            cv.mSet(next_angle, 0, 0, 360 - ref_angle)
            temp_angle = 360.0 - ref_angle
            #draw point dividers counterclockwise, just like how angle is calculated, arctan(y/x)
            for i in range(0, 20):
                cv.Line(new_image, center_dartboard, current_point,
                        cv.CV_RGB(0, 0, 255), 1, 8)
                #calculate the cartesian coordinate of the next point divider
                temp_angle = 360.0 - temp_angle
                temp_angle += 18.0
                if temp_angle >= 360.0:
                    temp_angle -= 360.0
                #make temp_angle reversed
                temp_angle = 360.0 - temp_angle
                #print temp_angle
                cv.mSet(next_angle, 0, 0, temp_angle)

                cv.PolarToCart(init_mag_mat,
                               next_angle,
                               tempX_mat,
                               tempY_mat,
                               angleInDegrees=True)

                #current_point = []
                #adjust the cartesian points
                current_point = (
                    int(round(cv.mGet(tempX_mat, 0, 0) + center_dartboard[0])),
                    int(
                        round(
                            cv.mGet(tempY_mat, 0, 0) +
                            (new_image.height - center_dartboard[1]))))
                #print current_point

            cv.ShowImage(window_name, new_image)

            ring_arr = []
            print "Please select the first ring (any point). i.e. the ring that encloses the double bull's eye."
            e.wait()
            e.clear()
            ring_arr.append(points[6])

            cv.Circle(new_image, points[6], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the second ring (any point). i.e. the ring that encloses the bull's eye."
            e.wait()
            e.clear()
            ring_arr.append(points[7])

            cv.Circle(new_image, points[7], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the third ring (any point). i.e. the closer ring that encloses the triple score region."
            e.wait()
            e.clear()
            ring_arr.append(points[8])

            cv.Circle(new_image, points[8], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the fourth ring (any point). i.e. the further ring that encloses the triple score region."
            e.wait()
            e.clear()
            ring_arr.append(points[9])

            cv.Circle(new_image, points[9], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the fifth ring (any point). i.e. the closer ring that encloses the double score region."
            e.wait()
            e.clear()
            ring_arr.append(points[10])

            cv.Circle(new_image, points[10], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the sixth ring (any point). i.e. the further ring that encloses the double score region."
            e.wait()
            e.clear()
            ring_arr.append(points[11])

            cv.Circle(new_image, points[11], 3, cv.CV_RGB(255, 0, 0), 2, 8)
            cv.ShowImage(window_name, new_image)

            ring_radius = []
            for i in range(0, 6):
                #find the radius of the ring
                ring_radius.append(
                    int(
                        math.sqrt((ring_arr[i][0] - center_dartboard[0])**2 +
                                  (ring_arr[i][1] - center_dartboard[1])**2)))
                #display the rings
                cv.Circle(new_image, center_dartboard, ring_radius[i],
                          cv.CV_RGB(0, 255, 0), 1, 8)

            cv.ShowImage(window_name, new_image)

            e.wait()

            #destroy calibration window
            key.set()

            #save valuable calibration data into a structure
            calData = CalibrationData()
            calData.top = points[0]
            calData.bottom = points[1]
            calData.left = points[2]
            calData.right = points[3]
            calData.center_dartboard = center_dartboard
            calData.init_point_arr = init_point_arr
            calData.ref_angle = ref_angle
            calData.ring_radius = ring_radius

            #write the calibration data to a file
            calFile = open("calibrationData.pkl", "wb")
            pickle.dump(calData, calFile, 0)
            calFile.close()

            calibrationComplete = True
def Calibration():
    global image
    
    if from_video:
        if from_camera:
            capture = cv.CaptureFromCAM(0)
        else:
            capture = cv.CaptureFromFile(videofile)
##        image = 0
        cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH, 640)
        cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, 480)

        if from_camera:
    ##we wait for 40 frames...the picture at the very start is always kind of weird,
    ##wait for the picture to stabalize
            for n in range(40):
    ##            RetrieveFrame is just GrabFrame and RetrieveFrame combined into 1
    ##            function call
                image = cv.QueryFrame(capture)
    ##            cv.GrabFrame(capture)
    ##            image = cv.CloneImage(cv.RetrieveFrame(capture))
                
            ## need to clone this image...otherwise once the capture gets released we won't have access
            ## to the image anymore
            image = cv.CloneImage(cv.QueryFrame(capture))
        else:
##            if we're capturing from a video file, then just take the first frame
            image = cv.QueryFrame(capture)
    else:
        image = cv.LoadImage(str(r"dartboard_cam1.bmp"),cv.CV_LOAD_IMAGE_COLOR)
        

    #data we need for calibration:
    #mapping for a perspective transform
    global mapping
    #center of the dartboard in x, y form
    global center_dartboard
    #initial angle of the 20 - 1 points divider
    global ref_angle
    #the radii of the rings, there are 6 of them
    global ring_radius
    global calibrationComplete
    calibrationComplete = False

    #for grabbing the user's clicks
    global points

    #either grab data from file or user
    while calibrationComplete == False:
        #Read calibration file, if exists
        if os.path.isfile("calibrationData.pkl"):
            try:
                #for grabbing key presses in the python window showing the image
                global keyPressEvent
                keyPressEvent = Event()
                global keyPress
                #for synchronizing the image window thread
                global windowReady
                windowReady = Event()
                #for synchronizing the drawing
                global drawingFinished
                drawingFinished = Event()

                #start a fresh set of points
                points = []
                
                calFile = open('calibrationData.pkl', 'rb')
                calData = CalibrationData()
                calData = pickle.load(calFile)
                #load the data into the global variables
                points.append(calData.top)
                points.append(calData.bottom)
                points.append(calData.left)
                points.append(calData.right)    #index of 3
                init_point_arr = calData.init_point_arr
                center_dartboard = calData.center_dartboard
                ref_angle = calData.ref_angle
                ring_radius = []
                ring_radius.append(calData.ring_radius[0])
                ring_radius.append(calData.ring_radius[1])
                ring_radius.append(calData.ring_radius[2])
                ring_radius.append(calData.ring_radius[3])
                ring_radius.append(calData.ring_radius[4])
                ring_radius.append(calData.ring_radius[5])      #append the 6 ring radii
                #close the file once we are done reading the data
                calFile.close()

                #copy image for old calibration data
                new_image = cv.CloneImage(image)

                #have the image in another window and thread
                t = Thread(target=CalibrationWindowThread2,args=(new_image,));
                t.start()
                #wait for the image window to setup
                windowReady.wait()
                
                #now draw them out:
                #*******************1. Transform image******************************
                newtop = (round(new_image.height/2), round(new_image.height * 0.20))
                newbottom = (round(new_image.height/2), round(new_image.height * 0.80))
                #Note: the height is smaller than the width
                newleft = (round(new_image.height * 0.20), round(new_image.height/2))
                newright = (round(new_image.height * 0.80), round(new_image.height/2))

                mapping = cv.CreateMat(3, 3, cv.CV_32FC1)

                #get a fresh new image
                new_image = cv.CloneImage(image)

                cv.GetPerspectiveTransform([points[0],points[1],points[2],points[3]],[newtop, newbottom, newleft, newright],mapping)
                cv.WarpPerspective(image,new_image,mapping)
                cv.ShowImage(prev_calibration_window,new_image)
                #*******************************************************************


                #********************2.Draw points dividers*************************
                #find initial angle of the 20-1 divider
                tempX_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
                #correct the point with respect to the center
                cv.mSet( tempX_mat, 0, 0, init_point_arr[0] - center_dartboard[0] )
                tempY_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
                #adjust the origin of y
                cv.mSet( tempY_mat, 0, 0, init_point_arr[1] - (new_image.height - center_dartboard[1]) )
                init_mag_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
                init_angle_reversed_mat = cv.CreateMat(1, 1, cv.CV_32FC1)

                #each point region is 360/12 = 18 degrees large
                cv.CartToPolar(tempX_mat, tempY_mat, init_mag_mat, init_angle_reversed_mat, angleInDegrees=True)

                #display dividers
                current_point = (int(round(init_point_arr[0])), int(round(init_point_arr[1])))
                next_angle = cv.CreateMat(1, 1, cv.CV_32FC1)
                cv.mSet( next_angle, 0, 0, 360 - ref_angle )
                temp_angle = 360.0 - ref_angle
                #draw point dividers counterclockwise, just like how angle is calculated, arctan(y/x)
                for i in range(0, 20):
                    cv.Line(new_image, center_dartboard, current_point, cv.CV_RGB(0, 0, 255), 1, 8)
                    #calculate the cartesian coordinate of the next point divider
                    temp_angle = 360.0 - temp_angle
                    temp_angle += 18.0
                    if temp_angle >= 360.0:
                        temp_angle -= 360.0
                    #make temp_angle reversed
                    temp_angle = 360.0 - temp_angle
                    #print temp_angle
                    cv.mSet( next_angle, 0, 0, temp_angle )

                    cv.PolarToCart(init_mag_mat, next_angle, tempX_mat, tempY_mat, angleInDegrees=True)

                    #current_point = []
                    #adjust the cartesian points
                    current_point = ( int(round( cv.mGet( tempX_mat, 0, 0) + center_dartboard[0] )), int(round( cv.mGet( tempY_mat, 0, 0) + (new_image.height - center_dartboard[1]) ) ))
                    #print current_point

                cv.ShowImage(prev_calibration_window,new_image)
                #*************************************************************************


                #**********************3. Draw rings**************************************
                for i in range(0,6):
                    #display the rings
                    cv.Circle(new_image, center_dartboard, ring_radius[i], cv.CV_RGB(0, 255, 0), 1, 8)

                cv.ShowImage(prev_calibration_window,new_image)
                #*************************************************************************

                #we are finished drawing, signal
                drawingFinished.set()

                #wait for key press
                print "Previous calibration data detected. Would you like to keep this calibration data? Press 'y' for yes"
                #wait indefinitely for a key press
                keyPressEvent.wait()

                #ASCII 121 is character 'y'
                if keyPress == 121:
                    #we are good with the previous calibration data
                    calibrationComplete = True
                else:
                    calibrationComplete = False
                    #delete the calibration file and start over
                    os.remove("calibrationData.pkl")

            #corrupted file
            except EOFError as err:
                print err

        #Manual calibration
        else:
            #use two events to emulate wait for mouse click event
            global e
            global key
            e = Event()
            key = Event()

            #start a fresh set of points
            points = []

            #copy image for manual calibration
            new_image = cv.CloneImage(image)

            t = Thread(target=CalibrationWindowThread,args=(new_image,));
            t.start()

            print "Please select the center of the 20 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[0], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the center of the 3 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[1], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the center of the 11 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[2], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the center of the 6 points outermost rim."
            e.wait()
            e.clear()

            cv.Circle(new_image, points[3], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            #calculate the desired circle dimensions
            newtop = (round(new_image.height/2), round(new_image.height * 0.20))
            newbottom = (round(new_image.height/2), round(new_image.height * 0.80))
            #Note: the height is smaller than the width
            newleft = (round(new_image.height * 0.20), round(new_image.height/2))
            newright = (round(new_image.height * 0.80), round(new_image.height/2))

            mapping = cv.CreateMat(3, 3, cv.CV_32FC1)

            #get a fresh new image
            new_image = cv.CloneImage(image)

            cv.GetPerspectiveTransform([points[0],points[1],points[2],points[3]],[newtop, newbottom, newleft, newright],mapping)
            cv.WarpPerspective(image,new_image,mapping)
            cv.ShowImage(window_name,new_image)

            print "The dartboard image has now been normalized."
            print ""

            center_dartboard = []
            print "Please select the middle of the dartboard. i.e. the middle of the double bull's eye"
            e.wait()
            e.clear()
            center_dartboard = points[4]
            center_dartboard = (int(round(center_dartboard[0])), int(round(center_dartboard[1])))

            cv.Circle(new_image, center_dartboard, 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            init_point_arr = []
            print "Please select the outermost intersection of the 20 points and 1 ponit line."
            e.wait()
            e.clear()
            init_point_arr = points[5]

            cv.Circle(new_image, init_point_arr, 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            #find initial angle of the 20-1 divider
            tempX_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            #correct the point with respect to the center
            cv.mSet( tempX_mat, 0, 0, init_point_arr[0] - center_dartboard[0] )
            tempY_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            #adjust the origin of y
            cv.mSet( tempY_mat, 0, 0, init_point_arr[1] - (new_image.height - center_dartboard[1]) )
            init_mag_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            init_angle_reversed_mat = cv.CreateMat(1, 1, cv.CV_32FC1)

            #each point region is 360/12 = 18 degrees large
            cv.CartToPolar(tempX_mat, tempY_mat, init_mag_mat, init_angle_reversed_mat, angleInDegrees=True)

            ref_angle = 360.0 - cv.mGet(init_angle_reversed_mat, 0, 0)
            global ref_mag
            ref_mag = cv.mGet(init_mag_mat, 0, 0)

            #print cv.mGet(init_mag_mat, 0, 0)
            #print "Initial angle"
            #print init_angle_val

            #display dividers
            current_point = (int(round(init_point_arr[0])), int(round(init_point_arr[1])))
            next_angle = cv.CreateMat(1, 1, cv.CV_32FC1)
            cv.mSet( next_angle, 0, 0, 360 - ref_angle )
            temp_angle = 360.0 - ref_angle
            #draw point dividers counterclockwise, just like how angle is calculated, arctan(y/x)
            for i in range(0, 20):
                cv.Line(new_image, center_dartboard, current_point, cv.CV_RGB(0, 0, 255), 1, 8)
                #calculate the cartesian coordinate of the next point divider
                temp_angle = 360.0 - temp_angle
                temp_angle += 18.0
                if temp_angle >= 360.0:
                    temp_angle -= 360.0
                #make temp_angle reversed
                temp_angle = 360.0 - temp_angle
                #print temp_angle
                cv.mSet( next_angle, 0, 0, temp_angle )

                cv.PolarToCart(init_mag_mat, next_angle, tempX_mat, tempY_mat, angleInDegrees=True)

                #current_point = []
                #adjust the cartesian points
                current_point = ( int(round( cv.mGet( tempX_mat, 0, 0) + center_dartboard[0] )), int(round( cv.mGet( tempY_mat, 0, 0) + (new_image.height - center_dartboard[1]) ) ))
                #print current_point

            cv.ShowImage(window_name,new_image)

            ring_arr = []
            print "Please select the first ring (any point). i.e. the ring that encloses the double bull's eye."
            e.wait()
            e.clear()
            ring_arr.append(points[6])

            cv.Circle(new_image, points[6], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the second ring (any point). i.e. the ring that encloses the bull's eye."
            e.wait()
            e.clear()
            ring_arr.append(points[7])

            cv.Circle(new_image, points[7], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the third ring (any point). i.e. the closer ring that encloses the triple score region."
            e.wait()
            e.clear()
            ring_arr.append(points[8])

            cv.Circle(new_image, points[8], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the fourth ring (any point). i.e. the further ring that encloses the triple score region."
            e.wait()
            e.clear()
            ring_arr.append(points[9])

            cv.Circle(new_image, points[9], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the fifth ring (any point). i.e. the closer ring that encloses the double score region."
            e.wait()
            e.clear()
            ring_arr.append(points[10])

            cv.Circle(new_image, points[10], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            print "Please select the sixth ring (any point). i.e. the further ring that encloses the double score region."
            e.wait()
            e.clear()
            ring_arr.append(points[11])

            cv.Circle(new_image, points[11], 3,cv.CV_RGB(255, 0, 0),2, 8)
            cv.ShowImage(window_name, new_image)

            ring_radius = []
            for i in range(0,6):
                #find the radius of the ring
                ring_radius.append(int(math.sqrt(( ring_arr[i][0] - center_dartboard[0] )** 2 + (ring_arr[i][1] - center_dartboard[1] )** 2)))
                #display the rings
                cv.Circle(new_image, center_dartboard, ring_radius[i], cv.CV_RGB(0, 255, 0), 1, 8)

            cv.ShowImage(window_name,new_image)

            e.wait()

            #destroy calibration window
            key.set()

            #save valuable calibration data into a structure
            calData = CalibrationData()
            calData.top = points[0]
            calData.bottom = points[1]
            calData.left = points[2]
            calData.right = points[3]
            calData.center_dartboard = center_dartboard
            calData.init_point_arr = init_point_arr
            calData.ref_angle = ref_angle
            calData.ring_radius = ring_radius

            #write the calibration data to a file
            calFile = open("calibrationData.pkl", "wb")
            pickle.dump(calData, calFile, 0)
            calFile.close()

            calibrationComplete = True
Example #9
0
def DartRegion(dart_loc):
    try:
        if calibration.calibrationComplete:
            print "Finding dart throw information"
            dartInfo = GameEngine.dartThrow()

            #find the magnitude and angle of the dart
            tempX_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            cv.mSet( tempX_mat, 0, 0, dart_loc[0] - calibration.center_dartboard[0] )
            tempY_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            #adjust the origin of y to fit a Cartesian plane
            cv.mSet( tempY_mat, 0, 0, dart_loc[1] - (calibration.image.height - calibration.center_dartboard[1]) )
            dart_mag_mat = cv.CreateMat(1, 1, cv.CV_32FC1)
            dart_angle_reversed_mat = cv.CreateMat(1, 1, cv.CV_32FC1)

            #each point region is 360/12 = 18 degrees large
            cv.CartToPolar(tempX_mat, tempY_mat, dart_mag_mat, dart_angle_reversed_mat, angleInDegrees=True)

            dart_angle_val = 360.0 - cv.mGet(dart_angle_reversed_mat, 0, 0)

            dartInfo.magnitude = cv.mGet(dart_mag_mat, 0, 0)
            dartInfo.angle = dart_angle_val

            #Calculating score:
            #Find base point
            if dart_angle_val < calibration.ref_angle:         #make sure dart's angle is always greater
                dart_angle_val += 360.0
                
            angleDiffMul = int((dart_angle_val - calibration.ref_angle) / 18.0)

            #starting from the 20 points
            if angleDiffMul == 0:
                dartInfo.base = 20
            elif angleDiffMul == 1:
                dartInfo.base = 5
            elif angleDiffMul == 2:
                dartInfo.base = 12
            elif angleDiffMul == 3:
                dartInfo.base = 9
            elif angleDiffMul == 4:
                dartInfo.base = 14
            elif angleDiffMul == 5:
                dartInfo.base = 11
            elif angleDiffMul == 6:
                dartInfo.base = 8
            elif angleDiffMul == 7:
                dartInfo.base = 16
            elif angleDiffMul == 8:
                dartInfo.base = 7
            elif angleDiffMul == 9:
                dartInfo.base = 19
            elif angleDiffMul == 10:
                dartInfo.base = 3
            elif angleDiffMul == 11:
                dartInfo.base = 17
            elif angleDiffMul == 12:
                dartInfo.base = 2
            elif angleDiffMul == 13:
                dartInfo.base = 15
            elif angleDiffMul == 14:
                dartInfo.base = 10
            elif angleDiffMul == 15:
                dartInfo.base = 6
            elif angleDiffMul == 16:
                dartInfo.base = 13
            elif angleDiffMul == 17:
                dartInfo.base = 4
            elif angleDiffMul == 18:
                dartInfo.base = 18
            elif angleDiffMul == 19:
                dartInfo.base = 1
            else:
                #something went wrong
                dartInfo.base = -300

            #Calculating multiplier (and special cases for Bull's Eye):
            for i in range(0, len(calibration.ring_radius)):
                print calibration.ring_radius[i]
                #Find the ring that encloses the dart
                if dartInfo.magnitude <= calibration.ring_radius[i]:
                    #Bull's eye, adjust base score
                    if i == 0:
                        dartInfo.base = 25
                        dartInfo.multiplier = 2
                    elif i == 1:
                        dartInfo.base = 25
                        dartInfo.multiplier = 1
                    #triple ring
                    elif i == 3:
                        dartInfo.multiplier = 3
                    #double ring
                    elif i == 5:
                        dartInfo.multiplier = 2
                    #single
                    elif i == 2 or i == 4:
                        dartInfo.multiplier = 1
                    #finished calculation
                    break

            #miss
            if dartInfo.magnitude > calibration.ring_radius[5]:
                dartInfo.base = 0
                dartInfo.multiplier = 0

            return dartInfo


    #system not calibrated
    except AttributeError as err1:
        print err1
        dartInfo = GameEngine.dartThrow()
        return dartInfo

    except NameError as err2:
        #not calibrated error
        print err2
        dartInfo = GameEngine.dartThrow()
        return dartInfo