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 ""
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))
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)
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)
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
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
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
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