【问题标题】:Fastest way to detect the non/least-changing pixels of successive images检测连续图像的非/最小变化像素的最快方法
【发布时间】:2020-03-11 15:33:20
【问题描述】:

我想找到视频流的静态像素。通过这种方式,我可以检测到视频流中的徽标和其他非移动项目。我的脚本背后的想法如下:

  • 在名为previous 的列表中收集多个大小相同且灰度大小相同的帧
  • 如果采集到一定数量的帧,调用函数np.std
  • 此函数循环遍历新图像的所有x-y-coordinates
  • 根据所有帧对应坐标的灰度值计算所有坐标的灰度值标准差

我的脚本:

import math
import cv2
import numpy as np


video = cv2.VideoCapture(0)
previous = []
n_of_frames = 200

while True:
   ret, frame = video.read()
   if ret:
      cropped_img = frame[0:150, 0:500]
      gray = cv2.cvtColor(cropped_img, cv2.COLOR_BGR2GRAY)
      if len(previous) == n_of_frames:
         stdev_gray = np.std(previous, axis=2)
         previous = previous[1:]
         previous.append(gray)
      else:
         previous.append(gray)

      cv2.imshow('frame', frame)

      key = cv2.waitKey(1)
      if key == ord('q'):
         break

video.release()
cv2.destroyAllWindows()

这个过程非常缓慢,我很好奇是否有更快的方法来做到这一点。我对 Cython 等持开放态度。非常感谢!

【问题讨论】:

  • 如果我假设您以 25 fps 的速度拍摄,那么平均超过 200 帧意味着您正在寻找 8 秒内的变化。如果是这样,您肯定不需要以每秒 25 倍的速度对每帧进行计算吗?您可以每 10 帧或 25 帧抓取并分析一次吗?其次,在您尝试通过优化来加快速度之前,请衡量您所看到的内容 - 因此请尝试了解仅捕获需要多长时间,然后仅进行分析...然后进行优化.
  • 最快意味着什么时间窗口?

标签: python image numpy opencv computer-vision


【解决方案1】:

一种方法是使用cv2.bitwise_and() 逐帧比较每个帧。这个想法是前一帧中的像素必须存在于当前帧中才能成为不变的像素。通过遍历帧列表,场景中的所有特征都必须存在于前一帧和当前帧中,才能被视为非移动项目。因此,如果我们按顺序遍历每一帧,最后一次迭代将具有所有先前帧的共享特征。

使用这组每秒捕获一次的帧

我们将每一帧转换为灰度然后cv2.bitwise_and() 与前一帧和当前帧。每次连续迭代的不变像素以灰色突出显示,而变化像素为黑色。最后一次迭代应该展示所有帧之间共享的像素。

如果您还对每一帧进行阈值处理,则会得到更明显的结果

import cv2
import glob

images = [cv2.imread(image, 0) for image in glob.glob("*.png")]

result = cv2.bitwise_and(images[0], images[1])
for image in images[2:]:
    result = cv2.bitwise_and(result, image)

cv2.imshow('result', result)
cv2.waitKey(0)

【讨论】:

  • 你的方法给出了我想要的并且一直在我脑海中的准确输出!!谢谢
  • 此方法将无法检测在白色和黑色之间闪烁的背景上的黑色徽标。我认为方差/偏差方法更可靠
  • 您好@nathancy,您如何使用您的代码迭代视频中的连续视频帧?谢谢
【解决方案2】:

可以从总和和平方和计算方差和标准差。

VAR X = EX^2 - (EX)^2

见链接https://en.wikipedia.org/wiki/Variance#Definition

Sum 和 Sum of squares 可以通过添加新图像和减去 n_of_frames 之前捕获的图像来顺序更新。 接下来计算方差并取平方根以获得标准偏差。 请注意,计算时间不取决于帧数。

查看代码

import math
import cv2
import numpy as np


video = cv2.VideoCapture(0)
previous = []
n_of_frames = 200

sum_of_frames = 0
sumsq_of_frames = 0

while True:
   ret, frame = video.read()
   if ret:
      cropped_img = frame[0:150, 0:500]
      gray = cv2.cvtColor(cropped_img, cv2.COLOR_BGR2GRAY)
      gray = gray.astype('f4')
      if len(previous) == n_of_frames:
         stdev_gray = np.sqrt(sumsq_of_frames / n_of_frames - np.square(sum_of_frames / n_of_frames))
         cv2.imshow('stdev_gray', stdev_gray * (1/255))
         sum_of_frames -= previous[0]
         sumsq_of_frames -=np.square(previous[0])
         previous.pop(0)
      previous.append(gray)
      sum_of_frames = sum_of_frames + gray
      sumsq_of_frames = sumsq_of_frames + np.square(gray)

      #cv2.imshow('frame', frame)

      key = cv2.waitKey(1)
      if key == ord('q'):
         break

video.release()
cv2.destroyAllWindows()

结果看起来非常棒。

【讨论】:

  • 谢谢,我喜欢你的方法。但是,接受的答案使我能够非常直接地cv2.findContours
  • 对不起@HJA24,您可以分享一个示例代码,说明您如何使用 bitwise_and 方法在视频中进行迭代?谢谢
猜你喜欢
  • 2020-09-07
  • 1970-01-01
  • 2019-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
相关资源
最近更新 更多