def gradient(img): cols, rows = cv.GetSize(img) x_drv = cv.CreateMat(rows,cols,cv.CV_32FC1) y_drv = cv.CreateMat(rows,cols,cv.CV_32FC1) mag = cv.CreateMat(rows,cols,cv.CV_32FC1) ang = cv.CreateMat(rows,cols,cv.CV_32FC1) cv.Sobel(img, x_drv, 1, 0) cv.Sobel(img, y_drv, 0, 1) cv.CartToPolar(x_drv,y_drv,mag,ang) return (mag,ang)
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 opencvSaliency(self, scaledImageGray): cvImageGray = cv.CreateMat(scaledImageGray.height, scaledImageGray.width, cv.CV_32FC1) cv.Convert(scaledImageGray, cvImageGray) src = cvImageGray dftWidth = cv.GetOptimalDFTSize(src.width - 1) dftHeight = cv.GetOptimalDFTSize(src.height - 1) real = cv.CreateMat(dftHeight, dftWidth, cv.CV_32FC1) imaginary = cv.CreateMat(dftHeight, dftWidth, cv.CV_32FC1) dft = cv.CreateMat(dftHeight, dftWidth, cv.CV_32FC2) tmp = cv.GetSubRect(real, (0, 0, src.width, src.height)) cv.Copy(src, tmp) cv.Zero(imaginary) cv.Merge(real, imaginary, None, None, dft) # do the fft cv.DFT(dft, dft, cv.CV_DXT_FORWARD, src.height) cv.Split(dft, real, imaginary, None, None) cv.CartToPolar(real, imaginary, real, imaginary, 0) cv.Log(real, real) filtered = cv.CreateMat(dftHeight, dftWidth, cv.CV_32FC1) cv.Copy(real, filtered) cv.Smooth(filtered, filtered, cv.CV_BLUR) cv.Sub(real, filtered, real, None) cv.Exp(real, real) cv.PolarToCart(real, imaginary, real, imaginary, 0) #cv.PolarToCart( np.ones( shape=(dftHeight,dftWidth), dtype=np.float32 ), imaginary, real, imaginary,0 ) # do inverse fourier transform cv.Merge(real, imaginary, None, None, dft) cv.DFT(dft, dft, cv.CV_DXT_INV_SCALE, src.height) cv.Split(dft, real, imaginary, None, None) # get magnitude cv.CartToPolar(real, imaginary, real, None, 0) cv.Pow(real, real, 2.0) FILTER_RAD = 3 IPL_BORDER_CONSTANT = 0 sfiltered = cv.CreateMat(real.height + FILTER_RAD * 2, real.width + FILTER_RAD * 2, cv.CV_32FC1) cv.CopyMakeBorder(real, sfiltered, (FILTER_RAD, FILTER_RAD), IPL_BORDER_CONSTANT) cv.Smooth(sfiltered, sfiltered, cv.CV_GAUSSIAN, 2 * FILTER_RAD + 1) (min, max, minLoc, maxLoc) = cv.MinMaxLoc(sfiltered) cv.ConvertScale(sfiltered, sfiltered, 1 / (max - min), -min / (max - min)) # copy result to output image tmp = cv.GetSubRect(sfiltered, (FILTER_RAD, FILTER_RAD, src.width, src.height)) cv.Copy(tmp, cvImageGray) #cvReleaseMat(&sfiltered); #cvReleaseMat(&real); #cvReleaseMat(&filtered); #cvReleaseMat(&imaginary); #cvReleaseMat(&dft); saliencyMap = np.array(255.0 * np.array(cvImageGray), dtype=np.uint8) return saliencyMap
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