2023电赛E

import time

import cv2
import numpy as np
import math
import serial


# ser = serial.Serial('/dev/ttyUSB0', 115200)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))


def emitMessage(position, _right, _up):
    ser = serial.Serial('COM5', 115200)
    # ltemp = []
    length = 3

    for i in range(length):
        p = position[i] * 100
        p = int(p)
        bp = int.to_bytes(p, 2, byteorder='little', signed=False)
        ser.write(bp)
        # ltemp.append(bp[:1])
        # ltemp.append(bp[1:])

    light_open = 1
    is_right = _right
    is_up = _up

    ser.write(bytes.fromhex(hex(light_open).lstrip("0x").zfill(2)))
    ser.write(bytes.fromhex(hex(is_right).lstrip("0x").zfill(2)))
    ser.write(bytes.fromhex(hex(is_up).lstrip("0x").zfill(2)))

    # ltemp.append(bytes.fromhex(hex(light_open).lstrip("0x").zfill(2)))
    # ltemp.append(bytes.fromhex(hex(is_right).lstrip("0x").zfill(2)))
    # ltemp.append(bytes.fromhex(hex(is_up).lstrip("0x").zfill(2)))

    # for b in ltemp:
    #     print('{:02x}'.format(b[0]), end=' ')
    # print()
    time.sleep(0.1)
    ser.close()

def detect(frame, flag):
    # 转换颜色空间为HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # 根据红色的HSV范围创建掩膜
    if flag == 'red':
        """
        lor = np.array([160, 0, 250])
    hir = np.array([180, 255, 255])
        """
        mask = cv2.inRange(hsv, np.array([160, 0, 250]),np.array([180, 255, 255]))  # 红  捕捉到了比较暗的区域
    elif flag == 'green':
        mask = cv2.inRange(hsv, np.array([80, 0, 230]), np.array([120, 255, 255]))  # 绿   还需调整
        # mask = cv2.inRange(hsv, np.array([80, 0, 200]), np.array([120, 255, 210]))  # 绿   还需调整

    mask = cv2.dilate(mask, None, iterations=5)

    # 寻找轮廓
    contours, _ = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    if len(contours) > 0:
        # 找到面积最大的轮廓
        max_contour = max(contours, key=cv2.contourArea)

        # 计算轮廓的最小外接圆
        ((x, y), radius) = cv2.minEnclosingCircle(max_contour)
        # print(x,y)
        # if x<140 or x>380 or y<210 or y>460:
        #     return -1

        # 计算轮廓的矩形边界框
        rect = cv2.minAreaRect(max_contour)
        box = cv2.boxPoints(rect)
        box = np.int0(box)

        # 绘制轮廓和边界框
        cv2.drawContours(frame, [box], 0, (0, 255, 0), 2)
        cv2.circle(frame, (int(x), int(y)), int(radius), (0, 255, 255), 2)
        cv2.putText(frame, flag, (int(x), int(y) + int(radius)), cv2.FONT_HERSHEY_SIMPLEX, 1, 1)

        # 计算中心坐标
        M = cv2.moments(max_contour)
        center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))

        # 在图像上绘制中心坐标
        cv2.circle(frame, center, 5, (0, 0, 255), -1)

        return center

next_red_center=(0,0)

def read_usb_capture():
    # 选择摄像头的编号
    cap = cv2.VideoCapture(0)  # 0是笔记本自带摄像头
    # 添加这句是可以用鼠标拖动弹出的窗体
    # cv2.namedWindow('video', cv2.WINDOW_AUTOSIZE)
    # cv2.resizeWindow("video", 640, 480)  # 设置长和宽
    # points_list = []
    flag=1
    key1 = 0
    points_list = [(0, 0) for i in range(5)]
    while (cap.isOpened()):  # 循环
        ret, frame = cap.read()  # read放回2个值,第一个是True和False 是否打开 第二个是传入图像
        frame = frame[130:390, 190:450]#上下左右
        if flag:
            box1 = lunkuo(frame)  # 每帧进行轮廓检测,更新直角点
            for i in range(len(box1)):
                points_list[i] = box1[i]
            points_list[4] = box1[0]
            flag=0

        red_center = detect(frame, 'red')
        if red_center==None:

            red_center=next_red_center

        if points_list[key1][1] - red_center[1] < 0:
            _up = 1
        else:
            _up = 0

        if points_list[key1][0] - red_center[0] < 0:
            _right = 0
        else:
            _right = 1

        if red_center == None:
            if points_list[key1][0] - red_center[0] < 0:
                red_center[0]-=1
            else:
                red_center[0] += 1
            if points_list[key1][1] - red_center[1] < 0:
                red_center[1] += 1
            else:
                red_center[1] -= 1

        dlta_x = abs(points_list[key1][1] - red_center[1])
        dlta_y = abs(points_list[key1][0] - red_center[0])

        if dlta_x > dlta_y:
            dx = min(dlta_x, 10)
            dy = dx * dlta_y / dlta_x
        else:
            dy = min(dlta_y, 10)
            dx = dy * dlta_x / dlta_y


        if math.sqrt(dlta_x ** 2 + dlta_y ** 2) < 5:
            key1 += 1
            if key1 == 5:
                break
            continue

        print(red_center)
        print(points_list[key1])

        print("dlta_x", points_list[key1][1] - red_center[1])
        print("dlta_y", points_list[key1][0] - red_center[0])
        print("dx", dx)
        print("dy", dy)
        next_red_center=(red_center[0]+dx,red_center[1]+dy)
        emitMessage((dx, dy, 1), _up, _right)

        # pt_index = (0, 1, 2, 3, 0)
        # for i in range(4):
        #     pt1 = box1[pt_index[i]]
        #     pt2 = box1[pt_index[i + 1]]
        #     cv2.line(frame, pt1, pt2, (0, 255, 0), 2)
        # cv2.imshow('video', frame)  # 显示出来

        cv2.waitKey(10)

    # 释放画面
    cap.release()
    cv2.destroyAllWindows()


def lunkuo(img):  # 检测轮廓
    img1_ = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换为灰度
    _,binary=cv2.threshold(img1_,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    kernel1 = np.ones((5, 5), np.uint8)
    erode = cv2.erode(binary, kernel1)

    # img_ = cv2.GaussianBlur(erode, (5, 5), 0)  # 高斯滤波去噪点
    # img__ = cv2.Canny(erode, 75, 200)  # Canny边缘检测

    img__ = cv2.dilate(erode, None, iterations=1)  # 扩张
    # img__ = cv2.erode(img__, None, iterations=1)  # 腐蚀

    # 轮廓检测
    contours, _ = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    print('img.shape', img.shape)
    cnt = contours[0]
    cv2.drawContours(img, [cnt], 0, (0, 255, 0), 1)
    cnt = contours[1]
    cv2.drawContours(img, [cnt], 0, (0, 0, 255), 1)

    rect1 = cv2.minAreaRect(contours[0])
    box1 = cv2.boxPoints(rect1)
    box1 = np.array(box1).astype(int)

    rect2 = cv2.minAreaRect(contours[1])
    box2 = cv2.boxPoints(rect2)
    box2 = np.array(box2).astype(int)

    box = np.mean(np.array((box1, box2)), 0)
    box = np.array(box).astype(int)

    for i in range(len(box)):
        cv2.circle(img, tuple(box1[i]), 1, (0, 255, 0), 2)
        cv2.circle(img, tuple(box2[i]), 1, (0, 0, 255), 2)
        cv2.circle(img, tuple(box[i]), 1, (0, 255, 255), 2)

    cv2.line(img, tuple(box[0]), tuple(box[1]), (0, 255, 255), 1)
    cv2.line(img, tuple(box[1]), tuple(box[2]), (0, 255, 255), 1)
    cv2.line(img, tuple(box[2]), tuple(box[3]), (0, 255, 255), 1)
    cv2.line(img, tuple(box[3]), tuple(box[0]), (0, 255, 255), 1)
    # cv2.imshow("1", img)
    # cv2.waitKey(0)

    return box

read_usb_capture()  # 开始

你可能感兴趣的:(python,开发语言)