【问题标题】:Understanding how to deploy python code to pop up balloons了解如何部署python代码来弹出气球
【发布时间】:2019-09-16 18:00:50
【问题描述】:

我是一个编程新手,我需要编写代码以在实时视频中使用 numpy 和 openCV 检测固定背景上的气球,并返回对象 [气球] 的中心。

抱歉,问题的无知。

由于我是新手,我在思考这样做的逻辑时遇到了麻烦,我没有资源来“教机器”和创建级联 XML 来检测气球,所以我想到了一种可能的解决方案: 使用 cv2.createBackgroundSubtractorMOG2() 来检测具有相同背景的运动,一旦有一些对象 [气球],计算实时视频中的所有白色像素并返回它的中心,具有正确的白色像素阈值数量。

问题是,我不知道如何获取 0-255 之间的像素值来知道它是白色还是黑色并同时显示视频,我认为有一个更简单的方法我找不到它的指南。

import numpy as np

import cv2

cap = cv2.VideoCapture(0)

fgbg = cv2.createBackgroundSubtractorMOG2()

while(1):

    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    fgmask = fgbg.apply(gray)
    img_arr = np.array(fgmask)
    cv2.imshow('frame',fgmask)
    for i in fgmask:
        for j in i:
            print(fgmask)
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

我在输出中看到了混乱的视频,并且在输出中出现了很多我不知道如何理解它们的值。

【问题讨论】:

  • 您使用print(fgmask) 显示图像中所有像素的值。然后你把它放在for-loop 中,这样你就可以多次打印相同的图像。如果你必须使用print(fgmask),那么只使用一次,不要在for-loop 中使用。
  • 如果您想在for-loop 中打印,那么print(j) 会更好,您应该会看到可以与 0-255 进行比较的灰度像素
  • 您还可以使用fgmask==255fgmask > 10 将数组中的所有元素与2 进行比较,将二维数组与True/False 匹配,然后您可以计算每行中有多少值为True sum(fgmask > 10) 以及所有数组中有多少值为 True sum(sum(fgmask > 10))。然后你可以认为当价值更大时,即。 1000然后有移动。
  • @furas 确实有帮助,现在的问题是视频超级滞后,因为它每帧运行 500*500 像素,有什么解决方案吗?
  • 第一:在waitKey()中使用较小的值,不需要等待这么长时间的key。第二:您不需要img_arr,因为fgmask 已经是数组。我使用带有 640x480 相机的旧笔记本,它运行速度非常快。也许相机无法更快地创建图像。

标签: python python-3.x popup-balloons


【解决方案1】:

我会用

changes = (fgmask>200).sum()

比较所有像素值几乎为白色 (>200) 并计算这些像素。

然后我可以将结果与某个值进行比较以将其视为移动。

import numpy as np

import cv2

cap = cv2.VideoCapture(0)

fgbg = cv2.createBackgroundSubtractorMOG2()

while True:

    ret, frame = cap.read()

    if frame is None:
        break

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    fgmask = fgbg.apply(gray)

    #changes = sum(sum(fgmask>200))
    changes = (fgmask>200).sum() 
    is_moving = (changes > 10000)
    print(changes, is_moving)

    cv2.imshow('frame', fgmask)

    k = cv2.waitKey(10) & 0xff
    if k == 27:
        break

cv2.destroyAllWindows()
cap.release()

print() 需要一些时间来显示文本,因此打印所有像素(循环多次)会减慢程序的速度。所以我跳过这个。我不必知道所有像素的值。


编辑:how to detect region of large # of white pixels using opencv? 中使用答案并添加可以找到白色区域并绘制矩形的代码。程序打开两个窗口——一个带有灰度fgmask,另一个带有RGB frame,它们可以一个接一个地隐藏。您必须移动一个窗口才能看到另一个窗口。

编辑:我添加了使用cv2.contourArea(cnt)(x,y,w,h) = cv2.boundingRect(cnt) 为所有国家创建包含项目(面积、x、y、w、h)的列表,然后获取max(items) 到获得面积最大的轮廓。然后它使用(x + w//2, y + h//2)作为红色圆圈的中心。

import numpy as np

import cv2

cap = cv2.VideoCapture(0)

fgbg = cv2.createBackgroundSubtractorMOG2()

while True:

    ret, frame = cap.read()

    if frame is None:
        break

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    fgmask = fgbg.apply(gray)

    #changes = sum(sum(fgmask>200))
    changes = (fgmask>200).sum() #
    is_moving = (changes > 10000)
    print(changes, is_moving)


    items = []

    contours, hier = cv2.findContours(fgmask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if 200 < area:
            (x,y,w,h) = cv2.boundingRect(cnt)
            cv2.rectangle(fgmask, (x,y),(x+w,y+h),255, 2)
            cv2.rectangle(frame, (x,y),(x+w,y+h),(0,255,0), 2)
            items.append( (area, x, y, w, h) )

    if items:
        main_item = max(items)
        area, x, y, w, h = main_item
        if w > h:
            r = w//2
        else:
            r = h//2
        cv2.circle(frame, (x+w//2, y+h//2), r, (0,0,255), 2)

    cv2.imshow('fgmask', fgmask)
    cv2.imshow('frame', frame)

    k = cv2.waitKey(10) & 0xff
    if k == 27:
        break

cv2.destroyAllWindows()
cap.release()

【讨论】:

  • 首先,你太棒了。这真的对我有帮助,其次是如果我有纯色 fgmask 将无法识别它,因为中心看起来没有变化,你知道如何解决它吗?也许我使用了错误的一般想法......我也很难逐帧保存并扫描所有图片以查找超过阈值的像素。
  • 我在 Stackoverflow 问题上发现了如何找到白色区域。我正在为此创建代码。
  • 非常感谢,如果我不是新手,我会将这个答案标记为超级有用。最后一个超级小问题是,我怎样才能获得主要“白点”中的中心位置[我想将激光聚焦到这个位置以弹出气球]。
  • 您有cv2.contourArea(cnt)(x,y,w,h) = cv2.boundingRect(cnt),因此您可以为所有计数创建包含(area,x,y,w,h) 项目的列表,然后获取max(list_of_items) 以获得最大面积的轮廓。然后中心是(x + w/2, y + h/2)
  • 我在最后一个代码中添加了这个 - 现在它为最大的区域绘制了红色圆圈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-06
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-11
相关资源
最近更新 更多