import cv2
import numpy as np
#from imutils import contours
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 time import sleep
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])# 白色阈值上界

ss = i2c(port=1, address=0x3C)
    # 初始化设备,这里改ssd1306, ssd1325, ssd1331, sh1106
device = ssd1306(ss)
# 连接串口
ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=2)  # 连接COM14,波特率位115200


def 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) = contours.sort_contours(cnts)
        # 寻找面积最大的轮廓的索引
        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)
        #img2 = cv2.circle(frame_out, center, 3, (0, 0, 255), 5)  # 传入圆心信息,并画在原图上
        #print(center)  # 输出各个中心点
        data = 'red'
        ser.write(data.encode())
        with canvas(device) as draw:
            draw.rectangle(device.bounding_box, outline='white', fill='black')
            font = ImageFont.truetype('FreeMonoBold.ttf', 12)
            draw.text((30, 20), 'red', fill='white', font=font)
        return True
    else:
        return False

def 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) = contours.sort_contours(cnts)
        # 寻找面积最大的轮廓的索引
        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))  # 画center圆心时。x,y必须是整数
        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)
        #img2 = cv2.circle(frame_out, center, 3, (0, 255, 0), 5)  # 传入圆心信息,并画在原图上
        #print(center)  # 输出各个中心点
        data = 'green'
        ser.write(data.encode())
        with canvas(device) as draw:
            draw.rectangle(device.bounding_box, outline='white', fill='black')
            font = ImageFont.truetype('FreeMonoBold.ttf', 12)
            draw.text((30, 20), 'green', fill='white', font=font)
        return True
    else:
        return False

def 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) = contours.sort_contours(cnts)
        # 寻找面积最大的轮廓的索引
        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))  # 画center圆心时。x,y必须是整数
        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)
        #print(center)  # 输出各个中心点
        data = 'white'
        ser.write(data.encode())
        with canvas(device) as draw:
            draw.rectangle(device.bounding_box, outline='white', fill='black')
            font = ImageFont.truetype('FreeMonoBold.ttf', 12)
            draw.text((30, 20), 'white', fill='white', font=font)
        return True
    else:
        return False
# 打开摄像头

vc = cv2.VideoCapture(0)
received_signal = False
red_pixels = 0
green_pixels = 0
white_pixels = 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
    if red(draw_frame):
        red_pixels = cv2.countNonZero(red_mask)
    if green(draw_frame):
        green_pixels = cv2.countNonZero(green_mask)
    if white(draw_frame):
        white_pixels = cv2.countNonZero(white_mask)
    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)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

vc.release()
cv2.destroyAllWindows()
ser.close()
颜色识别与串口传输:基于 Python OpenCV 和 OLED 屏幕的实现

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

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