def main():
    global timer
    timer = SW('timer')
    timer.start()
    nt = init_nt()
    cam = init_cv()
    loop(cam, nt)
def find_valids(img_orig, calibration, rect_cnt1, rect_cnt2):
    """
    Input: image from camera, calibration information, contours from generated rectangle
    Output:
        angle -> float, angle from camera center to target center
        validUpdate -> boolean, valid target found

    This function uses calibration information to create a mask of the target. It then
    finds valid targets comparing to the rectangle contours, calculates the angle to target center,
    and provides graphical representations for future use.
    """

    debug = calibration['debug']
    search = calibration['search']
    angle = 1000
    valid_update = False
    img_copy = np.copy(img_orig)
    lower_bound = np.array(calibration["green"]["green_lower"])
    upper_bound = np.array(calibration["green"]["green_upper"])
    if debug:
        timer_ft = SW('ft')
        timer_ft.start()
    hsv = cv2.cvtColor(img_copy, cv2.COLOR_BGR2HSV)
    if debug:
        elapsed=timer_ft.get()
        print("DEBUG: cvt took " + str(elapsed))
    if debug:
        timer_ft.start()
    mask = cv2.inRange(hsv, lower_bound, upper_bound)
    if debug:
        elapsed = timer_ft.get()
        print("DEBUG: inrange took "+ str(elapsed))
    if debug:
        timer_ft.start()
    erode_and_diliate = MI.erodeAndDilate(mask)
    if debug:
        elapsed = timer_ft.get()
        print("DEBUG: erode_and_dilate took " + str(elapsed))
    if debug:
        timer_ft.start()
    ret, mask_thresh = cv2.threshold(erode_and_diliate, 127, 255, cv2.THRESH_BINARY)
    if debug:
        elapsed = timer_ft.get()
        print("DEBUG: threshold took " + str(elapsed))
    if debug:
        time = datetime.now().strftime("%s")
        cv2.imwrite("/home/linaro/test_images/"+time+"image_orig.png", img_orig)
        cv2.imwrite("/home/linaro/test_images/"+time+"mask.png", mask)
        cv2.imwrite("/home/linaro/test_images/"+time+"erode_and_diliate.png", erode_and_diliate)
    if search:
        valid, cnt, cx, cy = VT.find_valid_target(mask_thresh, rect_cnt1, rect_cnt2)
        if valid:
            valid_update = True
            if debug:
                cx_avg = int((cx[0]+cx[1])/2)
                cy_avg = int((cy[0]+cy[1])/2)
                line_img = MI.drawLine2Target(mask_thresh, cx_avg, cy_avg)
                cv2.imwrite("/home/linaro/test_images/" + time + "target_lined.png", line_img)
            angle = IC.findAngle(img_orig, cx[0], cx[1])
    return angle, valid_update
def create_rect(debug):
    """
        Creates a rectangle and performs appropriate processing to provide a target
        returns the contour object of the rectangle
        :return the two contours of the rectangle we want to validate targets
        against (returned as a tuple)
        """
    # Draw rectangles of the retro reflective tape (Find dimensions in the game manual)
    # Camera dimensions: 320 x 240
    # Rectangle dimensions: 40 x 110
    if debug:
        timer_rect = SW('rect')
        timer_rect.start()
    width = 40
    length = 110
    img_width = 175
    img_length = 175

    top_left_x = int(img_width - width / 2)
    top_left_y = int(img_length - length / 2)
    bottom_right_x = int(img_width + width / 2)
    bottom_right_y = int(img_length + length / 2)

    background = np.zeros((350, 350, 3), np.uint8)
    rect1 = cv2.rectangle(background, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), (255, 255, 255), -1)
    m = cv2.getRotationMatrix2D((350 / 2, 350 / 2), -14.5, 1)
    rect1_rotated = cv2.warpAffine(rect1, m, (350, 350))
    ret, thresh = cv2.threshold(rect1_rotated, 127, 255, cv2.THRESH_BINARY)
    thresh = cv2.cvtColor(thresh, cv2.COLOR_BGR2GRAY)
    contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnt1 = contours[0]

    rect2 = rect1
    m = cv2.getRotationMatrix2D((350 / 2, 350 / 2), 14.5, 1)
    rect2_rotated = cv2.warpAffine(rect2, m, (350, 350))
    ret, thresh = cv2.threshold(rect2_rotated, 127, 255, cv2.THRESH_BINARY)
    thresh = cv2.cvtColor(thresh, cv2.COLOR_BGR2GRAY)
    contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnt2 = contours[0]
    if debug:
        elapsed = timer_rect.get()
        print('DEBUG: rectangles took ' + str(elapsed))
    return cnt1, cnt2
def run(cap, camera_table, calibration, freqFramesNT, rect_cnt1, rect_cnt2):
    """
    Run the main vision algorithm on each camera frame and update network table appropriately
    :param cap: cap returned from cv2.VideoCapture
    :param camera_table: the network table we are writing to
    :param calibration: dictionary containing hsv thresholds and whether we are in debug mode or not
    :param freqFramesNT: frequency of frames for data to be sent to network tables
    :param rect_cnt: contour of the rectangle we want to validate targets against
    :return: None
    """
    valid_count = 0
    n = 0
    while cap.isOpened():
        ret, frame = cap.read()
        if ret:
            try:
                if calibration['debug']:
                    timer_fv=SW('FV')
                    timer_fv.start()
                angle, valid_update = FT.find_valids(frame, calibration, rect_cnt1, rect_cnt2)
                if calibration['debug']:
                    elapsed = timer_fv.get()
                    print("DEBUG: find_valids took " + str(elapsed))
                    print("DEBUG: angle: " + str(angle) + " valid_update: " + str(valid_update) + " valid_count: " + str(valid_count) )
                if valid_update:
                    valid_count += 1
                if n > freqFramesNT:
                    nt_send(camera_table, angle, valid_count, valid_update)
                    n = 0
                else:
                    n += 1
            except:
                print("WARNING: There was an error with find_valids. Continuing.")
                continue
        else:
            print("WARNING: Unable to read frame. Continuing.")
            continue
    else:
        print("ERROR: Capture is not opened. Ending program.")
        sys.exit()
# Only works with mac and Windows 10 currently see comment on line 6 for more instructions
import cv2
import numpy as np
from util.stopwatch import stopwatch as SW

cap = cv2.VideoCapture(
    0)  # Need to change the 0 to what ever the camera devices name is
timer = SW('timer')
display = "normal"
lastk = 48

while cap.isOpened:
    k = cv2.waitKey(15) & 0xFF
    print(k)
    if k != 255:
        lastk = k
    else:
        k = lastk
    timer.start()
    ret, frame = cap.read()
    new_frame = frame
    if ret:
        print('Got a frame!!')
        frame = cv2.UMat(frame)
        display = "normal_frame"
        cv2.imshow("display", frame)
    if k == 48:
        display = "normal_frame"
        cv2.imshow("display", frame)
        fps = 1.0 / timer.get()
        print('frames per second: %.3f' % fps)
def run(cap, vision_table, calibration, freqFramesNT, desired_cnt):
    """[summary]

    Arguments:
        cap {[type]} -- [description]
        vision_table {[type]} -- [description]
        calibration {[type]} -- [description]
        freqFramesNT {[type]} -- [description]
        desired_cnt {[type]} -- [description]
    """
    valid_count = 0
    heartbeat = 0
    n = 0
    x = 0
    recent_vals = []
    while cap.isOpened():
        heartbeat += 1
        x += 1
        ret, frame = cap.read()
        if ret:
            try:
                if calibration['debug']:
                    print("DEBUG: heartbeat: " + str(heartbeat))
                    timer_fv = SW('FV')
                    timer_fv.start()
                angle, valid_update = FT.find_valids(frame, calibration,
                                                     desired_cnt)
            except Exception as e:
                print("WARNING: find_valids threw an exception: " + str(e))
                angle = 9999
                valid_update: False

            # Checking for anomalies
            if calibration['debug']:
                print("DEBUG: recent_vals: " + str(recent_vals) +
                      " last angle: " + str(angle))
            if angle != 1000 and angle != 9999:  # do not append the angle if something blew up
                recent_vals.append(angle)
            if len(
                    recent_vals
            ) > 5:  # if the length of the recent_values is larger than 5, we want to make it 5
                recent_vals.pop(0)
            if len(
                    recent_vals
            ) > 0:  # if there is no angle data, we want to NOT divide by zero
                average_angle = sum(recent_vals) / len(recent_vals)
            else:
                average_angle = 0  # set the average angle to something sane until we get some values
            if valid_update:
                valid_count += 1
            if calibration['debug']:
                elapsed = timer_fv.get()
                print("DEBUG: find_valids took " + str(elapsed))
                print("DEBUG: average_angle: " + str(average_angle) +
                      " valid_update: " + str(valid_update) +
                      " valid_count: " + str(valid_count))
            if n > freqFramesNT:
                nt_send(vision_table, average_angle, valid_count, valid_update,
                        heartbeat)
                n = 0
            else:
                n += 1

        else:
            print("WARNING: Unable to read frame. Continuing.")
            continue
    else:
        print("ERROR: Capture is not opened. Ending program.")
        sys.exit()
Beispiel #7
0
def find_valids(img_orig, calibration, desired_cnt):
    """[summary]

    Arguments:
        img_orig {[type]} -- [description]
        calibration {[type]} -- [description]
        desired_cnt {[type]} -- [description]

    Returns:
        [type] -- [description]
    """
    path = "/" + "/".join(os.getcwd().split("/")[1:3]) + "/test_images/"
    print("path: " + path)
    debug = calibration['debug']
    search = calibration['search']
    angle = 1000
    valid_update = False
    img_copy = np.copy(img_orig)
    lower_bound = np.array(calibration["green"]["green_lower"])
    upper_bound = np.array(calibration["green"]["green_upper"])
    if debug:
        timer_ft = SW('ft')
        timer_ft.start()
    hsv = cv2.cvtColor(img_copy, cv2.COLOR_BGR2HSV)
    if debug:
        elapsed = timer_ft.get()
        print("DEBUG: cvt took " + str(elapsed))
    if debug:
        timer_ft.start()
    mask = cv2.inRange(hsv, lower_bound, upper_bound)
    if debug:
        elapsed = timer_ft.get()
        print("DEBUG: inrange took " + str(elapsed))
    if debug:
        timer_ft.start()
    erode_and_diliate = MI.erodeAndDilate(mask)
    if debug:
        elapsed = timer_ft.get()
        print("DEBUG: erode_and_dilate took " + str(elapsed))
    if debug:
        timer_ft.start()
    ret, mask_thresh = cv2.threshold(erode_and_diliate, 127, 255,
                                     cv2.THRESH_BINARY)
    if debug:
        elapsed = timer_ft.get()
        print("DEBUG: threshold took " + str(elapsed))
    if debug:
        time = datetime.now().strftime("%s")
        cv2.imwrite(path + time + "_image_orig.png", img_orig)
        cv2.imwrite(path + time + "_mask.png", mask)
        cv2.imwrite(path + time + "_mask.png", mask_thresh)
        cv2.imwrite(path + time + "_erode_and_diliate.png", erode_and_diliate)
    if search:
        valid, cnt = VT.find_valid_target(mask_thresh, desired_cnt)
        if valid:
            valid_update = True
            hull = cv2.convexHull(cnt[0])
            cx, cy = IC.findCenter(hull)
            if debug:
                line_img = MI.drawLine2Target(mask_thresh, cx, cy)
                cv2.imwrite(path + time + "target_lined.png", line_img)
            angle = IC.findAngle(img_orig, cx)
    return angle, valid_update