13

我一直在寻找这样的东西,但我找不到所以就这样了。

一些背景

我使用 opencv 从视频文件中检索帧。通常人们会在一个无限循环中这样做,例如:

while (True):
    s, img = cv.read()

或者

for i in xrange(10000): #just a big number
    s, img = cv.read()

现在我想检索所有帧并在没有更多帧时退出循环。但是,我在 python 方面的技能还不够强大,无法做我想做的事情。

我想知道的

read函数(或方法,我不知道它们在python中是如何调用的)返回一个元组:第一个代表操作成功,第二个代表返回的帧。当元组的第一个元素为假时,我想打破 while 循环。有 C 背景,我想也许这会起作用:

while ((success, img = capture.read())[0]):
    #do sth with img

我认为当成功为假时这会打破循环。但它没有。然后我想也许这会起作用:

while ((success, img = capture.read()).success):
    #do sth with img

它也没有工作。我不想做类似的事情

while(True):
    s, i = capture.read()
    if (s == False):
        break

如果成功,如何测试条件而while不是if哪个中断?

4

6 回答 6

20

你可以写一个生成器函数。

def readframes(cv):
    while True:
        success, frame = cv.read()
        if success:
            yield frame
        else:
            return

这样,您可以使用 for 循环遍历帧。

for frame in readframes(cv):
    do_something_with_frame(frame)
于 2013-03-21T08:25:08.883 回答
7

思考 pythonic 的最好方法是忘记其他语言

s = True
while s:
    s, i = capture.read()
    if s:
        do_some_stuff(i)
于 2013-03-21T08:16:23.037 回答
7

Python 有一个替代iter签名,它将函数作为第一个参数,将确定停止条件的哨兵作为第二个参数。

使用它,你可以想出这样的东西:

for s,img in iter(cv.read, (False, None)):
    print img

不过,我怀疑它是否比单纯breakif街区更好。

此外,它只接受哨兵作为整体返回值,并且不能将停止条件基于它的某些部分(例如元组的第一个值)。这可能是一种解决方法,但会使代码更加模糊:

>>> for s,img in itertools.takewhile(lambda x: x[0], iter(cv.read, None)):
    print img

它用于itertools.takewhile确定返回元组的第一个值何时等于False


完整版测试:

>>> class Capture(object):
    def __init__(self):
        self.L = iter([1,2,3,4,5])
    def read(self):
        try:
            img = self.L.next()
        except StopIteration:
            return (False,None)
        return True, img

>>> cv = Capture()
>>> for s,img in iter(cv.read, (False, None)):
    print img

1
2
3
4
5

>>> cv = Capture()
>>> for s,img in itertools.takewhile(lambda x: x[0], iter(cv.read, None)):
    print img


1
2
3
4
5
于 2013-03-21T08:24:55.130 回答
1

这应该工作

while capture.read()[0]: 
    #do something

当然,您将无法以这种方式访问​​框架!

还有另一种方式

s,v = capture.read()
while s:
    #Do sth
    s,v = capture.read()

这当然是一种冗长的说法

while True: 
    s,v = capture.read()
    if not s: 
        break

你不想做什么(出于某种原因)

于 2013-03-21T08:17:13.410 回答
0

你不能做你在 python 中要求的事情(除非有我不知道的黑客)。

什么线:

s, i = capture.read()

正在做的是通过解包一个元组来分配2个单独的变量,没有办法告诉python你想要第一个分配的变量。在 python 中,在或条件语句
中赋值也是非法的。ifforwhile

你唯一能做的就是:

if(capture.read()[0]):

这意味着您会丢失图像数据。
简而言之,解包元组实际上非常性感,没有理由不利用它提供的功能!

于 2013-03-21T08:21:09.963 回答
0

这是关于使用返回元组的函数来打破循环的解决方案。

>>> def read(a):
...     if a == 0:
...         return (False, a+1)
...     return (True, a-1)
... 
>>> read(5)
(True, 4)
>>> read(0)
(False, 1)
>>> a = True
>>> i = 5
>>> while(a):
...     a, i = read(i)
...     if a:
...         print 'working'
...         
...     
... 
working
working
working
working
working
>>> 

现在您的代码将如下所示:

s = True
while(s):
    s, i = capture.read()
于 2013-03-21T08:23:29.660 回答