k230简单图像识别慢

Viewed 59

问题描述


帧率一般接近20,但是图像识别不稳定,识别很慢

硬件板卡


canMV-K230-LP4 V3.0

软件版本


CanMV_K230_LP4_V3.0_micropython_1.5_nncase_v2.110

其他信息


import time
import os
import sys
import math
from media.sensor import *
from media.display import *

sensor = None

1. 计算两条直线的角度差 (0~180度)

def angle_diff(a1, a2):
diff = abs(a1 - a2) % 180
return min(diff, 180 - diff)

2. 计算两条直线的几何交点

def get_line_intersection(line1, line2):
x1, y1, x2, y2 = line1.line()
x3, y3, x4, y4 = line2.line()

denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if abs(denom) < 1e-5:
    return None  # 平行线无交点

px = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denom
py = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denom
return (int(px), int(py))

3. 检查交点有效性

def is_valid_point(pt, rect, padding=12):
if not pt:
return False
rx, ry, rw, rh = rect
x, y = pt
return (rx - padding <= x <= rx + rw + padding) and (ry - padding <= y <= ry + rh + padding)

4. 计算两点间距离(边长)

def point_dist(p1, p2):
return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)

5. 计算直线中点

def get_line_midpoint(line):
x1, y1, x2, y2 = line.line()
return ((x1 + x2) / 2, (y1 + y2) / 2)

6. 从同一方向的线段中,挑选出距离最远的两条(即平行四边形相对的两条边)

def get_farthest_pair(lines_list):
if len(lines_list) < 2:
return None
max_d = -1
best_pair = None
for i in range(len(lines_list)):
for j in range(i + 1, len(lines_list)):
m1 = get_line_midpoint(lines_list[i])
m2 = get_line_midpoint(lines_list[j])
dist = math.sqrt((m1[0] - m2[0])**2 + (m1[1] - m2[1])**2)
if dist > max_d:
max_d = dist
best_pair = (lines_list[i], lines_list[j])
if max_d > 8: # 间距必须大于 8 像素
return best_pair
return None

try:
print("--- 启动高精度平行四边形识别程序 ---")
sensor = Sensor(width=320, height=320)
sensor.reset()
sensor.set_framesize(width=320, height=320)
sensor.set_pixformat(Sensor.RGB565)

Display.init(Display.LT9611, to_ide=True)
MediaManager.init()
sensor.run()

# 手机白屏黑图案专属灰度阈值
TARGET_THRESHOLD = [(0, 115)]

while True:
    os.exitpoint()
    img = sensor.snapshot(chn=CAM_CHN_ID_0)
    gray = img.to_grayscale()

    # 查找黑色色块 (兼容远距离小目标)
    blobs = gray.find_blobs(TARGET_THRESHOLD, area_threshold=80, merge=True)
    for blob in blobs:
        img.draw_rectangle(blob.rect(), color=(255, 0, 0), thickness=2)
        img.draw_cross(blob.cx(), blob.cy(), color=(255, 0, 0))

    for blob in blobs:
        area = blob.pixels()
        w, h = blob.w(), blob.h()
        perimeter = blob.perimeter()

        if w * h == 0:
            continue

        extent = area / (w * h)
        compactness = (perimeter * perimeter) / area if area > 0 else 0

        # 1. 四边形轮廓初筛 (矩形/平行四边形填充率通常在 0.30~0.95,Compactness 在 14~45)
        if (0.30 <= extent <= 0.95) and (14.0 <= compactness <= 45.0):

            # 2. 在色块区域提取直线
            raw_lines = gray.find_lines(roi=blob.rect(), threshold=300, x_stride=2, y_stride=2)

            # 3. 将直线按角度归类为 2 个主要方向组 (方向1 与 方向2 夹角大于 20 度)
            group1 = []
            group2 = []

            for l in raw_lines:
                ang = l.theta()
                if not group1:
                    group1.append(l)
                elif all(angle_diff(ang, gl.theta()) < 20 for gl in group1):
                    group1.append(l)
                elif not group2 and all(angle_diff(ang, gl.theta()) > 20 for gl in group1):
                    group2.append(l)
                elif group2 and all(angle_diff(ang, gl.theta()) < 20 for gl in group2):
                    group2.append(l)

            # 4. 从每个方向组中提取最外侧的两条对边线
            pair1 = get_farthest_pair(group1)
            pair2 = get_farthest_pair(group2)

            if pair1 and pair2:
                LA1, LA2 = pair1  # 方向 1 的两条对边
                LB1, LB2 = pair2  # 方向 2 的两条对边

                # 5. 两两求交,获得顺次连接的 4 个顶点
                p1 = get_line_intersection(LA1, LB1)
                p2 = get_line_intersection(LB1, LA2)
                p3 = get_line_intersection(LA2, LB2)
                p4 = get_line_intersection(LB2, LA1)

                # 6. 校验 4 个交点是否有效
                if (is_valid_point(p1, blob.rect()) and
                    is_valid_point(p2, blob.rect()) and
                    is_valid_point(p3, blob.rect()) and
                    is_valid_point(p4, blob.rect())):

                    # 计算 4 条边长
                    d12 = point_dist(p1, p2)
                    d23 = point_dist(p2, p3)
                    d34 = point_dist(p3, p4)
                    d41 = point_dist(p4, p1)

                    # 7. 平行四边形几何校验:对边长度必须近似相等 (误差 < 35%)
                    diff_opp1 = abs(d12 - d34) / max(d12, d34)
                    diff_opp2 = abs(d23 - d41) / max(d23, d41)

                    if diff_opp1 < 0.35 and diff_opp2 < 0.35 and min(d12, d23, d34, d41) > 5:
                        # --- 判定成功:开始绘制 ---

                        # A. 绘制 4 条绿线边框
                        img.draw_line(p1[0], p1[1], p2[0], p2[1], color=(0, 255, 0), thickness=2)
                        img.draw_line(p2[0], p2[1], p3[0], p3[1], color=(0, 255, 0), thickness=2)
                        img.draw_line(p3[0], p3[1], p4[0], p4[1], color=(0, 255, 0), thickness=2)
                        img.draw_line(p4[0], p4[1], p1[0], p1[1], color=(0, 255, 0), thickness=2)

                        # B. 绘制 4 个顶点红点
                        img.draw_circle(p1[0], p1[1], 3, color=(255, 0, 0), fill=True)
                        img.draw_circle(p2[0], p2[1], 3, color=(255, 0, 0), fill=True)
                        img.draw_circle(p3[0], p3[1], 3, color=(255, 0, 0), fill=True)
                        img.draw_circle(p4[0], p4[1], 3, color=(255, 0, 0), fill=True)

                        # C. 标注 4 条边的边长 (黄字)
                        m12 = ((p1[0] + p2[0]) // 2, (p1[1] + p2[1]) // 2)
                        m23 = ((p2[0] + p3[0]) // 2, (p2[1] + p3[1]) // 2)
                        m34 = ((p3[0] + p4[0]) // 2, (p3[1] + p4[1]) // 2)
                        m41 = ((p4[0] + p1[0]) // 2, (p4[1] + p1[1]) // 2)

                        img.draw_string(m12[0], m12[1], str(int(d12)), color=(255, 255, 0), scale=2)
                        img.draw_string(m23[0], m23[1], str(int(d23)), color=(255, 255, 0), scale=2)
                        img.draw_string(m34[0], m34[1], str(int(d34)), color=(255, 255, 0), scale=2)
                        img.draw_string(m41[0], m41[1], str(int(d41)), color=(255, 255, 0), scale=2)

                        # D. 精准计算中心坐标 (4 个顶点的中心)
                        cx = (p1[0] + p2[0] + p3[0] + p4[0]) // 4
                        cy = (p1[1] + p2[1] + p3[1] + p4[1]) // 4

                        # 中心标记:紫色十字 + 白点 + 坐标文本
                        img.draw_cross(cx, cy, color=(255, 0, 255), size=6, thickness=2)
                        img.draw_circle(cx, cy, 2, color=(255, 255, 255), fill=True)
                        img.draw_string(cx + 8, cy - 8, f"({cx},{cy})", color=(255, 255, 255), scale=1)

    img.compressed_for_ide()
    Display.show_image(img)

except Exception as e:
print("运行出错:", e)
finally:
if isinstance(sensor, Sensor):
sensor.stop()
Display.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)
MediaManager.deinit()

k230已经有cv加速的相关函数和固件了,怎么不试试,在传统识别上速度提升明显

1 Answers

你好,请升级到最新的daily build固件测试一下,以及这个代码格式请使用markdown语法正确粘贴。