143 lines
5.6 KiB
Python
143 lines
5.6 KiB
Python
# -*- coding:utf-8 -*-
|
||
# @Author len
|
||
# @Create 2023/11/30 11:08
|
||
|
||
import sensor, lcd, time
|
||
from machine import Timer, PWM
|
||
|
||
lcd.init(freq=15000000) # 初始化LCD
|
||
sensor.reset() # 复位和初始化摄像头
|
||
sensor.set_vflip(1) # 将摄像头设置成后置方式(所见即所得)
|
||
sensor.set_pixformat(sensor.RGB565)# 设置像素格式为彩色 RGB565
|
||
sensor.set_framesize(sensor.QVGA) # 设置帧大小为 QVGA (320x240)
|
||
sensor.set_auto_gain(False)
|
||
sensor.set_auto_whitebal(False)
|
||
sensor.set_auto_gain(0, 0)
|
||
sensor.skip_frames(time=200) # 等待设置生效
|
||
|
||
def draw_circles():
|
||
"""
|
||
检测并绘制图像中的圆形,仅在图像的右半部分进行检测,
|
||
"""
|
||
start_time = time.ticks_ms() # 记录开始时间(毫秒)
|
||
def circles_overlap(c1, c2):
|
||
"""判断两个圆是否重叠"""
|
||
dx = c1.x() - c2.x()
|
||
dy = c1.y() - c2.y()
|
||
distance = (dx**2 + dy**2)**0.5
|
||
return distance < (c1.r() + c2.r())
|
||
|
||
def merge_circles(new_circle, cache):
|
||
"""尝试合并新检测到的圆与缓存中的圆"""
|
||
for existing in cache:
|
||
if circles_overlap(new_circle, existing):
|
||
return False # 如果重叠,不加入新的圆
|
||
cache.append(new_circle) # 如果没有重叠,添加到缓存中
|
||
return True
|
||
|
||
def calculate_lab(area, img):
|
||
"""计算给定区域的平均 LAB 值"""
|
||
stats = img.get_statistics(roi=area)
|
||
return stats.l_mean(), stats.a_mean(), stats.b_mean()
|
||
|
||
def determine_color_from_lab(lab):
|
||
"""
|
||
返回最接近的颜色以及对应的距离
|
||
|
||
:param lab: (l, a, b) 三元组
|
||
:return: (closest_color, min_distance)
|
||
"""
|
||
# 你可以根据实际情况添加或修改更多预设颜色及其 LAB
|
||
predefined_colors = {
|
||
"红色": (50, 38, 1),
|
||
"黄色": (86, 2, 27),
|
||
"绿色": (75, -29, 15)
|
||
}
|
||
min_distance = float('inf')
|
||
closest_color = "灰色" # 默认或者未匹配时
|
||
|
||
# 打印一下实际检测到的LAB,便于调试
|
||
# print("检测到的LAB:", lab)
|
||
|
||
for color_name, (l_ref, a_ref, b_ref) in predefined_colors.items():
|
||
distance = ((lab[0] - l_ref) ** 2 +
|
||
(lab[1] - a_ref) ** 2 +
|
||
(lab[2] - b_ref) ** 2) ** 0.5
|
||
if distance < min_distance:
|
||
min_distance = distance
|
||
closest_color = color_name
|
||
if min_distance < 10:
|
||
print("最接近的颜色={}, 距离={:.2f}".format(closest_color, min_distance))
|
||
# print("最接近的颜色={}, 距离={:.2f}".format(closest_color, min_distance))
|
||
return closest_color, min_distance
|
||
|
||
count=0
|
||
|
||
min_color='red'
|
||
min_distance=50
|
||
while True:
|
||
img = sensor.snapshot()
|
||
# 只处理右半部分
|
||
roi = (img.width() // 2, 0, img.width() // 2, img.height())
|
||
|
||
# 在此根据整体亮度简单调参,阈值可自行调整
|
||
threshold = max(1000, min(5000, int(img.get_statistics().l_mean() * 50)))
|
||
|
||
# find_circles 参数可根据实际效果调整
|
||
circles = img.find_circles(roi=roi,
|
||
threshold=2500,
|
||
x_margin=20,
|
||
y_margin=20,
|
||
r_margin=20,
|
||
r_min=15,
|
||
r_max=30,
|
||
r_step=2)
|
||
|
||
if circles:
|
||
closest_circle = None
|
||
closest_distance = float('inf')
|
||
closest_color = "未知"
|
||
|
||
for c in circles:
|
||
area = (c.x() - c.r(), c.y() - c.r(), 2*c.r(), 2*c.r())
|
||
lab_val = calculate_lab(area, img)
|
||
color_name, distance = determine_color_from_lab(lab_val)
|
||
# 找出最小距离(与预设颜色最相似)的那个圆
|
||
if distance < closest_distance:
|
||
closest_distance = distance
|
||
closest_color = color_name
|
||
closest_circle = c
|
||
if closest_circle is None:
|
||
print('没有识别到')
|
||
continue
|
||
elif closest_distance<20:
|
||
area = (closest_circle.x() - closest_circle.r(),
|
||
closest_circle.y() - closest_circle.r(),
|
||
2*closest_circle.r(), 2*closest_circle.r())
|
||
# 画框和画圆
|
||
img.draw_rectangle(area, color=(255, 0, 0))
|
||
img.draw_circle(closest_circle.x(), closest_circle.y(), closest_circle.r(), color=(255, 0, 0))
|
||
print("最终识别到的颜色={}, 距离={:.2f}".format(closest_color, closest_distance))
|
||
min_distance=50
|
||
print("{}轮检测耗时: {} ms".format(count,time.ticks_diff(time.ticks_ms(), start_time)))
|
||
start_time = time.ticks_ms()
|
||
count+=1
|
||
|
||
else:
|
||
if closest_distance<min_distance:
|
||
min_color=closest_color
|
||
min_distance=closest_distance
|
||
if time.ticks_diff(time.ticks_ms(), start_time) > 5000:
|
||
print("最终识别到的颜色={}, 距离={:.2f}".format(min_color, min_distance))
|
||
print("{}轮检测耗时: {} ms".format(count,time.ticks_diff(time.ticks_ms(), start_time)))
|
||
start_time = time.ticks_ms()
|
||
|
||
min_distance=50
|
||
count+=1
|
||
|
||
|
||
|
||
# 主函数调用
|
||
if __name__ == "__main__":
|
||
draw_circles()
|