树莓派应用--AI项目实战篇来啦-11.OpenCV定位物体的实时位置

1. 介绍

本项目通过PCA9685舵机控制模块控制二自由度舵机云台固定在零点位置,然后通OpenCV检测到黄色小熊,找到中心位置并打印出中心位置的坐标,通过双色LED灯进行指示是否检测到目标,本项目为后面二维云台追踪物体和追踪人脸提供基础,云台追踪物体就必须知道物体的中心坐标和图像坐标的相对值,然后才能控制舵机云台进行水平方问(x方向)和垂直方向(y方向)进行修正。

2.OpenCV 定位物体的实时位置

使用平移/倾斜舵机云台将对象放置在屏幕中间。对于运动的物体,我们必须实时知道对象的位置。所以必须知道对象中心的坐标。

首先,之前已经学习过识别颜色,这里我们对其进行修改以打印所建立对象的x,y坐标。

代码的"核心"是找到对象在其上画一个圆并在其中心画一个红点。

在项目中搭建一个双色LED灯模块,该双色 LED 灯连接的是GPIO管脚(GPIO19)端口上,从而可以让双色LED 灯作为提示。

3.建立电路

|--------|--------|-----------|
| 树莓派 | T 型转接板 | 双色 LED 模块 |
| * | * | G(S) |
| GPIO19 | GPIO19 | R(中间) |
| GND | GND | GND |

|------|-------|----------------|
| 树莓派 | T型转接板 | PCA9685 舵机驱动模块 |
| SCL | SCL | SCL |
| SDA | SDA | SDA |
| 3.3V | 3.3V | VCC |
| 5V | 5V | V+ |
| GND | GND | GND |

|-------------|----------------|
| 舵机 | PCA9685 舵机驱动模块 |
| 水平方向舵机(pan) | PWM0 |
| 倾斜舵机(tilt) | PWM1 |

4. 源程序代码

python 复制代码
# 载入必要的库文件
from __future__ import print_function
from gpiozero import LED
from adafruit_servokit import ServoKit
from imutils.video import VideoStream
import imutils
import time
import cv2
import os

kit = ServoKit(channels=16)

# 舵机调零
pan =  90
tilt = 60    # 往上仰,方便操作
# 初始化位置
kit.servo[0].angle=pan
kit.servo[1].angle=tilt

# LED 初始化
redLed = LED(19)

kit = ServoKit(channels=16)

# 舵机调零
pan =  90
tilt = 60    # 往上仰,方便操作
# 初始化位置
kit.servo[0].angle=pan
kit.servo[1].angle=tilt

# LED 初始化
redLed = LED(19)

import libcamera
from picamera2 import Picamera2

picamera = Picamera2()
config = picamera.create_preview_configuration(main={"format": 'RGB888', "size": (640, 480)},
                                               raw={"format": "SRGGB12", "size": (1920, 1080)})
config["transform"] = libcamera.Transform(hflip=0, vflip=1)
picamera.configure(config)
picamera.start()

time.sleep(2.0)

# 定义对象的上下边界
# 在HSV颜色空间中进行跟踪
colorLower = (3,100,100)
colorUpper = (23,255,255)


# 创建显示控件
def bgr8_to_jpeg(value, quality=75):
    return bytes(cv2.imencode('.jpg', value)[1])
    
import traitlets
import ipywidgets.widgets as widgets
from IPython.display import display
Frame = widgets.Image(format='jpeg', width=500, height=350)
display(Frame)


# 线程函数操作库
import threading # 线程
import ctypes
import inspect

# 线程结束代码
def _async_raise(tid, exctype):
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")
        
def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)

# 关闭LED灯
redLed.off()
ledOn = False

def Video_display():
    global ledOn
    # 循环的帧从视频流
    while True:
        # 从视频流中抓取下一帧,调整大小
        # 帧,并将其转换为HSV颜色空间
        frame = picamera.capture_array()
        frame = imutils.resize(frame, width=500)
        frame = imutils.rotate(frame, angle=0)
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        # 为对象颜色构造一个遮罩,然后执行
        # 一系列的膨胀和侵蚀,以消除任何小的
        # blobs left in the mask
        mask = cv2.inRange(hsv, colorLower, colorUpper)
        mask = cv2.erode(mask, None, iterations=2)
        mask = cv2.dilate(mask, None, iterations=2)

        # 找到遮罩中的轮廓并初始化
        # (x, y) center of the object
        cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]
        #cnts = cnts[0] if imutils.is_cv2() else cnts[1]
        center = None

        # 只有在找到至少一条轮廓线时才进行
        if len(cnts) > 0:
            # 在蒙版中找到最大的轮廓,然后使用
            # 它可以计算出最小的围圆
            # 重心
            c = max(cnts, key=cv2.contourArea)
            ((x, y), radius) = cv2.minEnclosingCircle(c)
            M = cv2.moments(c)
            center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))

            # 只有当半径满足最小尺寸时才进行
            if radius > 10:
                # 在框架上画圆和质心,
                # 然后更新跟踪点的列表
                cv2.circle(frame, (int(x), int(y)), int(radius),(0, 255, 255), 2)
                cv2.circle(frame, center, 5, (0, 0, 255), -1)

                # 定位舵机在圆心
                mapObjectPosition(int(x), int(y))

                # 如果led还没有打开,打开led
                if not ledOn:
                    redLed.on()
                    ledOn = True
        # 如果没有检测到球,关闭LED灯
        elif ledOn:
            redLed.off()
            ledOn = False

        # 向我们的屏幕显示框架
        Frame.value = bgr8_to_jpeg(frame) 
        time.sleep(0.01)                # 不要CPU 占用太高
    # 做点清理工作
    print("\n [INFO] Exiting Program and cleanup stuff \n")


# 开始线程
t = threading.Thread(target=Video_display)
t.setDaemon(True)
t.start()

# 结束线程
stop_thread(t)

运行程序,将在终端上看到(x,y)位置坐标,移动对象并观察坐标。将看到x从0到500(从左到右),y从0到350(从上到下)。在 JupyterLab 上实时打印出坐标信息,当识别到物体(黄色小熊)的时候,可以观察双色LBD灯的变化。

相关推荐
cooldream200918 分钟前
RDFS—RDF模型属性扩展解析
人工智能·知识图谱·知识表示
MinIO官方账号1 小时前
使用亚马逊针对 PyTorch 和 MinIO 的 S3 连接器实现可迭代式数据集
人工智能·pytorch·python
四口鲸鱼爱吃盐1 小时前
Pytorch | 利用IE-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
人工智能·pytorch·python·深度学习·计算机视觉
四口鲸鱼爱吃盐1 小时前
Pytorch | 利用EMI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
人工智能·pytorch·python
章章小鱼1 小时前
LLM预训练recipe — 摘要版
人工智能
算家云2 小时前
Stability AI 新一代AI绘画模型:StableCascade 本地部署教程
人工智能·ai作画·stable diffusion·模型构建·算家云·算力租赁·stablecascade
RacheV+TNY2642782 小时前
深度解析:电商平台API接口的安全挑战与应对策略
人工智能·python·自动化·api
学术会议2 小时前
“智能控制的新纪元:2025年机器学习与控制工程国际会议引领变革
大数据·人工智能·科技·计算机网络·机器学习·区块链
呆头鹅AI工作室2 小时前
基于特征工程(pca分析)、小波去噪以及数据增强,同时采用基于注意力机制的BiLSTM、随机森林、ARIMA模型进行序列数据预测
人工智能·深度学习·神经网络·算法·随机森林·回归
一勺汤3 小时前
YOLO11改进-注意力-引入自调制特征聚合模块SMFA
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·目标跟踪