检测接近的物体

时间:2014-06-24 06:09:58

标签: python c++ opencv object-detection

我阅读了this博客文章,他使用激光和网络摄像头来估算纸板与网络摄像头的距离。

我对此有另一个想法。我不想计算与网络摄像头的距离。

我想检查对象是否正在接近网络摄像头。根据我的说法,算法将是:

  1. 检测网络摄像头Feed中的对象。
  2. 如果对象接近网络摄像头,它将在视频输入中变得越来越大。
  3. 使用此数据进行进一步计算。
  4. 由于我想检测随机对象,我使用findContours()方法查找视频Feed中的轮廓。使用它,我至少会在视频源中包含对象的轮廓。源代码是:

    import numpy as np
    import cv2
    
    vid=cv2.VideoCapture(0)
    ans, instant=vid.read()
    average=np.float32(instant)
    cv2.accumulateWeighted(instant, average, 0.01)
    background=cv2.convertScaleAbs(average)
    
    while(1):
        _,f=vid.read()
        imgray=cv2.cvtColor(f, cv2.COLOR_BGR2GRAY)
        ret, thresh=cv2.threshold(imgray,127,255,0)
        diff=cv2.absdiff(f, background)
        cv2.imshow("input", f)
        cv2.imshow("Difference", diff)
        if cv2.waitKey(5)==27:
            break
    cv2.destroyAllWindows()
    

    输出结果为:

    enter image description here

    我被困在这里。我将轮廓存储在一个数组中。当尺寸增加时我该怎么办?我该怎么办?

2 个答案:

答案 0 :(得分:3)

这里遇到的一个问题是识别并区分移动对象与视频源中的其他内容。一种方法可能是让相机“学习”没有物体的背景。然后,您可以不断地将其输入与此背景进行比较。获得背景的一种方法是使用平均运行。

任何大于小阈值的差异都意味着存在移动物体。如果你经常显示这种差异,你基本上有一个运动跟踪器。对象的大小只是所有非零(阈值)像素或其边界矩形的总和。您可以跟踪此大小并使用它来猜测对象是移动得更近还是更远。形态学操作可以帮助将轮廓分组成一个有凝聚力的对象。

由于它将跟踪任何移动,如果有两个对象,它们将被计算在一起。您可以在此处使用轮廓来查找和跟踪单个对象,例如使用轮廓边界或质心。你也可以用颜色分开它们。

以下是使用此策略的一些结果(灰色斑点是我的手):

My hand moving towards the camera

My hand moving away from the camera

它实际上做得很好,可以猜测我的手在哪个方向移动。

代码:

import cv2
import numpy as np

AVERAGE_ALPHA      = 0.2         # 0-1 where 0 never adapts, and 1 instantly adapts
MOVEMENT_THRESHOLD = 30          # Lower values pick up more movement
REDUCED_SIZE       = (400, 600)
MORPH_KERNEL       = np.ones((10, 10), np.uint8)

def reduce_image(input_image):
    """Make the image easier to deal with."""
    reduced = cv2.resize(input_image, REDUCED_SIZE) 
    reduced = cv2.cvtColor(reduced, cv2.COLOR_BGR2GRAY)
    return reduced

# Initialise
vid = cv2.VideoCapture(0)
average = None

old_sizes = np.zeros(20)
size_update_index = 0

while (True):
    got_frame, frame = vid.read()

    if got_frame:
        # Reduce image
        reduced = reduce_image(frame)
        if average is None: average = np.float32(reduced)

        # Get background
        cv2.accumulateWeighted(reduced, average, AVERAGE_ALPHA) 
        background = cv2.convertScaleAbs(average)

        # Get thresholded difference image
        movement     = cv2.absdiff(reduced, background)
        _, threshold = cv2.threshold(movement, MOVEMENT_THRESHOLD, 255, cv2.THRESH_BINARY)

        # Apply morphology to help find object
        dilated = cv2.dilate(threshold, MORPH_KERNEL, iterations=10)
        closed  = cv2.morphologyEx(dilated, cv2.MORPH_CLOSE, MORPH_KERNEL)

        # Get contours
        contours, _ = cv2.findContours(closed, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        cv2.drawContours(closed, contours, -1, (150, 150, 150), -1)

        # Find biggest bounding rectangle
        areas = [cv2.contourArea(c) for c in contours]
        if (areas != list()):
            max_index = np.argmax(areas)
            max_cont  = contours[max_index]

            x, y, w, h = cv2.boundingRect(max_cont)
            cv2.rectangle(closed, (x, y), (x+w, y+h), (255, 255, 255), 5)

            # Guess movement direction
            size = w*h
            if size > old_sizes.mean():
                print "Towards"
            else:
                print "Away"

            # Update object size 
            old_sizes[size_update_index] = size
            size_update_index += 1
            if (size_update_index) >= len(old_sizes): size_update_index = 0

        # Display image
        cv2.imshow('RaptorVision', closed)

显然,在识别,选择和跟踪物体等方面需要做更多的工作(如果在背景中有其他东西移动的话,它会非常可怕)。还有许多参数可以改变和调整(那些设置适用于我的系统)。我会把它留给你。

一些链接:

background extraction

motion tracking

如果你想通过删除背景获得更多高科技,请看一下:

wallflower

答案 1 :(得分:1)

Detect the object in the webcam feed.
If the object is approaching the webcam it'll grow larger and larger in the video feed.
Use this data for further calculations.

好主意。 如果要使用轮廓检测​​方法,可以通过以下方式进行:

  1. 你有一系列的图像I1,I2,...在
  2. 对每一个进行轮廓检测。 C1,C2,...,Cn(轮廓是OpenCV中的一组点)
  3. 在Image i和i + 1上取足够大的样本:S_i \ leq C_i,i \ in 1 ... n
  4. 检查样品中i + 1上最近点的所有点。然后你就可以找到你所有的积分。
  5. 检查此轨迹是否主要指向外部(棘手的部分;)
  6. 如果它们向外出现足够多的帧,则轮廓会变大。
  7. 另外,您可以尝试修剪不属于正确轮廓的点并使用覆盖矩形。通过这种方式检查尺寸非常容易,但我不知道如何轻松地选择"正确"分。