13

私はこのようなものを探していましたが、見つけることができなかったので、ここに行きます。

いくつかの背景

opencvを使用して、ビデオファイルからフレームを取得します。通常、人々は次のような無限ループでそれを行います。

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

また

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

今、私はすべてのフレームを取得し、フレームがなくなったらループを終了したいと思います。しかし、Pythonでの私のスキルは、私がやりたいことを実行するのに十分なほど強力ではありません。

知りたいこと

read関数(またはメソッド、Pythonでどのように呼び出されるかはわかりません)はタプルを返します。最初は操作の成功を表し、2番目は返されたフレームを表します。タプルの最初の要素がfalseの場合、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には、最初の引数として関数を取り、2番目の引数として停止条件を決定するセンチネルを持つ代替iterシグネチャがあります。

これを使用すると、次のようなものを思い付くことができます。

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

それでも、それがブロックbreak内の単なるプレーンよりも優れているかどうかは疑問です。if

また、全体的な戻り値としてセンチネルのみを受け入れ、その一部(タプルの最初の値など)に基づいて停止条件を設定することはできません。これは回避策になる可能性がありますが、コードがさらに難読化されます。

>>> 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 に答える