问题描述
前几天插上数据线开始时连时断,IDE上的帧缓冲区都看不了了,然后我也没在意,脱机运行看代码效果,现在链接都连不上了,看设备管理器的串口都没了(插不插TF卡两个都没了),
这种情况也出现过1,2次
,现在不管怎么折腾都连不上了,求教大佬.
另外我烧录进去过一个脱机运行的程序,现在只供电也无法运行
复现步骤
import time
import os
import sys
import math
from media.sensor import *
from media.display import *
from media.media import *
from machine import FPIOA
from machine import UART
from time import ticks_ms
sensor = None
BLACK_THRESHOLD = (0, 95)
def rectangle_score(corners, area):
"""几何校验;返回值越小越接近标准矩形,-1 表示不合格。"""
angle_error_sum = 0.0
side2 = []
for i in range(4):
p1 = corners[i]
p2 = corners[(i + 1) % 4]
dx = p2[0] - p1[0]
dy = p2[1] - p1[1]
side2.append(dx * dx + dy * dy)
if min(side2) < 20 * 20 or max(side2) > min(side2) * 25:
return -1
for i in range(4):
p0 = corners[(i - 1) % 4]
p1 = corners[i]
p2 = corners[(i + 1) % 4]
ax, ay = p0[0] - p1[0], p0[1] - p1[1]
bx, by = p2[0] - p1[0], p2[1] - p1[1]
dot = ax * bx + ay * by
cos_abs = abs(dot) / math.sqrt(max(1, side2[(i - 1) % 4] * side2[i]))
if cos_abs > 0.50: # 大约允许 60~120 度,兼顾透视形变
return -1
angle_error_sum += cos_abs
# 对角线应具有近似相同的中点,可滤除杂乱环境中的随机四边形。
mdx = corners[0][0] + corners[2][0] - corners[1][0] - corners[3][0]
mdy = corners[0][1] + corners[2][1] - corners[1][1] - corners[3][1]
if (mdx * mdx + mdy * mdy) * 100 > max(side2) * 25:
return -1
return int(angle_error_sum * 1000)
def center_black_ratio(binary_img, cx, cy, area):
"""按第一份代码检查矩形中心区域,隔点采样以降低运算量。"""
size = max(6, min(18, int(math.sqrt(area) / 18)))
half = size // 2
x0, x1 = max(0, cx - half), min(binary_img.width() - 1, cx + half)
y0, y1 = max(0, cy - half), min(binary_img.height() - 1, cy + half)
black_count = 0
total = 0
for y in range(y0, y1 + 1, 2):
for x in range(x0, x1 + 1, 2):
value = binary_img.get_pixel(x, y)
if isinstance(value, tuple):
value = value[0]
if value == 0:
black_count += 1
total += 1
return black_count * 100 // max(1, total)
try:
print("camera_test")
#配置串口,传输坐标
fpioa = FPIOA()
fpioa.set_function(5, FPIOA.UART2_TXD)
fpioa.set_function(6, FPIOA.UART2_RXD)
uart2 = UART(UART.UART2, baudrate=115200, bits=UART.EIGHTBITS, parity=UART.PARITY_NONE, stop=UART.STOPBITS_ONE)
#打开摄像头
sensor = Sensor()
sensor.reset()
# 鼠标悬停在函数上可以查看允许接收的参数
# 使用Gitee参考代码验证过的标准分辨率,避免640x640自定义尺寸
# 在OV5647/K230当前固件上导致snapshot()阻塞。
sensor.set_framesize(Sensor.QVGA)
sensor.set_pixformat(Sensor.RGB565)
Display.init(Display.ST7701, width=800, height=480, to_ide=True)
# 初始化媒体管理器
MediaManager.init()
# 启动 sensor
sensor.run()
#初始化各种参数
clock = time.clock()
stable_corner = None
stable_area = 0
lost_count = 0
max_lost_count = 1
min_rect_area = 1000
max_center_jump = 160
max_area_change_percent = 100
stable_laser = None
laser_lost_count = 0
# 小激光点有时只有1~2个有效像素,适当放宽亮度和红色分量。
max_laser_lost_count = 8
red_laser_threshold = [(15, 100, 10, 127, -30, 127)]
debug_first_frame = True
while True:
clock.tick()
os.exitpoint()
if debug_first_frame:
print("STEP 1: before snapshot")
img = sensor.snapshot(chn=CAM_CHN_ID_0)
if debug_first_frame:
print("STEP 2: snapshot ok")
rect_center_x = -1
rect_center_y = -1
laser_send_x = -1
laser_send_y = -1
# 矩形识别,可以用来找矩形的四个角的坐标
img_rect = img.to_grayscale(copy=True)
if debug_first_frame:
print("STEP 3: grayscale ok")
if debug_first_frame:
print("STEP 4: QVGA recognition image ok")
img_rect.binary([BLACK_THRESHOLD])
if debug_first_frame:
print("STEP 5: binary ok")
img_rect.dilate(1)
if debug_first_frame:
print("STEP 6: dilate ok")
rects = img_rect.find_rects(threshold=8000)
if debug_first_frame:
print("STEP 7: find_rects ok")
laser_blobs = img.find_blobs(red_laser_threshold,
pixels_threshold=1,
area_threshold=1,
merge=True)
if debug_first_frame:
print("STEP 8: find_blobs ok")
max_laser_blob = None
max_laser_pixels = 0
if laser_blobs:
for blob in laser_blobs:
# 排除大块红色物体;比赛激光点通常远小于该面积。
if blob.pixels() <= 100 and blob.pixels() > max_laser_pixels:
max_laser_pixels = blob.pixels()
max_laser_blob = blob
if max_laser_blob:
laser_lost_count = 0
laser_x = max_laser_blob.cx()
laser_y = max_laser_blob.cy()
if stable_laser == None:
stable_laser = (laser_x, laser_y)
else:
stable_laser = (
(stable_laser[0] * 6 + laser_x * 4) // 10,
(stable_laser[1] * 6 + laser_y * 4) // 10
)
elif stable_laser:
laser_lost_count += 1
if laser_lost_count > max_laser_lost_count:
stable_laser = None
max_corner = None
max_corner_area = 0
if rects:
best_score = None
for rect in rects:
raw_corner = rect.corners()
if len(raw_corner) != 4:
continue
small_corner = [(raw_corner[i][0], raw_corner[i][1]) for i in range(4)]
small_area = abs(
small_corner[0][0] * small_corner[1][1] + small_corner[1][0] * small_corner[2][1] +
small_corner[2][0] * small_corner[3][1] + small_corner[3][0] * small_corner[0][1] -
small_corner[1][0] * small_corner[0][1] - small_corner[2][0] * small_corner[1][1] -
small_corner[3][0] * small_corner[2][1] - small_corner[0][0] * small_corner[3][1]
) // 2
if small_area < min_rect_area:
continue
geometry = rectangle_score(small_corner, small_area)
if geometry < 0:
continue
small_cx = sum(p[0] for p in small_corner) // 4
small_cy = sum(p[1] for p in small_corner) // 4
black_ratio = center_black_ratio(img_rect, small_cx, small_cy, small_area)
if black_ratio < 25:
continue
# QVGA识别与显示使用同一坐标系,无需二次映射。
corner = small_corner
area = small_area
candidate_cx = small_cx
candidate_cy = small_cy
if stable_corner and stable_area > 0:
rect_center_x = candidate_cx
rect_center_y = candidate_cy
stable_center_x = (stable_corner[0][0] + stable_corner[1][0] + stable_corner[2][0] + stable_corner[3][0]) // 4
stable_center_y = (stable_corner[0][1] + stable_corner[1][1] + stable_corner[2][1] + stable_corner[3][1]) // 4
center_dx = rect_center_x - stable_center_x
center_dy = rect_center_y - stable_center_y
if center_dx * center_dx + center_dy * center_dy > max_center_jump * max_center_jump:
continue
if abs(area - stable_area) * 100 > stable_area * max_area_change_percent:
continue
geometry += (center_dx * center_dx + center_dy * center_dy) // 20
# 与第一份代码一致,优先选择较小的合格内框;几何误差和
# 上一帧距离用于避免杂乱背景中的小矩形抢占目标。
score = geometry + small_area // 50
if best_score is None or score < best_score:
best_score = score
max_corner_area = area
max_corner = corner
if max_corner:
lost_count = 0
if stable_corner == None:
stable_corner = max_corner
stable_area = max_corner_area
else:
old_cx = sum(p[0] for p in stable_corner) // 4
old_cy = sum(p[1] for p in stable_corner) // 4
new_cx = sum(p[0] for p in max_corner) // 4
new_cy = sum(p[1] for p in max_corner) // 4
move2 = (new_cx - old_cx) ** 2 + (new_cy - old_cy) ** 2
if move2 > 40 * 40:
new_weight = 9
elif move2 > 15 * 15:
new_weight = 7
else:
new_weight = 5
old_weight = 10 - new_weight
for i in range(4):
stable_corner[i] = (
(stable_corner[i][0] * old_weight + max_corner[i][0] * new_weight) // 10,
(stable_corner[i][1] * old_weight + max_corner[i][1] * new_weight) // 10
)
stable_area = (stable_area * old_weight + max_corner_area * new_weight) // 10
elif stable_corner:
lost_count += 1
if lost_count > max_lost_count:
stable_corner = None
stable_area = 0
if stable_corner:
corner = stable_corner
img.draw_line(corner[0][0], corner[0][1], corner[1][0], corner[1][1], color=(0, 255, 0), thickness=5)
img.draw_line(corner[2][0], corner[2][1], corner[1][0], corner[1][1], color=(0, 255, 0), thickness=5)
img.draw_line(corner[2][0], corner[2][1], corner[3][0], corner[3][1], color=(0, 255, 0), thickness=5)
img.draw_line(corner[0][0], corner[0][1], corner[3][0], corner[3][1], color=(0, 255, 0), thickness=5)
center_x = (corner[0][0] + corner[1][0] + corner[2][0] + corner[3][0]) // 4
center_y = (corner[0][1] + corner[1][1] + corner[2][1] + corner[3][1]) // 4
rect_center_x = center_x
rect_center_y = center_y
label_x = min(corner[0][0], corner[1][0], corner[2][0], corner[3][0])
label_y = min(corner[0][1], corner[1][1], corner[2][1], corner[3][1])
img.draw_circle(center_x, center_y, 3, color=(255, 0, 0), thickness=1, fill=True)
img.draw_string_advanced(label_x, label_y, 12, "({}, {})".format(center_x, center_y), color=(255, 0, 0))
if stable_laser:
laser_send_x = stable_laser[0]
laser_send_y = stable_laser[1]
img.draw_circle(stable_laser[0], stable_laser[1], 3, color=(0, 255, 0), thickness=1, fill=True)
img.draw_cross(stable_laser[0], stable_laser[1], color=(0, 255, 0), size=6, thickness=1)
img.draw_string_advanced(stable_laser[0] + 5, stable_laser[1] - 14, 12, "({}, {})".format(stable_laser[0], stable_laser[1]), color=(0, 255, 0))
uart2.write("R,{},{},L,{},{}\n".format(rect_center_x, rect_center_y, laser_send_x, laser_send_y))
img.draw_string_advanced(5, 5, 16, "fps: {:.1f}".format(clock.fps()), color=(255, 0, 0))
# 当前K230固件应每帧完成IDE压缩,否则首帧可能无法正常刷新。
img.compressed_for_ide()
if debug_first_frame:
print("STEP 9: compress ok")
Display.show_image(img, x=(800-320)//2, y=(480-240)//2)
if debug_first_frame:
print("STEP 10: display ok")
debug_first_frame = False
except KeyboardInterrupt as e:
print("用户停止: ", e)
except BaseException as e:
print(f"异常: {e}")
finally:
if isinstance(sensor, Sensor):
sensor.stop()
Display.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)
MediaManager.deinit()
硬件板卡
创博乐CanMVK230LP4V3.0
其他信息
镜像CanMV_K230_V3P0_micropython_v1.3-0-g8dd764f_nncase_v2.9.0
IEDcanmv-ide-4.0.7
