【问题标题】:Pythonic way to record changes inside a while loop在while循环中记录更改的Pythonic方法
【发布时间】:2016-06-25 01:23:16
【问题描述】:

我有一个 Python 脚本,它可以触发计算机网络摄像头,并且能够检测使用 opencv 捕获的视频中的运动。

它的工作方式是 Python 读取视频的第一帧并将其作为一个 numpy 数组存储在一个变量中。然后,脚本中运行了一个 while 循环,它基本上将第一个视频帧与视频的每个当前帧进行比较。在循环中每秒迭代大约 30 帧。当当前帧与第一帧不同时,我通过为其分配值 1 来更新 while 循环内的变量。因此,随着循环的进行,您可能有 0、0、0,然后是 1、1、1、1,具体取决于是否有运动。 我的目的是记录运动开始的时间。也就是说,我的变量从 0 变为 1 的时间。

这是我的伪代码:

start webcam
times_list=[]
motion_list=[]
while True:
    my_variable=0
    frame_difference=current_frame - first_frame
    if frame_difference > 0:
        continue
    my_variable=1
    motion_list.append(my_variable)
    #The motion_list will get big, so let's keep only the last two items to avoid memory problems
    #The last two items is all we need.
    #Check if there was a change from non-motion to motion
    if motion_list[-1]==1 and motion_list[-2]==0:
        times_list.append(datetime.datetime.now())

所以,最后我有一个时间列表,其中包含运动开始的所有时间。

这是一个好的解决方案还是我在这里遗漏了什么?

【问题讨论】:

  • 嗨,现在是周末,所以我有时间陪你 :) 经过昨天的讨论,我相应地更新了我的答案。通过您的 cmets,您似乎只对记录运动开始的最初时刻感兴趣,而不是整个运动时间线。

标签: python list while-loop


【解决方案1】:

更新:

第一个建议:

您可以做的改进很少,尤其是在您打算在Raspberry Pi 上运行您的应用程序时,尤其是在实践中经常(但不一定)。

总共有 4 种情况需要考虑,您的程序必须涵盖所有情况:

  1. 无动作:⇢ ⓪ ⇢ ⓪ ⇢ ⓪ ⇢

  2. 连续运动:⇢ ❶ ⇢ ❶ ⇢ ❶ ⇢

  3. 从无运动到有运动:⓪ ⇢ ❶

  4. 从动到不动:❶ ⇢ ⓪

唯一的注册时间是案例3所描述的那一次;而在议案期间(案例 2),我们不会关心时间。

我想在while 循环之前解决这个问题:

  • 你在某处保存了first_frame
  • 您将my_variable 设置为0

这是伪代码:

times_list=[]
my_variable = 0
while True:
    frame_difference = current_frame - first_frame
    # Case 1:
    if difference_frame == 0 and my_variable == 0:
        continue
    # Case 2:
    if difference_frame != 0 and my_variable == 1:
        continue
    # Case 3:
    if difference_frame != 0 and my_variable == 0:
        my_variable = 1
        # Your comments say this is the only instant you are interested in
        times_list.append(datetime.datetime.now())
    # Case 4:
    if difference_frame == 0 and my_variable == 1:
        my_variable = 0

注意事项:

  1. 出于性能考虑,最好先测试用例 1 和 2,因为在实践中,它们比其他两种情况更频繁地发生。因此,通过运行 continue 可以避免浪费时间检查不常见的情况 3 和 4。
  2. 我们摆脱了motion_list,不再需要为此列表分配内存,因为my_variable 扮演一个标志的角色,并且通过将其值重新设置为0 或@987654332 来满足您的需求@ 在最后两种情况下。

第二个建议:

如果您不是将此应用程序作为大学项目而是出于更实际/商业原因,您可能会想到此改进:由于从相机读取帧是一项 I/O 绑定任务,您可能对increasing webcam FPS 感兴趣(更可能在increasing Raspberry Pi FPS

【讨论】:

  • 因此,在您的代码中,如果第一帧与当前帧相同,则 while 循环将在 continue 上方重复,而不执行 now()。如果当前帧与第一帧不同,则执行now()并再次循环while循环,如果下一个当前帧仍与第一帧不同,则用now()记录另一个时间戳。这意味着,您的代码将在其中包含运动的每一帧记录一个时间戳。我错了吗?
  • 没错。但我想让你的结论(最后一句话)更清楚:什么定义了运动的瞬间?答案是:这是您获得与您的第一个框架不同的框架 (current_frame) 的那一刻。
  • 实际上,在 while 循环中,我使用absdiff() 方法计算帧差,然后应用findCountours() 方法检测差帧的轮廓。然后再次在 while 循环中,我有一个 for 循环,它遍历轮廓并检查计数区域是否小于某个最小给定区域,如果该区域小于最小区域,则继续操作。
  • 好的。如果我理解你的话,你总是将 current_framesame 第一帧进行比较,对吗? @A.S
  • 答案的更新版本说得通!感谢您的宝贵时间!
猜你喜欢
  • 2017-08-17
  • 2013-06-12
  • 2020-02-11
  • 2018-04-28
  • 2016-10-10
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
相关资源
最近更新 更多