web-dev-qa-db-ja.com

更新時にOpencvimshow()がフリーズする

私の画像処理アルゴリズムでは、python/OpenCVを使用しています。アルゴリズムの出力は、同じウィンドウで何度も更新されます。

ただし、ウィンドウがフリーズしてまったく更新されない場合がありますが、アルゴリズムは引き続き実行され、その間に画像が複数回更新されます。このUbuntuマシンでは、ウィンドウが濃い灰色に変わります。

関連するコードの抜粋は次のとおりです。

_for i in range(0,1000):
    img = loadNextImg()
    procImg = processImg(img)
    cv2.imshow("The result", procImg)
    cv2.waitKey(1)
_

N.B。:processImg()は、その手順に約1〜2秒かかります。行cv2.imshow(procImg)は、最初のインスタンスでウィンドウを作成します(つまり、前の呼び出しはありません)。

10
user3085931

私の提案は、画像を表示するためにMatplotlibpyplotを使用することです。次のようにします。

import matplotlib.pyplot as plt
# load image using cv2....and do processing.
plt.imshow(cv2.cvtColor(image, cv2.BGR2RGB))
# as opencv loads in BGR format by default, we want to show it in RGB.
plt.show()

Cv2.imshowの問題は解決しないことはわかっていますが、問題は解決します。

9
Dharma

待機時間を増やすと、この問題が解決します。しかし、私の意見では、これはそれほど多くはありませんが、睡眠に費やされる不必要な時間(20ミリ秒/フレーム)です。

変化

cv2.waitKey(1)

cv2.waitKey(20)

私の場合、ウィンドウがフリーズするのを防ぎます。この必要な待機時間は、マシンによって異なる場合があります。

5
user3085931

私もまったく同じ問題を抱えており、ウィンドウが更新されるfpsが、完全にフリーズするまで次第に遅くなっていることに気付きました。 waitKey(x)をより高い値に増やすと、画像が更新される期間が長くなりますが、cv2.imshow()が計算する必要がある時間がwait(Key)からの時間を超えると、更新が停止します。

(この不満をスキップ:) cv2.imshow()とwaitKey()の組み合わせは完全な設計エラーだと思いますが、UIが更新されるまでimshow()がブロックされないのはなぜですか?そうすれば、毎回waitKey()を呼び出さなくても、生活がずっと簡単になります...

追伸:opencv内のopencvウィンドウ用に独自のスレッドを開始する可能性があります:

_import cv2
img = cv2.imread("image.jpg")
cv2.startWindowThread()
cv2.namedWindow("preview")
cv2.imshow("preview", img)
_

ソース: cv2.imshowコマンドはopencv-pythonでは正しく機能しません

まあ、これは私にとっては機能しません。実行すると常にこのエラーが発生するからです。

_(python3:1177): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Attempt to unlock mutex that was not locked
Aborted
_

たぶんあなたはそれを試して、それがあなたのために働いているかどうかを報告することができますか?

編集:さて、別のスクリプトimshow.pyを作成して問題を解決しました:

_import cv2
import os.path

while True:
    if os.path.exists("image.pgm"):
        image = cv2.imread("image.pgm")
        if not image is None and len(image) > 0:
            cv2.imshow("Frame", image)
            cv2.waitKey(20)
_

そして、私は他のプログラムで次のように画像を書き出しています:cv2.imwrite("image.pgm", image)そして私は次のようにスクリプトを呼び出しています:

_import subprocess
subprocess.Popen(["python3", "imshow.py"])
_

これによりダーティリードが作成されることがありますが、私にとってはそれで十分な場合もありますが、2つのプロセス間でパイプまたはキューを使用することをお勧めします。

3
ElDani

cv2.destroyAllWindows()の直後にcv2.waitKey()を追加するだけです

3
Mohanavel T

したがって、ここで起こっていると思うのは、imshowの最初の呼び出し後もアクティブなウィンドウ(highGUIの要素)がwaitKey関数からの何らかの応答を待っているが、プログラム以降は非アクティブになっているということです。 loadNextImg関数のprocessImgの計算でスタックしています。効率のわずかな浪費を気にしない場合(つまり、すべての操作が重要な組み込みシステムで実行していない場合)、waitKeyの後でウィンドウを破棄し、imshowの前に再作成する必要があります。画像の処理と読み込み中にウィンドウが存在しなくなるため、highGUIがwaitKeyからの呼び出しを待ってスタックすることはなく、応答しなくなることもありません。

2
bstadt
try:
    import cv2
except:
    print("You need to install Opencv \n Run this command \n pip install python-opencv")
    exit()
print('Press q to quit frame')
def viewer(name,frame):
    while True:
        cv2.imshow(name,frame)
        if cv2.waitKey(10) & 0xff ==ord('q'):
            break
    return
cv2.destroyWindow(name)

このプログラムを保存し、これ以降、これをインポートし、関数ビューアを使用してフレーム/画像を表示すると、表示ウィンドウがハングしたりクラッシュしたりすることはありません。

1
Harsh Vijay

ウィンドウが灰色になっている場合は、より多くの処理能力が必要になる可能性があります。したがって、画像を小さいサイズの画像にサイズ変更して実行してみてください。操作の実行中に任意のキーを押すと、ipythonノートブックでの実行中にフリーズすることがあります。私はあなたの問題を個人的に実行しましたが、それを実行している間、灰色の画面が表示されませんでした。ターミナルを使って直接実行しました。コードと手順を以下に示します。

import argparse
import cv2
import numpy as np 

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
args = vars(ap.parse_args())

# load the image, grab its dimensions, and show it
image = cv2.imread(args["image"])
(h, w) = image.shape[:2]
cv2.imshow("Original", image)
cv2.waitKey(0)

for i in range(0,1000):
    image = cv2.imread(args["image"])
    cv2.imshow("The result",image);
    cv2.waitKey(0)

ターミナルで実行します。

  1. ソースアクティベートenv_name
  2. python Filename.py --image Imagename.png

これにより、フリーズせずに1つのウィンドウのみ(毎回更新)で結果が得られます。新しいウィンドウごとに個別の画像が必要な場合は、.format( i)以下のとおり。ただし、jupyterノートブックではなくターミナルでのみ実行することを忘れないでください。

このビデオリンクでターミナルコマンドを使用して確認できます https://www.youtube.com/watch?v=8O-FW4Wm10s

for i in range(0,1000):
    image = cv2.imread(args["image"])
    cv2.imshow("The result{}".format(i),image);
    cv2.waitKey(0)

これにより、1000枚の画像を個別に取得できる場合があります。

1
R K Bhalodia

cv2.imshow()関数の後に次の2行のコードを追加します。

cv2.waitKey()

cv2.destroyAllWindows()

0
hafiz031