示例#1
0
    def computePerspectiveTransformation(self, contours_structure,
                                         BASE_IM_GRAY, BASE_IM_red):
        target_dim = Dartboard.ENV['DART_BOARD_TARGET_DIMENSION']
        pts1 = np.zeros((4, 2), 'int')
        for i in range(len(contours_structure)):
            cnt = contours_structure[i]
            M = cv2.moments(cnt)
            cx = int(M['m10'] / M['m00'])
            cy = int(M['m01'] / M['m00'])
            #print(str(i) + " x: " + str(cx) + " y: " +str(cy))
            pts1[i, 0] = cx
            pts1[i, 1] = cy
        #print(pts1)
        sorted_points_x = pts1[pts1[:, 0].argsort()]
        #print(sorted_points_x)
        left_column = sorted_points_x[0:2, :]
        right_column = sorted_points_x[2:, :]
        sorted_points_y_left = left_column[left_column[:, 1].argsort()]
        sorted_points_y_right = right_column[right_column[:, 1].argsort()]

        pts_src = np.asarray(
            np.concatenate((sorted_points_y_left, sorted_points_y_right),
                           axis=0), "float32")
        #print(pts_src)
        pts_dest = np.float32([[0, 0], [0, target_dim[1]], [target_dim[1], 0],
                               [target_dim[1], target_dim[1]]])
        M = cv2.getPerspectiveTransform(pts_src, pts_dest)

        px, py = Image_Tools.getIntersection(pts_src)
        pts_src_corrected, ROI_bull, ROI_center = self._correctCenterOfBull(
            BASE_IM_GRAY, BASE_IM_red, px, py, pts_src)
        return M, pts_src_corrected
示例#2
0
    def computePerspectiveTransformationPts(self, PTS, BASE_IM_GRAY,
                                            BASE_IM_red):
        #PTS: top,bottom,left,right
        target_dim = Dartboard.ENV['DART_BOARD_TARGET_DIMENSION']
        pts_src = np.asarray(([PTS[0][0], PTS[0][1]], [PTS[3][0], PTS[3][1]],
                              [PTS[2][0], PTS[2][1]], [PTS[1][0], PTS[1][1]]),
                             "float32")

        diag = np.sqrt(((target_dim[0] / 2) * (target_dim[0] / 2)) +
                       ((target_dim[1] / 2) * (target_dim[1] / 2)))
        r = target_dim[0] / 2
        offset_diag = diag - r
        offset = np.sqrt((offset_diag * offset_diag) / 2)

        #top, right,left,bottom
        pts_dest = np.float32([[0 + offset, 0 + offset],
                               [0 + offset, target_dim[1] - offset],
                               [target_dim[1] - offset, 0 + offset],
                               [target_dim[1] - offset, target_dim[1]] - offset
                               ])
        M = cv2.getPerspectiveTransform(pts_src, pts_dest)

        px, py = Image_Tools.getIntersection(pts_src)
        pts_src_corrected, ROI_bull, ROI_center = self._correctCenterOfBull(
            BASE_IM_GRAY, BASE_IM_red, px, py, pts_src)
        return M, pts_src_corrected
示例#3
0
    def _correctCenterOfBull(self, IM_ROI_grey, IM_ROI_red, px, py,
                             src_points):
        src_points = src_points.copy()
        offset = Dartboard.ENV["BULL_CENTER_DETECTION_SIZE"]
        ROI_center = IM_ROI_grey[px - offset:px + offset,
                                 py - offset:py + offset]
        IM_ROI_red_center = IM_ROI_red[px - offset:px + offset,
                                       py - offset:py + offset]

        ROI_bull = ROI_center * IM_ROI_red_center

        im2, contours, hierarchy = cv2.findContours(ROI_bull.copy(),
                                                    cv2.RETR_LIST,
                                                    cv2.CHAIN_APPROX_SIMPLE)

        if len(contours) == 0:
            return None, None, None

        idx = Image_Tools.getMaxContourIdx(contours)
        bull_contour = contours[idx]

        M = cv2.moments(bull_contour)
        cx = int(M['m10'] / M['m00'])
        cy = int(M['m01'] / M['m00'])

        #scale back
        cx = (px - offset) + cx
        cy = (py - offset) + cy
        correction_offset_x = cx - px
        correction_offset_y = cy - py
        src_points[0, 0] += correction_offset_x
        src_points[3, 0] += correction_offset_x
        src_points[1, 1] += correction_offset_y
        src_points[2, 1] += correction_offset_y
        return src_points, ROI_bull, ROI_center
示例#4
0
 def warpWithRotation(self, IM_ROI_grey, M):
     target_dim = Dartboard.ENV['DART_BOARD_TARGET_DIMENSION']
     IM_ROI_NORMAL = cv2.warpPerspective(IM_ROI_grey, M,
                                         (target_dim[1], target_dim[1]))
     IM_ROI_ROTATED = Image_Tools.rotateImage(
         IM_ROI_NORMAL, -1 * Dartboard.ENV['DART_BOARD_TARGET_ROTATION'])
     return IM_ROI_ROTATED, IM_ROI_NORMAL
    def computeBaseFrame(self, IM, IM_GRAY):
        print("--Computing New Baseframe--")
        x, y, w, h, BOARD, GREEN, RED = self.dartboard_detector.detectDartboard(
            IM)
        self.BASE_IM = self.dartboard_detector.scaleROI(
            Image_Tools.getROI(IM, x, y, w, h))
        self.BASE_IM_GRAY = self.dartboard_detector.scaleROI(
            Image_Tools.getROI(IM_GRAY, x, y, w, h))
        self.BASE_IM_green = self.dartboard_detector.scaleROI(
            Image_Tools.getROI(GREEN, x, y, w, h))
        self.BASE_IM_red = self.dartboard_detector.scaleROI(
            Image_Tools.getROI(RED, x, y, w, h))
        self.BASE_IM_board = self.dartboard_detector.scaleROI(
            Image_Tools.getROI(BOARD, x, y, w, h))
        self.ROI_x = x
        self.ROI_y = y
        self.ROI_w = w
        self.ROI_h = h
        IM_ROI_thres_color, IM_ROI_thres_color_closed, contours_structure = self.dartboard_detector.getOrientation(
            self.BASE_IM, self.BASE_IM_board)
        #GUI.show(Image_Tools.debugContours(IM_ROI_thres_color,contours_structure),"ORIENTATION")
        self.M, src_points = self.dartboard.computePerspectiveTransformation(
            contours_structure, self.BASE_IM_GRAY, self.BASE_IM_red)

        if src_points is None:
            self.reset()
            return

        px, py = Image_Tools.getIntersection(src_points)
        if py is None:
            self.reset()
            return
        self.M_corrected = self.dartboard.computePerspectiveTransformationCorrection(
            src_points)
        self.PREVIOUS_DIFFERENCE = None
示例#6
0
    def drawDartboard(self):
        IM = np.zeros(Dartboard.ENV['DART_BOARD_TARGET_DIMENSION'], "uint8")
        offset = Dartboard.ENV['DART_BOARD_TARGET_OFFSET']
        center = (IM.shape[0] // 2, IM.shape[1] // 2)
        size_dartboard = 3400 + offset
        scale = IM.shape[0] / size_dartboard
        rad_board = int(3400 / 2 * scale)
        rad_bull = int(127 / 2 * scale)
        rad_ring = int(318 / 2 * scale)
        rad_double = int((3400 - 160) / 2 * scale)
        rad_triple = int((2140 - 160) / 2 * scale)
        width_rings = int(80 * scale)
        line_thickness = int(12 * scale)
        angle = 360 // 20
        angle_offset = 9

        #rings
        cv2.circle(IM, center, rad_bull, (255, 255, 255), line_thickness)
        cv2.circle(IM, center, rad_ring, (255, 255, 255), line_thickness)
        cv2.circle(IM, center, rad_double, (255, 255, 255), line_thickness)
        cv2.circle(IM, center, rad_double + width_rings, (255, 255, 255),
                   line_thickness)
        cv2.circle(IM, center, rad_triple, (255, 255, 255), line_thickness)
        cv2.circle(IM, center, rad_triple + width_rings, (255, 255, 255),
                   line_thickness)

        #lines
        line_shape = np.zeros(IM.shape, "uint8")
        line_shape[:, (line_shape.shape[1] // 2) -
                   line_thickness:(line_shape.shape[1] // 2) +
                   line_thickness] = 255
        IM_temp = np.zeros(IM.shape, "uint8")
        for i in range(0, 360, angle):
            line_shape_rot = Image_Tools.rotateImage(line_shape,
                                                     i + angle_offset)
            IM_temp = IM_temp + line_shape_rot

        #restore bull
        IM_mask = np.zeros(IM.shape, "uint8")
        cv2.circle(IM_mask, center, rad_board, (255, 255, 255), -1)
        cv2.circle(IM_mask, center, rad_ring, (0, 0, 0), -1)
        IM = IM + (IM_temp * IM_mask)

        #create Mask
        IM_mask = np.zeros(IM.shape, "uint8")
        cv2.circle(IM_mask, center, rad_board, (255, 255, 255), -1)

        #make color
        IM_color = np.repeat(IM[:, :, np.newaxis], 3, axis=2)
        return IM_color, IM_mask
示例#7
0
 def computeArrowOrientation(self, IM, arange, kernel):
     max_contour_length = 0
     max_angle = 0
     max_contour = 0
     max_img = 0
     for i in arange:
         kernel_rot = Image_Tools.rotateImage(kernel, i)
         closed = cv2.morphologyEx(IM, cv2.MORPH_CLOSE, kernel_rot)
         im2, contours, hierarchy = cv2.findContours(
             closed.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
         for j in range(len(contours)):
             length = cv2.arcLength(contours[j], True)
             if length > max_contour_length:
                 max_contour_length = length
                 max_angle = i
                 max_contour = contours[j]
                 max_img = closed
     return max_contour_length, max_angle, max_contour, max_img
示例#8
0
    def _detectArrowLine(self, IM_closed, max_contour, xx, yy, ww, hh):
        # Improve with fitting line
        line_image = np.zeros(IM_closed.shape, "uint8")
        line_image_peak = np.zeros(IM_closed.shape, "uint8")

        # then apply fitline() function
        [vx, vy, x, y] = cv2.fitLine(max_contour, cv2.DIST_L2, 0, 0.01, 0.01)

        # Now find two extreme points on the line to draw line
        righty = int((-x * vy / vx) + y)
        lefty = int(((line_image.shape[1] - x) * vy / vx) + y)

        #Finally draw the line
        cv2.line(line_image, (line_image.shape[1] - 1, lefty), (0, righty),
                 255, Arrow_Detector.ENV['DETECTION_APEX_LINE_THICKNESS'])
        cv2.line(line_image_peak, (line_image.shape[1] - 1, lefty),
                 (0, righty), 255,
                 Arrow_Detector.ENV['DETECTION_APEX_LINE_THICKNESS_PEAK'])

        #compute orientation
        (h, v) = self.detectArrowState(
            Image_Tools.getROI(IM_closed, xx, yy, ww, hh))
        if h == 'l':
            if v == 'u':
                arrow_x1 = xx + ww
                arrow_y1 = yy + hh
            else:
                arrow_x1 = xx + ww
                arrow_y1 = yy
        else:
            if v == 'u':
                arrow_x1 = xx
                arrow_y1 = yy + hh
            else:
                arrow_x1 = xx
                arrow_y1 = yy
        return arrow_x1, arrow_y1, line_image_peak, h, v
示例#9
0
    def _detectApex(self, IM_ROI2_grey, line_image_peak, arrow_x1, arrow_y1, h,
                    v):
        # Isolate the apex
        offset = Arrow_Detector.ENV['DETECTION_APEX_OFFSET']
        IM_ROI_APEX = IM_ROI2_grey[arrow_y1 - offset:arrow_y1 + offset,
                                   arrow_x1 - offset:arrow_x1 + offset]
        IM_ROI_LINE = line_image_peak[arrow_y1 - offset:arrow_y1 + offset,
                                      arrow_x1 - offset:arrow_x1 + offset]
        IM_ROI_APEX_edges = cv2.Canny(IM_ROI_APEX, 50, 100)
        IM_ROI_APEX_masekd = cv2.multiply(IM_ROI_LINE, IM_ROI_APEX_edges)

        #GUI.imShow(IM_ROI_APEX)
        #GUI.imShow(IM_ROI_APEX_edges)

        im2_line, contours_line, hierarchy_line = cv2.findContours(
            IM_ROI_APEX_masekd.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

        if len(contours_line) == 0:
            return None, None, None, None, None, None, None, None, None, None

        max_contour_idx = Image_Tools.getMaxContourIdx(contours_line)
        xxx, yyy, www, hhh = cv2.boundingRect(contours_line[max_contour_idx])

        #GUI.imShow(Image_Tools.debugRectangle(IM_ROI_APEX_masekd,xxx,yyy,www,hhh))
        #GUI.imShow(IM_ROI_APEX_masekd)

        IM_ROI_APEX_clipped = np.zeros(IM_ROI_APEX_masekd.shape, "uint8")
        IM_ROI_APEX_clipped[yyy:yyy + hhh,
                            xxx:xxx + www] = IM_ROI_APEX_masekd[yyy:yyy + hhh,
                                                                xxx:xxx + www]

        IM_ROI_APEX_masekd = IM_ROI_APEX_clipped
        #GUI.imShow(IM_ROI_APEX_clipped)

        # respect orientation
        y, x = np.where(IM_ROI_APEX_masekd > 1)
        np.sort(y)
        #print(h)
        #print(v)
        if h == 'l':
            if v == 'u':
                arrow_y2 = y[y.shape[0] - 1]
                x = np.where(IM_ROI_APEX_masekd[arrow_y2, :] > 1)[0]
                np.sort(x)
                arrow_x2 = x[x.shape[0] - 1]
            else:
                arrow_y2 = y[0]
                x = np.where(IM_ROI_APEX_masekd[arrow_y2, :] > 1)[0]
                arrow_x2 = x[x.shape[0] - 1]
        else:
            if v == 'u':
                arrow_y2 = y[y.shape[0] - 1]
                x = np.where(IM_ROI_APEX_masekd[arrow_y2, :] > 1)[0]
                np.sort(x)
                arrow_x2 = x[0]
                #arrow_y2 = yyy
                #arrow_x2 = xxx
            else:
                arrow_y2 = y[0]
                x = np.where(IM_ROI_APEX_masekd[arrow_y2, :] > 1)[0]
                np.sort(x)
                arrow_x2 = x[0]

        # transform to original space
        arrow_y1 = (arrow_y1 - offset) + arrow_y2
        arrow_x1 = (arrow_x1 - offset) + arrow_x2

        return arrow_x1, arrow_y1, IM_ROI_APEX
示例#10
0
    def capture(self):
        video = cv2.VideoCapture()
        if Darty.ENV['VIDEO_INPUT_PATH']:
            video = cv2.VideoCapture(Darty.ENV['VIDEO_INPUT_PATH'])

        # Fps stuff
        loop_delta = 1. / Darty.ENV['FPS_LIMIT']
        current_time = target_time = time.clock()
        frame_counter = 0

        while (True):
            # Sleep management. Limit fps.
            target_time += loop_delta
            sleep_time = target_time - time.clock()
            if sleep_time > 0:
                time.sleep(sleep_time)
                print("--FPS sleep--")

            # Loop frequency evaluation, prints actual fps
            previous_time, current_time = current_time, time.clock()
            time_delta = current_time - previous_time
            current_fps = 1. / time_delta

            #
            # Read Frame
            #
            ret, new_frame = video.read()
            #video.set(cv2.CAP_PROP_POS_FRAMES, frame_counter)
            if new_frame is None:
                print("END OF VIDEO, BREAKING")
                break  # no more frames to read

            #
            # Subsample over time
            #
            if frame_counter % Darty.ENV['FPS_SKIP'] == 0:
                print('frequency: ' + str(current_fps) + " fps_skip: " +
                      str(Darty.ENV['FPS_SKIP']))
                IM, IM_GRAY = Image_Tools.prepareImage(
                    new_frame, (Darty.ENV['RESOLUTION_WIDTH'],
                                Darty.ENV['RESOLUTION_HEIGHT']))

                #
                # Compute Base Image for the first time
                #
                #print("frame: " + str(frame_counter))
                if self.BASE_IM is None:
                    self.computeBaseFrame(IM, IM_GRAY)
                    continue

                #
                # Get ROI
                #
                IM_ROI = self.dartboard_detector.scaleROI(
                    Image_Tools.getROI(IM, self.ROI_x, self.ROI_y, self.ROI_w,
                                       self.ROI_h))
                IM_ROI_grey = self.dartboard_detector.scaleROI(
                    Image_Tools.getROI(IM_GRAY, self.ROI_x, self.ROI_y,
                                       self.ROI_w, self.ROI_h))
                GUI.show(IM, "FEED")

                #
                # Difference detection
                #
                IM_ROI_difference, IM_ROI_GRAY_NORM, IM_ROI_GRAY2_NORM, IM_ROI_GRAY_NORM_DIFF = self.difference_detector.computeDifference(
                    self.BASE_IM_GRAY, IM_ROI_grey)
                difference_sum = np.sum(IM_ROI_difference)
                if difference_sum > Darty.ENV['DIFFERENCE_THRES_RESET']:
                    self.computeBaseFrame(IM, IM_GRAY)
                    continue

                #print("Difference: " + str(difference_sum) + "px")
                if difference_sum > Darty.ENV['DIFFERENCE_THRES']:
                    #
                    # Arrow Detection
                    #
                    IM_arrow_closed, arrow_x1, arrow_y1, xx, yy, ww, hh, line_image, apex_image = self.arrow_detector.detectArrow(
                        IM_ROI_difference, IM_ROI_grey)

                    if arrow_x1 is not None:
                        IM_arrow_roi1 = self.arrow_detector.debugApex(
                            IM_ROI, arrow_x1, arrow_y1, (0, 255, 0))
                        IM_ROI_grey = self.arrow_detector.markApex(
                            IM_ROI_grey, arrow_x1, arrow_y1)

                        #
                        # Draw Dartboard
                        #
                        IM_ROI_ROTATED, IM_ROI_NORMAL = self.dartboard.warpWithRotation(
                            IM_ROI_grey, self.M_corrected)
                        cx, cy, angle, length, cross, IM_dot, IM_line = self.arrow_detector.getMetricOfArrow(
                            IM_ROI_ROTATED)

                        if cx is not None:
                            score = self.dartboard.calcScore(angle, length)
                            IM_dartboard, IM_mask = self.dartboard.drawDartboard(
                            )
                            IM_dartboard_geo, IM_dartboard_error = self.dartboard.drawFinalDartboard(
                                IM_dartboard, IM_dot, IM_ROI_ROTATED)
                            IM_score = self.dartboard.drawScore(
                                IM_dartboard_error, score)
                            GUI.show(IM_score, "DARTBOARD")
                            print("--Arrow Detected: Score was: " + str(score))
                            self.computeBaseFrame(IM, IM_GRAY)

                else:
                    if self.PREVIOUS_DIFFERENCE is None:
                        self.PREVIOUS_DIFFERENCE = IM_ROI_difference
                    else:
                        IM_ROI_difference = cv2.add(self.PREVIOUS_DIFFERENCE,
                                                    IM_ROI_difference)
                        self.PREVIOUS_DIFFERENCE = IM_ROI_difference

            cv2.waitKey(1)
            frame_counter += 1

        cv2.destroyAllWindows()