예제 #1
0
def _detect_CO_balls(img, balls, cue, display_list):
    PARA1 = int(float(img.shape[1]) / 640 * 15 + 0.5)
    PARA2 = int(float(img.shape[1]) / 640 * 40 + 0.5)
    p_cue_top, p_cue_bottom, cue_length = cue

    ## determine which ball is cue ball
    min_dist2cue_top = img.shape[0] + 1
    cue_ball_idx = -1
    for idx, ball in enumerate(balls):
        center, radius = ball
        dist2cue = zc.calc_triangle_area(center, p_cue_top,
                                         p_cue_bottom) * 2 / cue_length
        if dist2cue < PARA1:
            dist2cue_top = zc.euc_dist(center, p_cue_top)
            if dist2cue_top < min_dist2cue_top:
                min_dist2cue_top = dist2cue_top
                cue_ball_idx = idx
    if cue_ball_idx == -1:
        rtn_msg = {'status': 'fail', 'message': 'Cannot find cue ball'}
        return (rtn_msg, None)
    cue_ball = balls[cue_ball_idx]

    ## determine which ball is object ball
    min_dist2cue_top = img.shape[0] + 1
    object_ball_idx = -1
    for idx, ball in enumerate(balls):
        if idx == cue_ball_idx:
            continue
        center, radius = ball
        dist2cue = zc.calc_triangle_area(center, p_cue_top,
                                         p_cue_bottom) * 2 / cue_length
        if dist2cue < PARA2:
            dist2cue_top = zc.euc_dist(center, p_cue_top)
            if dist2cue_top < min_dist2cue_top:
                min_dist2cue_top = dist2cue_top
                object_ball_idx = idx
    if object_ball_idx == -1:
        rtn_msg = {'status': 'fail', 'message': 'Cannot find object ball'}
        return (rtn_msg, None)
    object_ball = balls[object_ball_idx]

    if 'CO_balls' in display_list:
        img_balls = img.copy()
        cv2.circle(img_balls, (int(cue_ball[0][0]), int(cue_ball[0][1])),
                   int(cue_ball[1]), (255, 255, 255), -1)
        cv2.circle(img_balls, (int(object_ball[0][0]), int(object_ball[0][1])),
                   int(object_ball[1]), (0, 0, 255), -1)
        zc.display_image("CO_balls",
                         img_balls,
                         resize_max=config.DISPLAY_MAX_PIXEL,
                         wait_time=config.DISPLAY_WAIT_TIME)

    rtn_msg = {'status': 'success'}
    return (rtn_msg, (cue_ball, object_ball))
예제 #2
0
def display_state(state):
    img_display = np.ones((200, 400, 3), dtype=np.uint8) * 100
    if state['is_playing']:
        cv2.putText(img_display, "Playing", (10, 50), cv2.FONT_HERSHEY_SIMPLEX,
                    1, [0, 255, 0])
        cv2.putText(img_display,
                    "The ball was last hit to %s" % state['ball_position'],
                    (10, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.8, [255, 100, 100])
        cv2.putText(img_display,
                    "Opponent is on the %s" % state['opponent_position'],
                    (10, 170), cv2.FONT_HERSHEY_SIMPLEX, 0.8, [255, 100, 100])
    else:
        cv2.putText(img_display, "Stopped", (10, 50), cv2.FONT_HERSHEY_SIMPLEX,
                    1, [0, 0, 255])

    zc.display_image('state',
                     img_display,
                     resize_max=config.DISPLAY_MAX_PIXEL,
                     wait_time=config.DISPLAY_WAIT_TIME)
예제 #3
0
def get_guidance(img, cue, CO_balls, pocket, display_list):
    PARA = int(float(img.shape[1]) / 640 * 8 + 0.5)
    rtn_msg, objects = _detect_aim_point(cue, CO_balls, pocket)
    if objects is not None:
        p_aim, p_aimed = objects
        print objects

    if rtn_msg['status'] == 'success':
        if 'all' in display_list:
            img_display = img.copy()
            # draw balls
            cue_ball, object_ball = CO_balls
            cv2.circle(img_display, (int(cue_ball[0][0]), int(cue_ball[0][1])),
                       int(cue_ball[1]), (255, 255, 255), -1)
            cv2.circle(img_display,
                       (int(object_ball[0][0]), int(object_ball[0][1])),
                       int(object_ball[1]), (0, 0, 255), -1)
            # draw cue
            p_cue_top, p_cue_bottom, _ = cue
            cv2.circle(img_display, p_cue_top, 3, (200, 0, 200), -1)
            cv2.line(img_display, p_cue_top, p_cue_bottom, (200, 0, 200), 3)
            # draw pocket
            cv2.drawContours(img_display, [cnt_pocket], 0, (255, 0, 0), -1)
            # draw aim point
            cv2.circle(img_display, (int(p_aim[0]), int(p_aim[1])), 3,
                       (0, 255, 0), -1)
            # draw aimed point
            cv2.circle(img_display, (int(p_aimed[0]), int(p_aim[1])), 3,
                       (0, 0, 0), -1)
            zc.display_image("all",
                             img_display,
                             resize_max=config.DISPLAY_MAX_PIXEL,
                             wait_time=config.DISPLAY_WAIT_TIME)

    if rtn_msg['status'] == 'success':
        if abs(p_aim[0] - p_aimed[0]) < PARA:
            return "good"
        elif p_aim[0] < p_aimed[0]:
            return "left"
        else:
            return "right"
    else:
        return None
예제 #4
0
    def _handle_img(self, img):
        if self.is_first_frame and not config.RECOGNIZE_ONLY: # do something special when the task begins
            result, img_guidance = self.task.get_first_guidance()
            zc.check_and_display('guidance', img_guidance, display_list, wait_time = config.DISPLAY_WAIT_TIME, resize_max = config.DISPLAY_MAX_PIXEL)
            self.is_first_frame = False
            result['state_index'] = 0  # first step
            return json.dumps(result)

        result = {'status' : "nothing"} # default

        stretch_ratio = float(16) / 9 * img.shape[0] / img.shape[1]
        if img.shape != (config.IMAGE_WIDTH, config.IMAGE_HEIGHT, 3):
            img = cv2.resize(img, (config.IMAGE_WIDTH, config.IMAGE_HEIGHT), interpolation = cv2.INTER_AREA)

        ## get bitmap for current image
        zc.check_and_display('input', img, display_list, wait_time = config.DISPLAY_WAIT_TIME, resize_max = config.DISPLAY_MAX_PIXEL)
        rtn_msg, bitmap = lc.process(img, stretch_ratio, display_list)
        if rtn_msg['status'] != 'success':
            print rtn_msg['message']
            if rtn_msg['message'] == "Not confident about reconstruction, maybe too much noise":
                self.counter['not_confident'] += 1
            return json.dumps(result)

        self.counter['confident'] += 1

        ## try to commit bitmap
        state_change = False
        if bm.bitmap_same(self.commited_bitmap, bitmap):
            pass
        else:
            current_time = time.time()
            if not bm.bitmap_same(self.temp_bitmap['bitmap'], bitmap):
                self.temp_bitmap['bitmap'] = bitmap
                self.temp_bitmap['first_time'] = current_time
                self.temp_bitmap['count'] = 0
                self.counter['diff_from_prev'] += 1
            else:
                self.counter['same_as_prev'] += 1
            self.temp_bitmap['count'] += 1
            if current_time - self.temp_bitmap['first_time'] > config.BM_WINDOW_MIN_TIME or self.temp_bitmap['count'] >= config.BM_WINDOW_MIN_COUNT:
                self.commited_bitmap = self.temp_bitmap['bitmap']
                state_change = True
        #print "\n\n\n\n\n%s\n\n\n\n\n" % self.counter

        bitmap = self.commited_bitmap
        if 'lego_syn' in display_list and bitmap is not None:
            img_syn = bm.bitmap2syn_img(bitmap)
            zc.display_image('lego_syn', img_syn, wait_time = config.DISPLAY_WAIT_TIME, resize_scale = 50)

        if config.RECOGNIZE_ONLY:
            return json.dumps(result)

        ## now user has done something, provide some feedback
        img_guidance = None
        if state_change:
            self.task.update_state(bitmap)
            result, img_guidance = self.task.get_guidance()

            if self.task.is_final_state():
                step_idx = len(self.task.states)
            else:
                # get current step
                step_idx = self.task.state2idx(self.task.current_state)
                # make sure step index is always -1 in case of error
                # also, differentiate from the default initial step (which we assign a step index 0)
                # from the internal step index obtained from the task (which also begins at 0) by 
                # shifting the index by 1:
                step_idx = -1 if step_idx < 0 else step_idx + 1
            result['state_index'] = step_idx

        if img_guidance is not None:
            zc.check_and_display('guidance', img_guidance, display_list, wait_time = config.DISPLAY_WAIT_TIME, resize_max = config.DISPLAY_MAX_PIXEL)

        return json.dumps(result)
예제 #5
0

# load test image
input_file = parse_arguments()
img = cv2.imread(input_file)
stretch_ratio = float(16) / 9 * img.shape[0] / img.shape[1]
if img.shape != (config.IMAGE_WIDTH, config.IMAGE_HEIGHT, 3):
    img = cv2.resize(img, (config.IMAGE_WIDTH, config.IMAGE_HEIGHT),
                     interpolation=cv2.INTER_AREA)

zc.check_and_display("input",
                     img,
                     display_list,
                     resize_max=config.DISPLAY_MAX_PIXEL,
                     wait_time=config.DISPLAY_WAIT_TIME)

# process image and get the symbolic representation
rtn_msg, bitmap = lc.process(img, stretch_ratio, display_list)
if 'lego_syn' in display_list and bitmap is not None:
    img_syn = bm.bitmap2syn_img(bitmap)
    zc.display_image('lego_syn',
                     img_syn,
                     wait_time=config.DISPLAY_WAIT_TIME,
                     resize_scale=50)

try:
    while True:
        time.sleep(1)
except KeyboardInterrupt as e:
    sys.stdout.write("user exits\n")
예제 #6
0
def find_opponent(img, img_prev, display_list):
    def draw_flow(img, flow, step=16):
        h, w = img.shape[:2]
        y, x = np.mgrid[step / 2:h:step, step / 2:w:step].reshape(2, -1)
        fx, fy = flow[y, x].T
        lines = np.vstack([x, y, x + fx, y + fy]).T.reshape(-1, 2, 2)
        lines = np.int32(lines + 0.5)
        vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
        cv2.polylines(vis, lines, 0, (0, 255, 0))
        for (x1, y1), (x2, y2) in lines:
            cv2.circle(vis, (x1, y1), 1, (0, 255, 0), -1)
        return vis

    def draw_rects(img, rects, color):
        for x1, y1, x2, y2 in rects:
            cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)

    #start_time = current_milli_time()

    ## General preparations
    if 'opponent' in display_list:
        img_opponent = img_prev.copy()
    zc.check_and_display('rotated',
                         img,
                         display_list,
                         is_resize=False,
                         wait_time=config.DISPLAY_WAIT_TIME)
    zc.check_and_display('rotated_prev',
                         img_prev,
                         display_list,
                         is_resize=False,
                         wait_time=config.DISPLAY_WAIT_TIME)
    bw = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    bw_prev = cv2.cvtColor(img_prev, cv2.COLOR_BGR2GRAY)

    # valid part of img_prev
    mask_img_prev_valid = zc.get_mask(img_prev, rtn_type="mask")
    bool_img_prev_valid = zc.shrink(mask_img_prev_valid, 15,
                                    iterations=3).astype(bool)
    bool_img_prev_invalid = np.bitwise_not(bool_img_prev_valid)
    mask_white_prev = zc.color_inrange(img_prev, 'HSV', S_U=50, V_L=130)
    bool_white_prev = zc.shrink(mask_white_prev,
                                13,
                                iterations=3,
                                method='circular').astype(bool)
    # valid part of img
    mask_img_valid = zc.get_mask(img, rtn_type="mask")
    bool_img_valid = zc.shrink(mask_img_valid, 15, iterations=3).astype(bool)
    bool_img_invalid = np.bitwise_not(bool_img_valid)
    mask_white = zc.color_inrange(img, 'HSV', S_U=50, V_L=130)
    bool_white = zc.shrink(mask_white, 13, iterations=3,
                           method='circular').astype(bool)

    # prior score according to height
    row_score, col_score = np.mgrid[0:img.shape[0], 0:img.shape[1]]
    row_score = img.shape[0] * 1.2 - row_score.astype(np.float32)

    #print "time0: %f" % (current_milli_time() - start_time)
    ## method 1: optical flow - dense
    opt_flow = np.zeros((bw.shape[0], bw.shape[1], 2), dtype=np.float32)
    opt_flow[::2, ::2, :] = cv2.calcOpticalFlowFarneback(bw_prev[::2, ::2],
                                                         bw[::2, ::2],
                                                         pyr_scale=0.5,
                                                         levels=1,
                                                         winsize=15,
                                                         iterations=3,
                                                         poly_n=7,
                                                         poly_sigma=1.5,
                                                         flags=0)
    if 'denseflow' in display_list:
        zc.display_image('denseflow',
                         draw_flow(bw, opt_flow, step=16),
                         is_resize=False,
                         wait_time=config.DISPLAY_WAIT_TIME)
    # clean optical flow
    mag_flow = np.sqrt(np.sum(np.square(opt_flow), axis=2))
    bool_flow_valid = mag_flow > 2
    bool_flow_valid = np.bitwise_and(bool_flow_valid, bool_img_prev_valid)
    bool_flow_valid = np.bitwise_and(bool_flow_valid,
                                     np.bitwise_not(bool_white_prev))
    bool_flow_invalid = np.bitwise_not(bool_flow_valid)
    # substract all the flow by flow average
    x_ave = np.mean(opt_flow[bool_flow_valid, 0])
    y_ave = np.mean(opt_flow[bool_flow_valid, 1])
    opt_flow[:, :, 0] -= x_ave
    opt_flow[:, :, 1] -= y_ave
    opt_flow[bool_flow_invalid, :] = 0
    if 'denseflow_cleaned' in display_list:
        zc.display_image('denseflow_cleaned',
                         draw_flow(bw, opt_flow, step=16),
                         is_resize=False,
                         wait_time=config.DISPLAY_WAIT_TIME)

    # give the flow a "score"
    score_flow = np.sqrt(np.sum(np.square(opt_flow), axis=2))
    score_flow = score_flow * row_score
    score_horizonal = np.sum(score_flow, axis=0)
    low_pass_h = np.ones(120)
    low_pass_h /= low_pass_h.sum()
    score_horizonal_filtered_dense = np.convolve(score_horizonal,
                                                 low_pass_h,
                                                 mode='same')
    if 'dense_hist' in display_list:
        plot_bar(score_horizonal_filtered_dense, name='dense_hist')
        print np.argmax(score_horizonal_filtered_dense)
    if 'opponent' in display_list:
        cv2.circle(img_opponent,
                   (np.argmax(score_horizonal_filtered_dense), 220), 20,
                   (0, 255, 0), -1)
    #print "time1: %f" % (current_milli_time() - start_time)

    ## method 2: optical flow - LK
    feature_params = dict(maxCorners=100,
                          qualityLevel=0.03,
                          minDistance=5,
                          blockSize=3)
    lk_params = dict(winSize=(15, 15),
                     maxLevel=2,
                     criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT,
                               10, 0.03))
    p0 = cv2.goodFeaturesToTrack(bw_prev,
                                 mask=mask_img_prev_valid,
                                 useHarrisDetector=False,
                                 **feature_params)
    if p0 is None:
        # TODO: this is also a possible indication that the rally is not on
        rtn_msg = {
            'status':
            'fail',
            'message':
            'No good featuresToTrack at all, probably no one in the scene'
        }
        return (rtn_msg, None)
    p1, st, err = cv2.calcOpticalFlowPyrLK(bw_prev, bw, p0, None, **lk_params)
    # Select good points
    good_new = p1[st == 1]
    good_old = p0[st == 1]
    # draw the tracks
    if 'LKflow' in display_list:
        img_LK = img_prev.copy()
        for i, (new, old) in enumerate(zip(good_new, good_old)):
            a, b = new.ravel()
            c, d = old.ravel()
            cv2.line(img_LK, (a, b), (c, d), (0, 255, 0), 2)
            cv2.circle(img_LK, (c, d), 5, (0, 255, 0), -1)
        zc.display_image('LKflow',
                         img_LK,
                         is_resize=False,
                         wait_time=config.DISPLAY_WAIT_TIME)
    bool_flow_valid = np.bitwise_and(bool_img_valid,
                                     np.bitwise_not(bool_white))
    bool_flow_invalid = np.bitwise_not(bool_flow_valid)
    bool_flow_valid_prev = np.bitwise_and(bool_img_prev_valid,
                                          np.bitwise_not(bool_white_prev))
    bool_flow_invalid_prev = np.bitwise_not(bool_flow_valid_prev)
    is_reallygood = np.zeros((good_new.shape[0]), dtype=bool)
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        if bool_flow_invalid_prev[d,
                                  c] or max(a, b) > config.O_IMG_HEIGHT or min(
                                      a, b) < 0 or bool_flow_invalid[b, a]:
            continue
        is_reallygood[i] = True
    reallygood_new = good_new[is_reallygood]
    reallygood_old = good_old[is_reallygood]
    motion = reallygood_new - reallygood_old
    motion_real = motion - np.mean(motion, axis=0)
    if 'LKflow_cleaned' in display_list:
        img_LK_cleaned = img_prev.copy()
        img_LK_cleaned[bool_flow_invalid_prev, :] = [0, 0, 255]
        for i, (new, old) in enumerate(zip(reallygood_new, reallygood_old)):
            c, d = old.ravel()
            cv2.line(img_LK_cleaned, (c, d),
                     (c + motion_real[i, 0], d + motion_real[i, 1]),
                     (0, 255, 0), 2)
            cv2.circle(img_LK_cleaned, (c, d), 5, (0, 255, 0), -1)
        zc.display_image('LKflow_cleaned',
                         img_LK_cleaned,
                         is_resize=False,
                         wait_time=config.DISPLAY_WAIT_TIME)
    score_flow = np.zeros(bw.shape, dtype=np.float32)
    score_flow[reallygood_old[:, 1].astype(np.int),
               reallygood_old[:, 0].astype(np.int)] = np.sqrt(
                   np.sum(np.square(motion_real), axis=1))
    score_flow = score_flow * row_score
    score_horizonal = np.sum(score_flow, axis=0)
    low_pass_h = np.ones(120)
    low_pass_h /= low_pass_h.sum()
    score_horizonal_filtered_LK = np.convolve(score_horizonal,
                                              low_pass_h,
                                              mode='same')
    if 'LK_hist' in display_list:
        plot_bar(score_horizonal_filtered_LK, name='LK_hist')
        print np.argmax(score_horizonal_filtered_LK)
    # if motion too small, probably no one is there...
    if np.max(score_horizonal_filtered_LK) < 300:
        # TODO: this is also a possible indication that the rally is not on
        rtn_msg = {
            'status': 'fail',
            'message': 'Motion too small, probably no one in the scene'
        }
        return (rtn_msg, None)
    if 'opponent' in display_list:
        cv2.circle(img_opponent, (np.argmax(score_horizonal_filtered_LK), 220),
                   20, (0, 0, 255), -1)
    #print "time2: %f" % (current_milli_time() - start_time)

    ## method 3: remove white wall
    mask_white = zc.color_inrange(img_prev, 'HSV', S_U=50, V_L=130)
    zc.check_and_display('mask_white_wall',
                         mask_white,
                         display_list,
                         resize_max=config.DISPLAY_MAX_PIXEL,
                         wait_time=config.DISPLAY_WAIT_TIME)
    score = row_score
    score[bool_img_invalid] = 0
    score[bool_white] = 0
    score_horizonal = np.sum(score, axis=0)
    low_pass_h = np.ones(120)
    low_pass_h /= low_pass_h.sum()
    score_horizonal_filtered_wall = np.convolve(score_horizonal,
                                                low_pass_h,
                                                mode='same')
    if 'wall_hist' in display_list:
        plot_bar(score_horizonal_filtered_wall, name='wall_hist')
        print np.argmax(score_horizonal_filtered_wall)
    if 'opponent' in display_list:
        cv2.circle(img_opponent,
                   (np.argmax(score_horizonal_filtered_wall), 220), 20,
                   (255, 0, 0), -1)
    #print "time3: %f" % (current_milli_time() - start_time)

    ## combining results of three methods
    #score_horizonal_filtered = score_horizonal_filtered_dense * score_horizonal_filtered_LK * score_horizonal_filtered_wall
    score_horizonal_filtered = score_horizonal_filtered_dense / 10 + score_horizonal_filtered_LK * 10
    opponent_x = np.argmax(score_horizonal_filtered)
    if 'opponent' in display_list:
        cv2.circle(img_opponent, (opponent_x, 220), 20, (200, 200, 200), -1)
        zc.check_and_display('opponent',
                             img_opponent,
                             display_list,
                             is_resize=False,
                             wait_time=config.DISPLAY_WAIT_TIME)

    rtn_msg = {'status': 'success'}
    return (rtn_msg, opponent_x)
예제 #7
0
    def _generate_guidance(self, header, state_info_str, engine_id):
        if config.RECOGNIZE_ONLY:
            return json.dumps(result)

        if self.is_first_frame:  # do something special when the task begins
            result, img_guidance = self.task.get_first_guidance()
            result['image'] = b64encode(zc.cv_image2raw(img_guidance))
            zc.check_and_display('guidance',
                                 img_guidance,
                                 display_list,
                                 wait_time=config.DISPLAY_WAIT_TIME,
                                 resize_max=config.DISPLAY_MAX_PIXEL)
            self.is_first_frame = False
            header['status'] = result.pop('status')
            result.pop('animation', None)
            return json.dumps(result)

        header['status'] = "success"
        result = {}  # default

        state_info = json.loads(state_info_str)
        if not state_info['trust']:
            header['status'] = "fail"
            return json.dumps(result)

        state = state_info['state']

        if state == "None":
            header['status'] = "nothing"
            return json.dumps(result)

        bitmap = np.array(json.loads(state))

        ## try to commit bitmap
        state_change = False
        if bm.bitmap_same(self.commited_bitmap, bitmap):
            pass
        else:
            current_time = time.time()
            if not bm.bitmap_same(self.temp_bitmap['bitmap'], bitmap):
                self.temp_bitmap['bitmap'] = bitmap
                self.temp_bitmap['first_time'] = current_time
                self.temp_bitmap['count'] = 0
            self.temp_bitmap['count'] += 1
            if current_time - self.temp_bitmap[
                    'first_time'] > config.BM_WINDOW_MIN_TIME or self.temp_bitmap[
                        'count'] >= config.BM_WINDOW_MIN_COUNT:
                self.commited_bitmap = self.temp_bitmap['bitmap']
                state_change = True

        bitmap = self.commited_bitmap
        if 'lego_syn' in display_list and bitmap is not None:
            img_syn = bm.bitmap2syn_img(bitmap)
            zc.display_image('lego_syn',
                             img_syn,
                             wait_time=config.DISPLAY_WAIT_TIME,
                             resize_scale=50)

        ## now user has done something, provide some feedback
        img_guidance = None
        if state_change:
            self.task.update_state(bitmap)
            result, img_guidance = self.task.get_guidance()
            result['image'] = b64encode(zc.cv_image2raw(img_guidance))
            header['status'] = result.pop('status')
            result.pop('animation', None)

        if img_guidance is not None:
            zc.check_and_display('guidance',
                                 img_guidance,
                                 display_list,
                                 wait_time=config.DISPLAY_WAIT_TIME,
                                 resize_max=config.DISPLAY_MAX_PIXEL)

        return json.dumps(result)
예제 #8
0
    def _handle_img(self, img):
        if self.is_first_frame and not config.RECOGNIZE_ONLY:  # do something special when the task begins
            result, img_guidance = self.task.get_first_guidance()
            zc.check_and_display('guidance',
                                 img_guidance,
                                 display_list,
                                 wait_time=config.DISPLAY_WAIT_TIME,
                                 resize_max=config.DISPLAY_MAX_PIXEL)
            result['image'] = b64encode(zc.cv_image2raw(img_guidance))
            result.pop('animation', None)
            self.is_first_frame = False
            return json.dumps(result)

        result = {'status': "nothing"}  # default

        stretch_ratio = float(16) / 9 * img.shape[0] / img.shape[1]
        if img.shape != (config.IMAGE_WIDTH, config.IMAGE_HEIGHT, 3):
            img = cv2.resize(img, (config.IMAGE_WIDTH, config.IMAGE_HEIGHT),
                             interpolation=cv2.INTER_AREA)

        ## get bitmap for current image
        zc.check_and_display('input',
                             img,
                             display_list,
                             wait_time=config.DISPLAY_WAIT_TIME,
                             resize_max=config.DISPLAY_MAX_PIXEL)
        rtn_msg, bitmap = lc.process(img, stretch_ratio, display_list)

        if gabriel.Debug.TIME_MEASUREMENT:
            result[gabriel.Protocol_measurement.
                   JSON_KEY_APP_SYMBOLIC_TIME] = time.time()

        if rtn_msg['status'] != 'success':
            print rtn_msg['message']
            if rtn_msg[
                    'message'] == "Not confident about reconstruction, maybe too much noise":
                self.counter['not_confident'] += 1
            return json.dumps(result)

        self.counter['confident'] += 1

        ## try to commit bitmap
        state_change = False
        if bm.bitmap_same(self.commited_bitmap, bitmap):
            pass
        else:
            current_time = time.time()
            if not bm.bitmap_same(self.temp_bitmap['bitmap'], bitmap):
                self.temp_bitmap['bitmap'] = bitmap
                self.temp_bitmap['first_time'] = current_time
                self.temp_bitmap['count'] = 0
                self.counter['diff_from_prev'] += 1
            else:
                self.counter['same_as_prev'] += 1
            self.temp_bitmap['count'] += 1
            if current_time - self.temp_bitmap[
                    'first_time'] > config.BM_WINDOW_MIN_TIME or self.temp_bitmap[
                        'count'] >= config.BM_WINDOW_MIN_COUNT:
                self.commited_bitmap = self.temp_bitmap['bitmap']
                state_change = True
        #print "\n\n\n\n\n%s\n\n\n\n\n" % self.counter

        bitmap = self.commited_bitmap
        if 'lego_syn' in display_list and bitmap is not None:
            img_syn = bm.bitmap2syn_img(bitmap)
            zc.display_image('lego_syn',
                             img_syn,
                             wait_time=config.DISPLAY_WAIT_TIME,
                             resize_scale=50)

        if config.RECOGNIZE_ONLY:
            return json.dumps(result)

        ## now user has done something, provide some feedback
        img_guidance = None
        if state_change:
            self.task.update_state(bitmap)
            sym_time = result[
                gabriel.Protocol_measurement.JSON_KEY_APP_SYMBOLIC_TIME]
            result, img_guidance = self.task.get_guidance()
            result[gabriel.Protocol_measurement.
                   JSON_KEY_APP_SYMBOLIC_TIME] = sym_time
            result['image'] = b64encode(zc.cv_image2raw(img_guidance))
            result.pop('animation', None)

        if img_guidance is not None:
            zc.check_and_display('guidance',
                                 img_guidance,
                                 display_list,
                                 wait_time=config.DISPLAY_WAIT_TIME,
                                 resize_max=config.DISPLAY_MAX_PIXEL)

        return json.dumps(result)
예제 #9
0
def _detect_cue(img, mask_tables, mask_balls, display_list):
    CUE_MIN_LENGTH = int(float(img.shape[1]) / 640 * 40 + 0.5)
    PARA1 = int(float(img.shape[1]) / 640 * 2 + 0.5)
    mask_blue, mask_bluer, mask_table, mask_table_fat = mask_tables

    ### edges on the table
    #img_table = np.zeros(img.shape, dtype=np.uint8)
    #img_table = cv2.bitwise_and(img, img, dst = img_table, mask = mask_table_convex)
    #bw_table = cv2.cvtColor(img_table, cv2.COLOR_BGR2GRAY)
    #edge_table = cv2.Canny(bw_table, 80, 160)
    #edge_table = zc.expand(edge_table, 2)
    #zc.check_and_display("edge_table", edge_table, display_list, resize_max = config.DISPLAY_MAX_PIXEL, wait_time = config.DISPLAY_WAIT_TIME)

    ### detect cue
    #lines = cv2.HoughLinesP(edge_table, 1, np.pi/180, 30, minLineLength = 70, maxLineGap = 3)
    #if lines is None:
    #    rtn_msg = {'status': 'fail', 'message' : 'Cannot find cue'}
    #    return (rtn_msg, None)
    #lines = lines[0]
    #if 'cue_edge' in display_list:
    #    img_cue = img.copy()
    #    for line in lines:
    #        pt1 = (line[0], line[1])
    #        pt2 = (line[2], line[3])
    #        cv2.line(img_cue, pt1, pt2, (255, 0, 255), 2)
    #    zc.check_and_display("cue_edge", img_cue, display_list, resize_max = config.DISPLAY_MAX_PIXEL, wait_time = config.DISPLAY_WAIT_TIME)

    ## interesting parts on the table (pockets, cue, hand, etc.)
    mask_table_convex, _ = zc.make_convex(mask_table.copy(),
                                          use_approxPolyDp=False)
    zc.check_and_display_mask("table_convex",
                              img,
                              mask_table_convex,
                              display_list,
                              resize_max=config.DISPLAY_MAX_PIXEL,
                              wait_time=config.DISPLAY_WAIT_TIME)
    mask_interesting = cv2.subtract(
        cv2.subtract(mask_table_convex, mask_table), mask_bluer)
    mask_interesting = cv2.subtract(mask_interesting, mask_balls)
    mask_interesting = zc.shrink(mask_interesting, PARA1)
    zc.check_and_display_mask("interesting",
                              img,
                              mask_interesting,
                              display_list,
                              resize_max=config.DISPLAY_MAX_PIXEL,
                              wait_time=config.DISPLAY_WAIT_TIME)
    # find the blob with cue (and probably hand)
    # TODO: this may be more robust with find_largest_CC function, in the case of half ball close to the bottom
    mask_cue_hand = zc.get_closest_blob(
        mask_interesting.copy(), (img.shape[0], img.shape[1] / 2),
        min_length=CUE_MIN_LENGTH,
        hierarchy_req='outer')  # cue must be close to the bottom

    ## find cue top
    p_cue_top = zc.get_edge_point(mask_cue_hand, (0, -1))
    if p_cue_top is None:
        rtn_msg = {'status': 'fail', 'message': 'Cannot find cue top'}
        return (rtn_msg, None)

    ## find cue bottom
    # the cue detected initially may not have reached the bottom of the image
    for i in xrange(10):
        mask_cue_hand = zc.expand_with_bound(mask_cue_hand,
                                             cv2.bitwise_not(mask_bluer))
    mask_cue_bottom = mask_cue_hand.copy()
    mask_cue_bottom[:-2, :] = 0
    mask_cue_bottom[:, :p_cue_top[0] - 40] = 0
    mask_cue_bottom[:, p_cue_top[0] + 40:] = 0
    nonzero = np.nonzero(mask_cue_bottom)
    if len(nonzero) < 2 or len(nonzero[0]) == 0:
        rtn_msg = {'status': 'fail', 'message': 'Cannot find cue bottom'}
        return (rtn_msg, None)
    rows, cols = nonzero
    p_cue_bottom = ((np.min(cols) + np.max(cols)) / 2, img.shape[0])

    ## cue info
    cue_length = zc.euc_dist(p_cue_top, p_cue_bottom)
    if 'cue' in display_list:
        img_cue = img.copy()
        img_cue[mask_cue_hand > 0, :] = [0, 255, 255]
        cv2.circle(img_cue, p_cue_top, 3, (255, 0, 255), -1)
        cv2.line(img_cue, p_cue_top, p_cue_bottom, (255, 0, 255), 2)
        zc.display_image("cue",
                         img_cue,
                         resize_max=config.DISPLAY_MAX_PIXEL,
                         wait_time=config.DISPLAY_WAIT_TIME)

    ## skeletonize
    #skeleton_cue_hand = zc.skeletonize(mask_cue_hand)
    rtn_msg = {'status': 'success'}
    return (rtn_msg, (p_cue_top, p_cue_bottom, cue_length))