欢迎光临
我们一直在努力

什么是识别阈现在我们要做一下2024年电子设计大赛E题三子棋,我们采用的方案是用两个步进电机来当移动棋子的工具,我们还采用了opmv和stm32f103c8t6通信,然后我们采用的是红色棋盘,黑色棋子和白色棋子,我们的红色阈值是red_board_threshold = (71, 51, 24, 58, -69

<think>好的,我现在需要帮用户解决关于2024年电子设计大赛E题三子棋项目的视觉模块代码问题。用户需要完整的基于OpenMV的代码,包括红色棋盘识别、黑白棋子检测,以及与STM32的通信。首先,我得回顾用户提供的引用内容,确保代码符合这些要求。

首先,用户提到的引用[1]关于颜色阈值的设置,需要注意阈值参数的结构。用户明确给出了红色棋盘的阈值red_board_threshold = (71, 51, 24, 58, -69, 67),所以这部分需要直接应用。同时,引用提到可以处理多个颜色,这里需要检测黑色和白色棋子,可能需要分别设置阈值。但用户提到黑色用叉号,白色用圆圈,可能需要不同的识别方式,比如形状检测而不是颜色阈值?

然后,引用[2]中提到sensor.set_vflip(True)的设置,用户可能摄像头是倒置安装的,所以代码中必须包含这一行,否则图像方向可能不对,影响后续处理。此外,通信协议部分需要注意,用户希望串口输出棋盘状态,可能需要特定的格式,比如3×3的矩阵。

引用[3]是关于步进电机的控制,但用户当前的请求主要集中在视觉模块,所以这部分可能暂时不需要处理,但可能需要确保串口通信的格式与STM32端兼容。

接下来,用户的需求是完整的视觉模块代码,包括红色棋盘检测、黑白棋子识别,并通过串口输出。需要明确各部分如何实现:

1. 红色棋盘检测:使用给定的阈值,可能需要先找到红色区域,然后定位棋盘的位置。可能需要边缘检测或霍夫变换来找到棋盘网格。

2. 黑白棋子识别:黑色和白色可能在颜色空间上有明显差异,但用户提到黑色用叉号,白色用圆圈,这可能意味着需要形状识别。例如,通过检测圆形或交叉线来判断棋子类型。不过,用户提供的引用[1]中提到了颜色阈值,可能需要结合颜色和形状。比如,白色棋子可能颜色较亮,黑色较暗,同时形状不同。

不过,用户提到“黑色和白色棋子检测”,可能更倾向于颜色阈值。但OpenMV的颜色检测在黑白情况下可能不够准确,可能需要调整阈值,或者使用灰度阈值。或者,可能需要通过亮度来区分,比如白色棋子亮度高,黑色低。

另外,棋盘是红色的,需要先排除棋盘的颜色干扰,只检测棋子。可能需要先分割棋盘区域,再在每个格子中检测棋子。

需要结构化的代码:

– 初始化摄像头,设置像素格式、帧大小,启用垂直翻转。
– 定义颜色阈值,包括红色棋盘、黑色和白色棋子。
– 主循环中捕获图像,进行棋盘检测,找到网格位置。
– 对每个网格区域进行棋子检测,判断是黑色、白色或空。
– 将棋盘状态通过串口发送给STM32。

关于棋盘检测,可能需要先找到红色区域,然后在该区域内寻找棋盘网格线。或者,使用霍夫直线检测来找到网格线,再计算出每个格子的位置。

棋子检测方面,每个格子中是否有棋子,以及棋子的类型。如果黑色用叉号,可能需要检测交叉线,而白色用圆圈,检测圆形。这可能需要使用find_lines和find_circles的方法。但这也可能比较复杂,尤其是在棋盘格线存在的情况下。或者,使用颜色阈值,例如黑色棋子的颜色阈值和白色棋子的颜色阈值,结合区域内的blob检测。

需要处理的问题包括:

1. 棋盘定位:确保准确找到每个格子的坐标,以便分割区域。
2. 棋子识别:区分黑色和白色,可能需要不同的阈值或形状检测。
3. 串口通信:输出3×3的矩阵,比如0表示空,1表示黑,2表示白。

可能的实现步骤:

1. 初始化摄像头和串口。
2. 检测红色棋盘区域,找到四个角点,进行透视变换,校正棋盘为规整的3×3网格。
3. 将校正后的图像分割为9个格子。
4. 在每个格子中,检测是否存在黑色或白色棋子。可能使用颜色阈值或形状检测。
5. 生成棋盘状态数组,通过串口发送。

但用户提供的示例代码中使用了霍夫直线检测来找到网格点,可能不需要透视变换,而是通过直线交点确定格子位置。这可能更简单,但需要处理可能的视角变形。

需要结合用户之前提供的代码,比如detect_chessboard函数,返回9个关键点,然后根据这些点分割每个格子。

在棋子识别部分,用户之前的代码使用了颜色blob检测,但现在需要区分黑色和白色。可能需要设置两个颜色阈值,或者在灰度图像中进行阈值处理。

例如,白色棋子可能在灰度图像中亮度较高,使用阈值(200, 255),而黑色棋子阈值(0, 50)。或者,使用LAB颜色空间的L通道来区分亮度。

同时,用户提到黑色用叉号,白色用圆圈,可能需要同时检测形状。例如,在棋子所在的blob区域内,检测是否有圆形或交叉线。这可能需要结合多种检测方法。

但考虑到处理速度和实时性,可能优先使用颜色阈值来区分黑白,形状检测可能会增加计算量。因此,可能需要先通过颜色阈值确定棋子存在,再根据形状确认类型,或者直接通过颜色区分。

如果黑白棋子颜色差异明显,可能直接通过颜色阈值即可区分。例如,白色棋子的LAB值中L较高,而黑色较低。需要用户提供具体的阈值,但用户只给出了红色棋盘的阈值,所以可能需要建议用户进行阈值标定。

不过,用户明确要求使用红色棋盘阈值,而黑白棋子的检测可能需要另外的阈值。因此,代码中需要定义例如black_threshold和white_threshold,并在每个格子中搜索对应的blob。

可能的代码结构:

– 定义红色棋盘阈值,用于定位棋盘。
– 定义黑色和白色棋子的阈值。
– 检测红色区域,找到棋盘角点或网格线交点,分割出9个格子。
– 对每个格子,分别检测是否有黑色或白色blob,记录状态。
– 输出3×3矩阵到串口。

需要处理棋盘检测的稳定性,可能需要在检测到棋盘后,保存网格坐标,避免每帧重新检测,除非棋盘移动了。或者每隔一定帧数重新检测棋盘位置,如用户之前的代码示例所示。

在通信方面,输出格式可能需要是类似“1,0,2,0,1,0,0,0,2”这样的字符串,表示3×3的状态,或者每行三个数字,方便STM32解析。

此外,需要考虑OpenMV的处理速度,可能需要降低分辨率,设置ROI,或调整帧率,以确保实时性。

可能的错误点:

1. 棋盘检测不准确,导致格子坐标错误。
2. 颜色阈值不合适,导致棋子误检或漏检。
3. 串口通信格式不匹配,导致STM32无法正确解析。

需要测试每个部分,例如显示检测到的网格点和棋子位置,进行调试。

总结步骤:

1. 初始化摄像头和串口,设置垂直翻转。
2. 定义颜色阈值。
3. 检测棋盘网格,获取9个格子的坐标。
4. 对每个格子,检测黑色和白色棋子。
5. 生成棋盘状态数组。
6. 通过串口发送状态。

现在需要将这些步骤转化为代码,结合用户提供的引用和之前的示例。</think>以下是根据您需求优化的完整视觉模块代码,整合了棋盘检测、棋子识别、坐标映射与串口通信功能:

“`python
# 三子棋视觉系统完整代码(OpenMV4 H7)
# 版本:v2.1 2024电赛优化版
import sensor, image, time, math, pyb

# 硬件初始化 ======================================================
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA) # 160×120分辨率
sensor.set_vflip(True) # 摄像头倒置安装时需启用[^2]
sensor.set_hmirror(True)
sensor.skip_frames(time=2000)
clock = time.clock()

# 颜色阈值配置(实验室环境需重新标定)===============================
red_board_threshold = (71, 51, 24, 58, -69, 67) # 红色棋盘阈值
white_threshold = (70, 100, -10, 10, -10, 10) # 白色棋子(LAB)
black_threshold = (0, 40, -10, 10, -10, 10) # 黑色棋子(LAB)

# 通信配置 ========================================================
uart = pyb.UART(3, 115200, timeout_char=1000) # 与STM32通信

# 棋盘参数 ========================================================
GRID_SIZE = 3
last_grid = None # 缓存上次检测的网格坐标

def find_chessboard(img):
global last_grid
# 检测红色棋盘区域
red_blobs = img.find_blobs([red_board_threshold],
area_threshold=1000,
merge=True, margin=10)

if red_blobs:
largest_blob = max(red_blobs, key=lambda b: b.area())
img.draw_rectangle(largest_blob.rect(), color=(0,255,0))

# 提取棋盘ROI区域
roi = (largest_blob.x()-10, largest_blob.y()-10,
largest_blob.w()+20, largest_blob.h()+20)

# 霍夫变换检测直线
lines = img.find_lines(roi=roi, threshold=1000,
theta_margin=25, rho_margin=25)

# 筛选水平/垂直线
h_lines = [l for l in lines if abs(l.theta()) < 5]
v_lines = [l for l in lines if abs(l.theta()-90) < 5]

# 计算网格交点
grid_points = []
for h in h_lines[:3]: # 取前3条水平线
for v in v_lines[:3]: # 取前3条垂直线
x = (v.rho() – h.rho()*math.cos(v.theta())) / math.sin(v.theta())
y = h.rho()
grid_points.append((int(x), int(y)))

# 按坐标排序得到3×3网格
grid_points.sort(key=lambda p: (p[1]//40, p[0]))
last_grid = grid_points[:9] if len(grid_points)>=9 else last_grid
return last_grid

def detect_pieces(img, grid):
board = [[0]*GRID_SIZE for _ in range(GRID_SIZE)]
if not grid:
return board

# 计算每个格子中心区域
cell_w = (grid[2][0] – grid[0][0])//2
cell_h = (grid[6][1] – grid[0][1])//2

for i in range(GRID_SIZE):
for j in range(GRID_SIZE):
# 获取当前格子中心坐标
cx = grid[i*3 + j][0] + cell_w
cy = grid[i*3 + j][1] + cell_h

# 创建检测ROI(20×20像素)
roi = (cx-10, cy-10, 20, 20)

# 检测白色棋子(圆形特征)
white = img.find_blobs([white_threshold],
roi=roi,
merge=True,
pixels_threshold=30)
if white:
img.draw_circle(cx, cy, 8, color=(255,255,255))
board[i][j] = 2 # 白棋标记
continue

# 检测黑色棋子(叉号特征)
black = img.find_blobs([black_threshold],
roi=roi,
merge=True,
pixels_threshold=30)
if black:
# 交叉线检测
lines = img.find_lines(roi=roi,
threshold=500,
theta_margin=25,
rho_margin=25)
if len(lines) >= 2:
img.draw_cross(cx, cy, color=(0,0,0), size=15)
board[i][j] = 1 # 黑棋标记
return board

# 主循环 ========================================================
while True:
clock.tick()
img = sensor.snapshot()

# 每30帧更新棋盘定位(降低计算负载)
if pyb.millis() % 300 == 0:
grid = find_chessboard(img)

# 实时棋子检测
if grid:
# 绘制棋盘参考线
for p in grid:
img.draw_circle(p[0], p[1], 2, color=(0,255,0))

# 获取棋盘状态
board_state = detect_pieces(img, grid)

# 生成通信协议数据
state_str = ‘,’.join([str(cell) for row in board_state for cell in row])
uart.write("BOARD:" + state_str + "
") # 示例输出:BOARD:0,1,2,0,2,1,1,0,0

# 调试信息显示
img.draw_string(5,5, "FPS:%.1f" % clock.fps(), color=(255,0,0))
“`

赞(0)
未经允许不得转载:上海聚慕医疗器械有限公司 » 什么是识别阈现在我们要做一下2024年电子设计大赛E题三子棋,我们采用的方案是用两个步进电机来当移动棋子的工具,我们还采用了opmv和stm32f103c8t6通信,然后我们采用的是红色棋盘,黑色棋子和白色棋子,我们的红色阈值是red_board_threshold = (71, 51, 24, 58, -69

登录

找回密码

注册