예제 #1
0
    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
예제 #2
0
    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)
예제 #4
0
    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)
예제 #5
0
    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
예제 #6
0
    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)
예제 #7
0
    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])]
예제 #8
0
    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