import cv2 import numpy as np import serial from luma.core.interface.serial import i2c, spi from luma.core.render import canvas from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106 from PIL import ImageFont

颜色阈值

lower_red = np.array([0, 178, 71]) # 红色阈值下界 higher_red = np.array([56, 255, 207]) # 红色阈值上界 lower_green = np.array([86, 122, 37]) # 绿色阈值下界 higher_green = np.array([96, 255, 191]) # 绿色阈值上界 lower_white = np.array([0, 0, 221]) # 白色阈值下界 higher_white = np.array([180, 0, 255])# 白色阈值上界

初始化 OLED 屏幕

ss = i2c(port=1, address=0x3C) device = ssd1306(ss)

连接串口

ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=2)

预设信号接收标志为 False

received_signal = False

定义函数:检测红色物体

def detect_red(draw_frame): kernel = np.ones((5, 5), np.uint8) frame_hsv = cv2.cvtColor(draw_frame, cv2.COLOR_BGR2HSV)

# 颜色识别
img = cv2.inRange(frame_hsv, lower_red, higher_red)

# 膨胀操作
dilation = cv2.dilate(img, kernel, iterations=1)

# 闭操作
closing = cv2.morphologyEx(dilation, cv2.MORPH_CLOSE, kernel)

# 高斯滤波
closing = cv2.GaussianBlur(closing, (5, 5), 0)

# 边缘检测
edges = cv2.Canny(closing, 10, 20)

'''上面进行那么多操作就是为了得到更好的目标图形,具体效果因环境而异'''

# 寻找轮廓
cnts, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 判断轮廓数量也就是判断是否寻找到轮廓,如果没有找到轮廓就不继续进行操作
if len(cnts) > 0:
    # 存放轮廓面积的列表
    s = []

    # 存放最大轮廓的索引
    max_index = 0

    # 获得排序后的轮廓列表以及每个轮廓对应的外接矩形
    (cnts, boundingRects) = cv2.sortContours(cnts, cv2.SORT_DESCENDING)

    # 寻找面积最大的轮廓的索引
    for cnt in cnts:
        s.append(cv2.contourArea(cnt))

    max_index = s.index(max(s))

    # 根据面积最大轮廓的索引找到它的外接矩形的信息
    (x, y, w, h) = boundingRects[max_index]

    # 画矩形
    frame_out = cv2.rectangle(draw_frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
    center_x, center_y = (int(x + w / 2), int(y + h / 2))
    box_size = 10
    center_box = draw_frame[center_y - box_size:center_y + box_size, center_x - box_size:center_x + box_size]

    # 在屏幕上绘制矩形框
    cv2.rectangle(img, (center_x - box_size, center_y - box_size), (center_x + box_size, center_y + box_size),
                  (0, 255, 0), 2)

    red_mask = cv2.inRange(center_box, lower_red, higher_red)
    red_pixels = cv2.countNonZero(red_mask)

    data = 'red'
    ser.write(data.encode())

    with canvas(device) as draw:
        draw.rectangle(device.bounding_box, outline='white', fill='black')
        draw.text((30, 20), 'red', fill='white')

    return True

else:
    return False

定义函数:检测绿色物体

def detect_green(draw_frame): kernel = np.ones((5, 5), np.uint8) frame_hsv = cv2.cvtColor(draw_frame, cv2.COLOR_BGR2HSV)

# 颜色识别
img = cv2.inRange(frame_hsv, lower_green, higher_green)

# 膨胀操作
dilation = cv2.dilate(img, kernel, iterations=1)

# 闭操作
closing = cv2.morphologyEx(dilation, cv2.MORPH_CLOSE, kernel)

# 高斯滤波
closing = cv2.GaussianBlur(closing, (5, 5), 0)

# 边缘检测
edges = cv2.Canny(closing, 10, 20)

'''上面进行那么多操作就是为了得到更好的目标图形,具体效果因环境而异'''

# 寻找轮廓
cnts, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 判断轮廓数量也就是判断是否寻找到轮廓,如果没有找到轮廓就不继续进行操作
if len(cnts) > 0:
    # 存放轮廓面积的列表
    s = []

    # 存放最大轮廓的索引
    max_index = 0

    # 获得排序后的轮廓列表以及每个轮廓对应的外接矩形
    (cnts, boundingRects) = cv2.sortContours(cnts, cv2.SORT_DESCENDING)

    # 寻找面积最大的轮廓的索引
    for cnt in cnts:
        s.append(cv2.contourArea(cnt))

    max_index = s.index(max(s))

    # 根据面积最大轮廓的索引找到它的外接矩形的信息
    (x, y, w, h) = boundingRects[max_index]

    # 画矩形
    frame_out = cv2.rectangle(draw_frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
    center_x, center_y = (int(x + w / 2), int(y + h / 2))
    box_size = 10
    center_box = draw_frame[center_y - box_size:center_y + box_size, center_x - box_size:center_x + box_size]

    # 在屏幕上绘制矩形框
    cv2.rectangle(img, (center_x - box_size, center_y - box_size), (center_x + box_size, center_y + box_size),
                  (0, 255, 0), 2)

    green_mask = cv2.inRange(center_box, lower_green, higher_green)
    green_pixels = cv2.countNonZero(green_mask)

    data = 'green'
    ser.write(data.encode())

    with canvas(device) as draw:
        draw.rectangle(device.bounding_box, outline='white', fill='black')
        draw.text((30, 20), 'green', fill='white')

    return True

else:
    return False

定义函数:检测白色物体

def detect_white(draw_frame): kernel = np.ones((5, 5), np.uint8) frame_hsv = cv2.cvtColor(draw_frame, cv2.COLOR_BGR2HSV)

# 颜色识别
img = cv2.inRange(frame_hsv, lower_white, higher_white)

# 膨胀操作
dilation = cv2.dilate(img, kernel, iterations=1)

# 闭操作
closing = cv2.morphologyEx(dilation, cv2.MORPH_CLOSE, kernel)

# 高斯滤波
closing = cv2.GaussianBlur(closing, (5, 5), 0)

# 边缘检测
edges = cv2.Canny(closing, 10, 20)

'''上面进行那么多操作就是为了得到更好的目标图形,具体效果因环境而异'''

# 寻找轮廓
cnts, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

if len(cnts) > 0:
    # 存放轮廓面积的列表
    s = []

    # 存放最大轮廓的索引
    max_index = 0

    # 获得排序后的轮廓列表以及每个轮廓对应的外接矩形
    (cnts, boundingRects) = cv2.sortContours(cnts, cv2.SORT_DESCENDING)

    # 寻找面积最大的轮廓的索引
    for cnt in cnts:
        s.append(cv2.contourArea(cnt))

    max_index = s.index(max(s))

    # 根据面积最大轮廓的索引找到它的外接矩形的信息
    (x, y, w, h) = boundingRects[max_index]

    frame_out = cv2.rectangle(draw_frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
    center_x, center_y = (int(x + w / 2), int(y + h / 2))
    box_size = 10
    center_box = draw_frame[center_y - box_size:center_y + box_size, center_x - box_size:center_x + box_size]

    # 在屏幕上绘制矩形框
    cv2.rectangle(img, (center_x - box_size, center_y - box_size), (center_x + box_size, center_y + box_size),
                  (0, 255, 0), 2)

    white_mask = cv2.inRange(center_box, lower_white, higher_white)
    white_pixels = cv2.countNonZero(white_mask)

    data = 'white'
    ser.write(data.encode())

    with canvas(device) as draw:
        draw.rectangle(device.bounding_box, outline='white', fill='black')
        draw.text((30, 20), 'white', fill='white')

    return True

else:
    return False

打开摄像头

vc = cv2.VideoCapture(0)

while True: flag, frame = vc.read() draw_frame = frame.copy()

# 读取串口数据
data = ser.readline().decode('utf-8').strip()
if data == 'g':
    print('received_signal')
    received_signal = True

# 执行颜色检测函数
red_result = detect_red(draw_frame)
green_result = detect_green(draw_frame)
white_result = detect_white(draw_frame)

# 统计颜色像素点数量
red_pixels = 0
green_pixels = 0
white_pixels = 0
if red_result:
    red_pixels = 1  # 这里直接设置 red_pixels 为 1,因为 detect_red 函数已经计算了红色像素点
if green_result:
    green_pixels = 1  # 同理,设置 green_pixels 为 1
if white_result:
    white_pixels = 1  # 设置 white_pixels 为 1

# 判断颜色
color_name = ''
if red_pixels > white_pixels and red_pixels > green_pixels:
    color_name = 'red'
elif white_pixels > red_pixels and white_pixels > green_pixels:
    color_name = 'white'
elif green_pixels > red_pixels and green_pixels > white_pixels:
    color_name = 'green'

# 发送识别结果
if received_signal:
    if color_name:
        ser.write(color_name.encode('utf-8'))
        received_signal = False  # 处理完信号后将其重置为 False
    else:
        print('Color not recognized!')

# 显示图像
cv2.imshow('frame', frame)
cv2.waitKey(1)

释放资源

vc.release() cv2.destroyAllWindows() ser.close()

颜色识别与 OLED 显示:实时检测红色、绿色和白色物体

原文地址: https://www.cveoy.top/t/topic/nXSu 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录