2024年电赛E题-opencv图像处理部分

代码包括了棋盘与棋子的识别,初始十颗棋子的坐标标定以及棋子移动后的棋子跟踪,写的着急,有些过于冗余,当然我是选择了一个比较难的方案,就是将十字滑台放在棋盘下面,通过磁吸拖着棋子移动,路径规划部分在封箱前一小时还在挣扎,基本思路没错,调整bug的时间几乎是没有的,结果就是只能做好一题,后面的题目都需要路径规划。。。

时间短,只写了三天,没写注释,看不懂就请教GPT吧。

import cv2
import numpy as np
import heapq

img_height = 0
img_width = 0

chessNum = [[2, 2, 2],
            [2, 2, 2],
            [2, 2, 2]]

NUM = [[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]]

grid_centers = [[(0, 0), (0, 0), (0, 0)],
                [(0, 0), (0, 0), (0, 0)],
                [(0, 0), (0, 0), (0, 0)]]

grid_coord = [[(0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)],
              [(0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)],
              [(0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0)]]

white_chess_center = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
black_chess_center = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]

white_chess_center_fixed = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
black_chess_center_fixed = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]

white_chess_center_fixed_temp = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
black_chess_center_fixed_temp = [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]

path_chess_num = [[2, 2, 2, 2, 2, 2, 2],
                  [2, 0, 2, 2, 2, 0, 2],
                  [2, 0, 2, 2, 2, 0, 2],
                  [2, 0, 2, 2, 2, 0, 2],
                  [2, 2, 2, 2, 2, 2, 2]]

path_chess_num_centers = [[(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
                          [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
                          [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
                          [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],
                          [(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]]

chess_init = 0
check_init = 0

move_path = []
move_path_temp = []

outer_rect = []
board_size = 0

nextstep = 99

cap = cv2.VideoCapture(0)


def path_design(nextstep, blacknum, white_num):
    directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    path_chess_num = [[2, 2, 2, 2, 2, 2, 2],
                      [2, 0, 2, 2, 2, 0, 2],
                      [2, 0, 2, 2, 2, 0, 2],
                      [2, 0, 2, 2, 2, 0, 2],
                      [2, 2, 2, 2, 2, 2, 2]]

    for _ in range(3):
        for __ in range(3):
            path_chess_num[1 + _][2 + __] = chessNum[_][__]

    for i in range(3):
        for j in range(3):
            path_chess_num_centers[1 + i][2 + j] = grid_centers[i][j]

    for i in range(5):
        centerblack = black_chess_center_fixed[i]
        centerw = white_chess_center_fixed[i]

        path_chess_num_centers[i][0] = 0, centerblack[0]
        path_chess_num_centers[i][6] = centerw[0], img_height // 5 * 3

    for i in range(3):
        center_up = grid_centers[1][i]
        center_down = grid_centers[2][i]

        path_chess_num_centers[0][2 + i] = img_height // 5 * 3, center_up[1]
        path_chess_num_centers[4][2 + i] = img_height // 5 * 3, center_down[1]

    path_chess_num_centers[0][1] = 150, 0
    path_chess_num_centers[4][1] = 150, img_height // 5 * 3

    path_chess_num_centers[0][5] = img_width // 5 * 3 - 150, 0
    path_chess_num_centers[4][5] = img_width // 5 * 3 - 150, img_height // 5 * 3

    if blacknum != 0 and white_num == 0:
        if blacknum == 1:
            start = (0, 0)
        elif blacknum == 2:
            start = (0, 1)
        elif blacknum == 3:
            start = (0, 2)
        elif blacknum == 4:
            start = (0, 3)
        elif blacknum == 5:
            start = (0, 4)

    elif blacknum == 0 and white_num != 0:
        if white_num == 1:
            start = (6, 0)
        elif white_num == 2:
            start = (6, 1)
        elif white_num == 3:
            start = (6, 2)
        elif white_num == 4:
            start = (6, 3)
        elif white_num == 5:
            start = (6, 4)

    if nextstep == 1:
        goal = (1, 2)
    elif nextstep == 2:
        goal = (1, 3)
    elif nextstep == 3:
        goal = (1, 4)
    elif nextstep == 4:
        goal = (2, 2)
    elif nextstep == 5:
        goal = (2, 3)
    elif nextstep == 6:
        goal = (2, 4)
    elif nextstep == 7:
        goal = (3, 2)
    elif nextstep == 8:
        goal = (3, 3)
    elif nextstep == 9:
        goal = (3, 4)

    def is_valid(x, y):
        return 0 <= x < 5 and 0 <= y < 7 and path_chess_num[x][y] == 2

    def heuristic(a, b):
        return abs(a[0] - b[0]) + abs(a[1] - b[1])

    def a_star(start, goal):
        open_set = []
        heapq.heappush(open_set, (0 + heuristic(start, goal), 0, start))
        came_from = {}
        g_score = {start: 0}
        f_score = {start: heuristic(start, goal)}

        while open_set:
            _, current_g, current = heapq.heappop(open_set)

            if current == goal:
                path = []
                while current in came_from:
                    path.append(current)
                    current = came_from[current]
                path.append(start)
                return path[::-1]

            for direction in directions:
                neighbor = (current[0] + direction[0], current[1] + direction[1])
                if not is_valid(neighbor[0], neighbor[1]):
                    continue

                tentative_g_score = g_score[current] + 1
                if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
                    came_from[neighbor] = current
                    g_score[neighbor] = tentative_g_score
                    f_score[neighbor] = tentative_g_score + heuristic(neighbor, goal)
                    heapq.heappush(open_set, (f_score[neighbor], tentative_g_score, neighbor))
        return None

    paths = a_star(start, goal)

    itemp = 0
    if paths != None:
        for i in range(len(paths)):
            if itemp == 0 and blacknum != 0 and white_num == 0:
                if blacknum == 1:
                    move_path_temp.append(black_chess_center_fixed[0])
                    itemp += 1

                elif blacknum == 2:
                    move_path_temp.append(black_chess_center_fixed[1])
                    itemp += 1

                elif blacknum == 3:
                    move_path_temp.append(black_chess_center_fixed[2])
                    itemp += 1

                elif blacknum == 4:
                    move_path_temp.append(black_chess_center_fixed[3])
                    itemp += 1

                elif blacknum == 5:
                    move_path_temp.append(black_chess_center_fixed[4])
                    itemp += 1

            elif itemp == 0 and blacknum == 0 and white_num != 0:
                if white_num == 1:
                    move_path_temp.append(white_chess_center_fixed[0])
                    itemp += 1

                elif white_num == 2:
                    move_path_temp.append(white_chess_center_fixed[1])
                    itemp += 1

                elif white_num == 3:
                    move_path_temp.append(white_chess_center_fixed[2])
                    itemp += 1

                elif white_num == 4:
                    move_path_temp.append(white_chess_center_fixed[3])
                    itemp += 1

                elif white_num == 5:
                    move_path_temp.append(white_chess_center_fixed[4])
                    itemp += 1

            x, y = paths[i]
            center = path_chess_num_centers[x][y]
            move_path_temp.append(center)

    move_path = move_path_temp
    print(move_path)

    for i in range(len(move_path_temp)):
        move_path_temp.pop()

    return move_path


def are_circles_similar(c1, c2):
    x1, y1, r1 = c1
    x2, y2, r2 = c2
    distance = np.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
    return distance < (r1 + r2) / 2


def detect_color_in_circle(frame, circle):
    x, y, r = circle
    mask = np.zeros_like(frame[:, :, 0], dtype=np.uint8)
    cv2.circle(mask, (x, y), r, (255), -1)
    masked_img = cv2.bitwise_and(frame, frame, mask=mask)
    hsv_img = cv2.cvtColor(masked_img, cv2.COLOR_BGR2HSV)
    mean_color = cv2.mean(hsv_img, mask=mask)
    h, s, v = mean_color[0:3]
    if s < 60 and v > 170:
        return 1
    else:
        return 0


def detect_board_chess(frame):
    global chess_init, white_chess_center, black_chess_center, check_init, grid_coord, grid_centers, NUM, chessNum, black_chess_center_fixed, white_chess_center_fixed, black_chess_center_fixed_temp, white_chess_center_fixed_temp
    rectangles = []

    if check_init == 0:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        blurred = cv2.GaussianBlur(gray, (5, 5), 0)
        edges = cv2.Canny(blurred, 50, 150, apertureSize=3)
        contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        if len(contours) == 0:
            return frame

        for contour in contours:
            if 4000 < cv2.contourArea(contour) < 60000:
                rect = cv2.minAreaRect(contour)
                box = cv2.boxPoints(rect)
                box = box.astype(int)
                _, (width, height), _ = rect

                if 80 < width < 200 and 80 < height < 200:
                    duplicate = False
                    for existing_box, _ in rectangles:
                        if cv2.pointPolygonTest(existing_box, rect[0], False) >= 0:
                            duplicate = True
                            break
                    if not duplicate:
                        rectangles.append((box, rect))

        if len(rectangles) != 9:
            return frame

        rectangles = sorted(rectangles, key=lambda r: r[1][0][1])
        rows = [sorted(rectangles[i:i + 3], key=lambda r: r[1][0][0]) for i in range(0, 9, 3)]

        for i, row in enumerate(rows):
            for j, (box, rect) in enumerate(row):
                center = (int(rect[0][0]), int(rect[0][1]))
                x, y, w, h = cv2.boundingRect(box)
                grid_coord[i][j] = box
                grid_centers[i][j] = center

        check_init += 1

    if chess_init == 0:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        blurred = cv2.GaussianBlur(gray, (9, 9), 2)
        circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, dp=1.2, minDist=20, param1=50, param2=40,
                                   minRadius=10, maxRadius=50)

        if circles is not None:
            circles = np.round(circles[0, :]).astype("int")
            unique_circles = []

            for circle in circles:
                is_unique = True
                for u_circle in unique_circles:
                    if are_circles_similar(circle, u_circle):
                        is_unique = False
                        break
                if is_unique:
                    unique_circles.append(circle)

            unique_circles = unique_circles[:10]

            black_chess_num = 0
            white_chess_num = 0

            for (x, y, r) in unique_circles:
                color = detect_color_in_circle(frame, (x, y, r))
                if color == 0:
                    if black_chess_num <= 4:
                        black_chess_num += 1
                        black_chess_center_fixed_temp[black_chess_num - 1] = (x, y)
                    else:
                        black_chess_num = 0

                elif color == 1:
                    if white_chess_num <= 4:
                        white_chess_num += 1
                        white_chess_center_fixed_temp[white_chess_num - 1] = (x, y)
                    else:
                        white_chess_num = 0
        if black_chess_num == 5 and white_chess_num == 5:
            black_chess_center_fixed = sorted(black_chess_center_fixed_temp, key=lambda piece: piece[1])
            white_chess_center_fixed = sorted(white_chess_center_fixed_temp, key=lambda piece: piece[1])
            chess_init += 1

    if check_init == 1:
        for i in range(3):
            for j in range(3):
                box = grid_coord[i][j]
                center = grid_centers[i][j]
                cv2.drawContours(frame, [box], 0, (0, 255, 0), 2)
                cv2.putText(frame, str(NUM[i][j]), center, cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA)

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (9, 9), 2)
    circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, dp=1.2, minDist=20, param1=50, param2=40,
                               minRadius=10, maxRadius=50)

    if circles is not None:
        circles = np.round(circles[0, :]).astype("int")
        unique_circles = []

        for circle in circles:
            is_unique = True
            for u_circle in unique_circles:
                if are_circles_similar(circle, u_circle):
                    is_unique = False
                    break
            if is_unique:
                unique_circles.append(circle)

        unique_circles = unique_circles[:10]

        black_chess_num = 0
        white_chess_num = 0

        for (x, y, r) in unique_circles:
            color = detect_color_in_circle(frame, (x, y, r))
            if color == 0:
                if black_chess_num <= 4:
                    black_chess_num += 1
                    black_chess_center[black_chess_num - 1] = (x, y)


            elif color == 1:
                if white_chess_num <= 4:
                    white_chess_num += 1
                    white_chess_center[white_chess_num - 1] = (x, y)

    if black_chess_num == 5 and white_chess_num == 5:
        for i in range(3):
            for j in range(3):
                if chessNum[i][j] == 0:
                    for (x, y) in black_chess_center:
                        gx, gy = grid_centers[i][j]
                        distance = np.sqrt((x - gx) ** 2 + (y - gy) ** 2)
                        if distance > 50:
                            chessNum[i][j] = 2

                elif chessNum[i][j] == 1:
                    for (x, y) in white_chess_center:
                        gx, gy = grid_centers[i][j]
                        distance = np.sqrt((x - gx) ** 2 + (y - gy) ** 2)
                        if distance > 50:
                            chessNum[i][j] = 2

        for _ in range(5):
            bx, by = black_chess_center[_]
            cv2.circle(frame, (bx, by), 10, (0, 0, 255), -1)
            for i in range(3):
                for j in range(3):
                    gx, gy = grid_centers[i][j]

                    if np.sqrt((bx - gx) ** 2 + (by - gy) ** 2) < 50:
                        chessNum[i][j] = 0

            wx, wy = white_chess_center[_]
            cv2.circle(frame, (wx, wy), 10, (0, 0, 255), -1)
            for i in range(3):
                for j in range(3):
                    gx, gy = grid_centers[i][j]
                    if np.sqrt((wx - gx) ** 2 + (wy - gy) ** 2) < 50:
                        chessNum[i][j] = 1
    return frame


def main():
    global cap, board_size
    while True:
        ret, frame = cap.read()
        if not ret:
            break

        img_height, img_width = frame.shape[:2]
        x, y, w, h = img_width // 5, img_height // 5, img_width // 5 * 3, img_height // 5 * 3

        roi = frame[y:y + h, x:x + w]
        roi_frame = detect_board_chess(roi)

        cv2.imshow('roi_frame', roi_frame)

        x, y, w, h = grid_coord[0][0]
        board_size = w * h

        # print(chessNum)
        # print(w)
        # print(grid_centers[1][1])

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()


if __name__ == "__main__":
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值