重现步骤
期待结果和实际结果
软硬件版本信息
8.1最新版的固件库,嘉立创K230
import time, os, sys, gc
from machine import Pin
from media.sensor import * # 摄像头接口 / Camera interface
from media.display import * # 显示接口 / Display interface
from media.media import * # 媒体资源管理器 / Media manager
from machine import UART
from machine import FPIOA
import _thread
import cv_lite # cv_lite扩展模块 / cv_lite extension module
import ulab.numpy as np
import math
image_shape = [480, 800]
sensor = Sensor(id=2, width=1280, height=720,fps=90)
sensor.reset()
sensor.set_framesize(width=image_shape[1], height=image_shape[0])
sensor.set_pixformat(Sensor.RGB888)
#Display.init(Display.VIRT, width=image_shape[1], height=image_shape[0], to_ide=True, quality=50)
Display.init(Display.ST7701, width=800, height=480, to_ide=True,osd_num=2)
# -------------------------------
# 初始化媒体资源管理器并启动摄像头 / Init media manager and start camera
# -------------------------------
MediaManager.init()
sensor.run()
# 创建FPIOA对象,用于初始化引脚功能配置
fpioa = FPIOA()
# 设置引脚功能,将指定的引脚配置为普通GPIO功能
fpioa.set_function(53, FPIOA.GPIO53)
# 按键引脚为53,按下时高电平,设置为输入模式
button = Pin(53, Pin.IN, Pin.PULL_DOWN) # 使用下拉电阻
# -------------------------------
# 启动帧率计时器 / Start FPS timer
# -------------------------------
clock = time.clock()
# 相机参数
FOCAL_LENGTH_MM = 3.0 # 焦距3.0mm
SENSOR_WIDTH_MM = 4.8 # 假设传感器宽度4.8mm (典型值)
IMAGE_WIDTH_PIXELS = image_shape[1] # 图像宽度(像素)
# 计算焦距的像素当量
focal_length_pixels = (FOCAL_LENGTH_MM * IMAGE_WIDTH_PIXELS) / SENSOR_WIDTH_MM
# 矩形实际物理尺寸
ACTUAL_WIDTH_MM = 210.0 # 实际宽度(毫米)
ACTUAL_HEIGHT_MM = 297.0 # 实际高度(毫米)
def detect_corners(cor_img):
if rect_w<cor_img.width() and rect_h<cor_img.height() and rect_w%8==0 and rect_h%8==0:
cor_img = cor_img.copy(roi=(rect_x,rect_y,rect_w,rect_h))
else:
cor_img=cor_img
cor_img_shape=[cor_img.height(), cor_img.width()]
cor_img_np = cor_img.to_numpy_ref() # 获取 GRAYSCALE ndarray 引用 / Get GRAYSCALE ndarray reference
max_corners = 20 # 最大角点数 / Maximum number of corners
quality_level = 0.3 # Shi-Tomasi质量因子 / Corner quality factor (0.01 ~ 0.1)
min_distance = 8.0 # 最小角点距离 / Minimum distance between corners
corners = cv_lite.grayscale_find_corners(
cor_img_shape, cor_img_np,
max_corners,
quality_level,
min_distance
)
# 遍历角点数组,绘制角点 / Draw detected corners
for i in range(0, len(corners), 2):
x = corners[i]
y = corners[i + 1]
img_cut.draw_circle(x+rect_x, y+rect_y, 3, color=(255, 255, 255), fill=True)
Display.show_image(cor_img, x=int((800-img.width())/2),y=int((480-img.height())/2),layer=Display.LAYER_OSD2)
def find_target_rectangle(img_):
"""在图像中查找矩形目标并返回边界框尺寸(返回面积最大的矩形)"""
# 查找矩形
binary=img_.binary([(0, 74)])
img_.gaussian(1)
edge=img_.laplacian(1,mul=0.2) # 拉普拉斯边缘检测,窗口大小为 3
edge.binary([(0, 5)])
rects = edge.find_rects(threshold=1000)
max_area = 0
target_rect = None
for rect in rects:
w = rect.w()
h = rect.h()
# 过滤小区域
if w < 40 or h < 50:
continue
# 计算宽高比 (210/297 ≈ 0.707)
aspect_ratio = min(w, h) / max(w, h)
if 0.6 < aspect_ratio < 0.8:
# 计算当前矩形面积
area = w * h
# 更新最大面积矩形
if area > max_area:
max_area = area
target_rect = rect
return target_rect
def calculate_distance(rect):
"""
根据检测到的矩形计算到目标的距离
参数:
rect - 检测到的矩形对象
返回:
距离(毫米), 如果矩形无效返回0
"""
if rect is None:
return 0
w = rect.w()
h = rect.h()
# 过滤无效尺寸
if w <= 0 or h <= 0:
return 0
# 计算距离(使用宽度和高度分别计算后取平均)
distance_width = (ACTUAL_WIDTH_MM * focal_length_pixels) / w
distance_height = (ACTUAL_HEIGHT_MM * focal_length_pixels) / h
return (distance_width + distance_height) / 2.0
while True:
clock.tick()
# 拍摄当前帧图像 / Capture current frame
img = sensor.snapshot()
img.histeq()
img_cut=img.copy(roi=(240,0,296,480))
img_gray=img.copy(roi=(240,0,296,480))
img_gray=img_gray.to_grayscale()
rect = find_target_rectangle(img_gray)
if rect:
# 获取矩形属性
x = rect.x()
y = rect.y()
w = rect.w()
h = rect.h()
# 裁剪矩形内部区域
rect_offset = 0.1 # 边界偏移比例
rect_x = max(0, int(x + w * rect_offset))
rect_y = max(0, int(y + h * rect_offset))
rect_w = max(8, int(w * (1 - 2 * rect_offset)))
rect_h = max(8, int(h * (1 - 2 * rect_offset)))
if ((rect_w+7)//8)*8!=0 or((rect_h+7)//8)*80:
rect_w = ((rect_w+7)//8)*8
rect_h = ((rect_h+7)//8)*8
detect_corners(img_gray)
else:
rect_w = 160
rect_h = 160
corner=rect.corners()
"""
img_cut.draw_line(corner[0][0], corner[0][1], corner[1][0], corner[1][1], color=(0, 255, 0), thickness=1)
img_cut.draw_line(corner[2][0], corner[2][1], corner[1][0], corner[1][1], color=(0, 255, 0), thickness=1)
img_cut.draw_line(corner[2][0], corner[2][1], corner[3][0], corner[3][1], color=(0, 255, 0), thickness=1)
img_cut.draw_line(corner[0][0], corner[0][1], corner[3][0], corner[3][1], color=(0, 255, 0), thickness=1)
"""
# 在图像上绘制矩形
img_cut.draw_rectangle(x, y, w, h, color=(0, 0, 255), thickness=2)
print(w,h,calculate_distance(rect))
# 显示图像 / Display image with corners
Display.show_image(img, layer=Display.LAYER_OSD0)
Display.show_image(img_cut,x=800-img_gray.width(),layer=Display.LAYER_OSD1)
# 进行垃圾回收 / Perform garbage collection
gc.collect()
# -------------------------------
# 退出时释放资源 / Cleanup on exit
# -------------------------------
sensor.stop()
Display.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)
MediaManager.deinit()
错误日志
尝试解决过程
补充材料