You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

基于OpenCV的Python图像处理:物体掉落检测代码求助

没问题,我来帮你搞定这个基于OpenCV的柠檬掉落检测功能!针对柠檬赛跑的场景,咱们可以通过跟踪柠檬位置与预设参考区域(勺子范围)的关系来精准判断掉落事件。下面是具体的实现思路和可运行代码:

核心思路

本质就是:先定义勺子的有效区域(柠檬应该待着的地方),然后实时检测柠檬的位置,如果柠檬的中心坐标超出这个区域,就判定为掉落。考虑到柠檬的颜色特征,用HSV颜色空间的颜色识别来定位柠檬是最直接高效的方案。

具体实现步骤
  • 第一步:获取视频流(支持摄像头实时采集或本地视频文件)
  • 第二步:手动框选勺子的参考区域(运行代码后,用鼠标拖拽框选勺子所在区域即可)
  • 第三步:对每一帧图像进行预处理,提取柠檬的黄色区域
  • 第四步:通过轮廓检测定位柠檬的中心坐标,判断是否在勺子区域内
  • 第五步:一旦检测到柠檬超出区域,立即触发掉落提示
完整代码示例
import cv2
import numpy as np

# 全局变量:存储勺子的参考区域坐标
spoon_region = None
drawing = False
ix, iy = -1, -1

# 鼠标回调函数:用于框选勺子区域
def select_region(event, x, y, flags, param):
    global ix, iy, drawing, spoon_region
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            img_copy = param.copy()
            cv2.rectangle(img_copy, (ix, iy), (x, y), (0, 255, 0), 2)
            cv2.imshow('Select Spoon Region', img_copy)
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        spoon_region = (min(ix, x), min(iy, y), abs(x - ix), abs(y - iy))
        cv2.destroyWindow('Select Spoon Region')

def main():
    # 初始化视频捕获:0为摄像头,也可以换成视频文件路径比如'lemon_race.mp4'
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        print("无法打开视频流!")
        return

    # 读取第一帧用于框选勺子区域
    ret, frame = cap.read()
    if not ret:
        print("无法读取视频帧!")
        return

    cv2.imshow('Select Spoon Region', frame)
    cv2.setMouseCallback('Select Spoon Region', select_region, frame)
    cv2.waitKey(0)

    if spoon_region is None:
        print("未选择勺子区域,程序退出!")
        return

    # 定义柠檬的HSV颜色范围(可根据实际场景调整)
    lower_yellow = np.array([20, 100, 100])
    upper_yellow = np.array([30, 255, 255])

    # 用于防抖的计数变量:连续n帧不在区域内才判定掉落
    drop_count = 0
    drop_threshold = 3

    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break

        # 转换到HSV颜色空间,提取黄色区域
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        mask = cv2.inRange(hsv, lower_yellow, upper_yellow)

        # 形态学操作去除噪声
        kernel = np.ones((5,5), np.uint8)
        mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
        mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

        # 查找轮廓,定位柠檬
        contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        lemon_detected = False
        lemon_center = None

        for cnt in contours:
            area = cv2.contourArea(cnt)
            # 过滤小轮廓,避免误判噪声
            if area > 500:
                lemon_detected = True
                # 计算柠檬的中心坐标
                M = cv2.moments(cnt)
                cx = int(M['m10']/M['m00'])
                cy = int(M['m01']/M['m00'])
                lemon_center = (cx, cy)
                # 在帧上绘制柠檬的中心和轮廓
                cv2.drawContours(frame, [cnt], -1, (0, 0, 255), 2)
                cv2.circle(frame, (cx, cy), 5, (255, 0, 0), -1)
                break

        # 绘制勺子的参考区域
        sx, sy, sw, sh = spoon_region
        cv2.rectangle(frame, (sx, sy), (sx+sw, sy+sh), (0, 255, 0), 2)

        # 判断柠檬是否掉落
        if lemon_detected:
            cx, cy = lemon_center
            # 检查柠檬中心是否在勺子区域内
            if not (sx < cx < sx+sw and sy < cy < sy+sh):
                drop_count += 1
                if drop_count >= drop_threshold:
                    cv2.putText(frame, "LEMON DROPPED!", (50, 50), 
                                cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            else:
                drop_count = 0
        else:
            # 如果连续多帧没检测到柠檬,也判定为掉落(可选逻辑)
            drop_count += 1
            if drop_count >= drop_threshold*2:
                cv2.putText(frame, "LEMON DROPPED!", (50, 50), 
                            cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

        cv2.imshow('Lemon Drop Detection', frame)

        # 按q键退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()
优化建议
  • 颜色范围调整:如果实际场景中黄色干扰多,可以用cv2.createTrackbar创建滑块来实时调整HSV的上下限,找到最适合的参数。
  • 背景减除:如果场景中有移动的背景(比如人的手),可以用cv2.createBackgroundSubtractorMOG2来去除背景,只保留运动物体,提升检测稳定性。
  • 轮廓跟踪:对于快速移动的柠檬,可以用cv2.TrackerCSRT_create()这类跟踪器,比逐帧检测轮廓更流畅。
  • 防抖机制:代码里已经加了简单的计数防抖,你可以根据实际帧率调整drop_threshold的值,避免因偶尔的帧模糊导致误判。

内容的提问来源于stack exchange,提问作者Kartikey Arora

火山引擎 最新活动