def update(self, *texture): okay, self.image = self.capture.read() if not getColor.sensitivity == self.ids.sensitivity.value_normalized: getColor.sensitivity = self.ids.sensitivity.value_normalized bounds = getColor.get(self.sampleImages) self.bounds = [np.array(bounds[0]), np.array(bounds[1])] if okay: coord = find.search(self.image[0:Global.hoopY, 0:self.w], self.bounds[0], self.bounds[1]) if self.filter: self.image = find.filter(self.image, self.bounds[0], self.bounds[1]) if not coord == (-1, -1): disp = self.image.copy() cv2.circle(disp, coord, 7, (0, 0, 255), 5) self.ids.img.texture = cam.capToTexture(disp) else: self.ids.img.texture = cam.capToTexture(self.image) try: self.radius = int(self.ids.radius.text) except: pass
def update(self, texture): okay, self.image = self.capture.read() if okay: disp = self.image if not self.normY == -1: cv2.line(disp, (-10, self.normY), (self.w + 10, self.normY), (0, 255, 0)) cv2.line(disp, (self.normX, -10), (self.normX, self.h + 10), (0, 255, 0)) self.ids.img.texture = cam.capToTexture(disp)
def update(self, texture): okay, self.image = self.capture.read() if okay: self.texture = cam.capToTexture(self.image) self.canvas.clear() with self.canvas: Rectangle(texture=self.texture, pos=self.pos, size=self.size) paint.message(self, "Please click on the basketball", 10, 50, 200) if self.tryAgain: paint.message(self, "Try clicking a more uniform area", 10, 110, 200)
def update(self, *texture): okay, self.image = self.capture.read() if okay: disp = find.filter(self.image, Global.lower_bound, Global.upper_bound) cv2.line(disp, (-10, Global.hoopY), (self.w + 10, Global.hoopY), (0, 255, 0)) for fp in self.falsePos: cv2.rectangle(self.image, (fp[0] - Global.deadPointRad, fp[1] - Global.deadPointRad), (fp[0] + Global.deadPointRad, fp[1] + Global.deadPointRad), (0, 255, 0), 10) cv2.rectangle(disp, (fp[0] - Global.deadPointRad, fp[1] - Global.deadPointRad), (fp[0] + Global.deadPointRad, fp[1] + Global.deadPointRad), (0, 255, 0), 10) coord = find.search(self.image[0:Global.hoopY, 0:self.w], Global.lower_bound, Global.upper_bound) if not coord == (-1, -1): cv2.circle(disp, coord, 5, (255, 0, 0), 5) self.ids.img.texture = cam.capToTexture(disp)
def refreshImage(self): # generate image try: self.image = Global.reportImage.copy() except: pass dispShots = [] for i in range(0, len(self.shots)): shot = self.shots[i] if self.map[i] == 1: dispShots.append(shot) self.image = paint.shotsImage(dispShots, self.image) try: self.ids.img.texture = cam.capToTexture(self.image) except: pass
def update(self, texture): self.ids.numShots.text = "Shots: " + str(len(Global.shots)) okay, self.image = self.capture.read() self.useMid = False midPoint = False if okay: self.frame += 1 for fp in Global.deadPoints: cv2.rectangle( self.image, (fp[0] - Global.deadPointRad, fp[1] - Global.deadPointRad), (fp[0] + Global.deadPointRad, fp[1] + Global.deadPointRad), (0, 0, 0), 10) if self.tracking: #look for point using tracker ok, bbox = self.tracker.update(self.image) #reset tracker point trackerPoint = (-1, -1) #look for point using color calibration point = find.search(self.image[0:Global.hoopY, 0:self.w], Global.lower_bound, Global.upper_bound) if ok: #find midpoint of tracker box p1 = (int(bbox[0]), int(bbox[1])) p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3])) midPoint = (int( (p1[0] + p2[0]) / 2), int((p1[1] + p2[1]) / 2)) #create range for color calibration point pf1 = (int(point[0] - self.radius), int(point[1] - self.radius)) pf2 = (int(point[0] + self.radius), int(point[1] + self.radius)) pfDiameter = self.radius * 2 #if conflict between two points if not point == (-1, -1) and (point[0] < p1[0] or point[0] > p2[0] or point[1] < p1[1] or point[1] > p2[1]): #if tracker stuck or less than 3 points reset tracker and use color point if len(self.last3 ) < 3 or midPoint == self.last_midPoint: cv2.rectangle(self.image, pf1, pf2, (255, 0, 0)) del self.tracker self.tracker = cv2.TrackerMedianFlow_create() self.tracker.init( self.image, (pf1[0], pf1[1], pfDiameter, pfDiameter)) midPoint = (-1, -1) self.useMid = False else: #check distance between last two points dist01sq = (self.last3[0][0] - self.last3[1][0] )**2 + (self.last3[0][1] - self.last3[1][1])**2 dist12sq = (self.last3[1][0] - self.last3[2][0] )**2 + (self.last3[1][1] - self.last3[2][1])**2 #if distance "small enough" use a line to project the next point if dist01sq < 30**2: # line: y = m(x-h) + k # y = (self.last3[0][1] - self.last3[1][1])/(self.last3[0][0] - self.last3[1][0]) * (point[0] - self.last3[0][0]) + self.last3[0][1] try: yP = (self.last3[0][1] - self.last3[1][1] ) / (self.last3[0][0] - self.last3[1][0]) * ( point[0] - self.last3[1][0] ) + self.last3[1][1] yMid = ( self.last3[0][1] - self.last3[1][1] ) / (self.last3[0][0] - self.last3[1][0] ) * (midPoint[0] - self.last3[1][0] ) + self.last3[1][1] distYP = abs(yP - point[1]) distYMid = abs(yMid - midPoint[1]) #if projection is close to tracker point use the tracker instead of the color if distYMid < distYP: self.useMid = True except: self.useMid = self.useMid #store midpoint to check for sticking points self.last_midPoint = midPoint else: #else not trakcing yet: initialize tracker using color point point = find.search(self.image[0:Global.hoopY, 0:self.w], Global.lower_bound, Global.upper_bound) if not point == (-1, -1): self.tracking = True self.tracker.init( self.image, (int(point[0] - self.radius), self.radius * 2, int(point[1] - self.radius), self.radius * 2)) if not self.reportImage: Global.reportImage = self.image.copy() self.reportImage = True #if there is a point, log it if (not point == (-1, -1) and not self.useMid) or midPoint: if point == (-1, -1): point = midPoint if point[1] < Global.hoopY: try: if not (point == self.last3[2]): self.time = videoTime(self.capture) except: self.time = videoTime(self.capture) #draw circle on the ball, and append point or midPoint to self.shot cv2.circle(self.image, point, 7, (0, 0, 255), 7) self.shot.append([point, self.time]) self.last3.insert(0, point) if len(self.last3) > 3: self.last3.pop() items = len(self.shot) - 1 #if more than one point if items > 1: #if starting from the shooter when previous point was at basket, initialize new shot if (self.shot[items - 1][0][0] < self.newShotThreshold and self.shot[items][0][0] > self.newShotThreshold and self.basketOn == 1) or ( self.shot[items - 1][0][0] > self.newShotThreshold and self.shot[items][0][0] < self.newShotThreshold and self.basketOn == -1): toAdd = self.shot[items][0] self.frame = 0 self.shot = [[toAdd, self.time]] self.wait_for_angle = True #if going backwards delete point elif self.shot[items - 1][0] * self.basketOn < self.shot[ items][0] * self.basketOn: self.shot.pop() self.last3.pop() #if shot initialized and passed cuttoff time - save shot to Global if self.wait_for_angle and self.time > 0 and ( videoTime(self.capture) > self.time + self.displayAngleThreshold): #reset time to avoid double logging shots self.time = 0 try: #fit parabola and calculate angle z = calc.curveFit(self.shot, "x") theta = int(round(calc.angle(z))) print "theta = " + str(theta) self.ids.lastAngle.text = "Last Angle = " + str( theta) + " degrees" #play sound if self.audio == True: if theta > 60: playsound("audio/ABOVE.wav", False) elif theta < 35: playsound("audio/BELOW.wav", False) else: playsound( "audio/numbers/" + str(theta) + ".wav", False) z[0] = z[0] * -1 z[1] = z[1] * -1 z[2] = z[2] * -1 + Global.hoopY self.curve = z Global.shots.append(self.shot) self.wait_for_angle = False except: #if having trouble curve fitting, discard shot and start over print "error trackshots.py ln 201" self.shot = [] self.last3 = [] #draw green line of raw data for i in range(1, len(self.shot) - 1): cv2.line(self.image, self.shot[i - 1][0], self.shot[i][0], (0, 255, 0)) try: if len(self.shot) > 1: x0 = (-1 * self.curve[1] - ((self.curve[1]**2) - 4 * self.curve[0] * (self.curve[2] - Global.hoopY))** (0.5)) / (2 * self.curve[0]) x1 = (-1 * self.curve[1] + ((self.curve[1]**2) - 4 * self.curve[0] * (self.curve[2] - Global.hoopY))** (0.5)) / (2 * self.curve[0]) xlin = np.linspace(x0, x1, num=100) for i in range(1, 100): #draw blue line of curve fit cv2.line( self.image, (int(xlin[i - 1]), int(self.curve[0] * xlin[i - 1]**2 + self.curve[1] * xlin[i - 1] + self.curve[2])), (int(xlin[i]), int(self.curve[0] * xlin[i]**2 + self.curve[1] * xlin[i] + self.curve[2])), (255, 0, 0)) else: #if no shot, replace curve with a line outside visible area self.curve = [0, 0, -10] except: pass else: self.manager.current = "menu" if okay: #show grid of basketheight height, width, channels = self.image.shape cv2.line(self.image, (-10, Global.hoopY), (width + 10, Global.hoopY), (0, 255, 0)) cv2.line(self.image, (self.newShotThreshold, -10), (self.newShotThreshold, height + 10), (0, 255, 0)) self.ids.img.texture = cam.capToTexture(self.image)
def selectColor(self, *args): absX = args[0].last_touch.px absY = args[0].last_touch.py totalWidth = args[0].width totalHeight = args[0].height imageSize = args[0].get_norm_image_size() trueImgX = (totalWidth - imageSize[0]) / 2 trueImgY = (totalHeight - imageSize[1]) / 2 self.radius = int(self.ids.radius.text) # if inside displayed image + radius if absX > trueImgX + self.radius and absX < trueImgX + imageSize[ 0] - self.radius and absY > trueImgY + self.radius and absY < trueImgY + imageSize[ 1] - self.radius: rawHeight, rawWidth, channels = self.image.shape transX = (absX - trueImgX) #* rawWidth / imageSize[0]ent transY = (absY - trueImgY) #* rawHeight / imageSize[1]ent transY = imageSize[1] - transY normX = int(transX * rawWidth / imageSize[0]) normY = int(transY * rawHeight / imageSize[1]) normRadius = int(float(self.radius) * rawWidth / 640) if normY - normRadius < Global.hoopY: blur = cv2.GaussianBlur(self.image, (5, 5), 0) sample = getColor.addSample(self.image, normX, normY, normRadius) self.ids.samples.text = str(getColor.samples) self.median = sample[0] self.std = sample[1] self.h = self.median[0] self.s = self.median[1] self.v = self.median[2] self.sampleImages.append([ cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)[0:Global.hoopY, 0:rawWidth], normX, normY ]) self.calImage = self.image.copy() cv2.circle(self.calImage, (normX, normY), normRadius, (0, 255, 0)) self.ids.img.texture = cam.capToTexture(self.calImage) if self.playing: self.playPause() self.updateInputs() bounds = getColor.get(self.sampleImages) self.bounds = [np.array(bounds[0]), np.array(bounds[1])]
def generate(self): if len(Global.shots) < 1: self.manager.current = 'menu' self.shots = [] self.angles = [] self.maxHeights = [] Global.shotFits = [] shots_filtered_raw = calc.filterRaw(Global.shots) for shot in shots_filtered_raw: try: self.shots.append( [calc.curveFit(shot, "x"), calc.curveFit(shot, "t")]) except: pass self.shots = calc.filterShots(self.shots, shots_filtered_raw) Global.shotsFiltered = self.shots if Global.mapped: dispShots = [] for i in range(0, len(self.shots)): shot = self.shots[i] if Global.map[i] == 1: dispShots.append(shot) self.shots = dispShots self.ids.shotsTaken.text = str(len(self.shots)) + "/" + str( len(Global.shots)) for shot in self.shots: theta = calc.angle(shot[0]) self.angles.append(theta) maxHeight = calc.maxHeight(shot[0]) self.maxHeights.append(maxHeight) std = np.std(self.angles) average = np.mean(self.angles) median = np.median(self.angles) self.ids.stdAngle.text = str(round(std, 2)) self.ids.averageAngle.text = str(round(average, 2)) self.ids.medianAngle.text = str(round(median, 2)) # generate image try: self.image = Global.reportImage.copy() except: pass self.image = paint.shotsImage(self.shots, self.image) pixelToFeetList = [] for shot in self.shots: a = shot[1][0] pixelToFeetList.append(abs(32.2 / (2 * a))) pixelToFeet = np.median(pixelToFeetList) Global.pixelToFeet = pixelToFeet endXs = [] for shot in self.shots: a = shot[0][0] b = shot[0][1] c = shot[0][2] #avoid imaginary numbers if (b**2 - 4 * a * c) >= 0: x01 = (-1 * b - (b**2 - 4 * a * c)**(0.5)) / (2 * a) x02 = (-1 * b + (b**2 - 4 * a * c)**(0.5)) / (2 * a) x0 = 0 # on left if Global.basketOn == 1: if x01 < x02: x0 = x01 else: x0 = x02 else: if x01 < x02: x0 = x02 else: x0 = x01 endXs.append(x0) distStd = np.std(endXs) distStdIn = distStd * pixelToFeet * 12 self.ids.distStd.text = str(round(distStdIn, 2)) + " In" # Dx = v0 t + 1/2 a t^2 # V^2 = v0^2 + 2 a Dx try: self.ids.traceImage.texture = cam.capToTexture(self.image) except: pass Global.shotFits = self.shots Global.angles = self.angles Global.stdAngle = std Global.averageAngle = average Global.medianAngle = median Global.averageMaxHeight = np.mean(self.maxHeights) Global.stdMaxHeight = np.std(self.maxHeights) Global.medianMaxHeight = np.median(self.maxHeights) Global.maxHeights = self.maxHeights