LoginSignup
6
4

More than 5 years have passed since last update.

OpenCVとmatplotlib.pyplotの競合について

Last updated at Posted at 2018-02-21

OpenCV(Python)で処理した画像の画素値ヒストグラムをmatplotlib.pyplotしようとしてハマったのでメモしておきます。

環境

項目 バージョン
OS MacOSX Sierra
Python 3.6.2(pyenv-virtualenv)
matplotlibのbackend TkAgg(pyenvとvirtualenvで環境構築した時にmatplotlib.pyplotが使えなかった時の対処法を参考に設定させていただきました)
$ pip freeze -l
cycler==0.10.0
matplotlib==2.1.2
numpy==1.13.3
opencv-python==3.3.0.10
pyparsing==2.2.0
python-dateutil==2.6.1
pytz==2018.3
six==1.11.0

やりたかったこと

  • 現在カメラに写っている画像をプレビューしながら、画素値のヒストグラムをリアルタイムに描画する

だいぶ端折っていまいまいましたが、当初はだいたい下のようなコードを書きました。

# coding: UTF-8
import cv2
import numpy as np
import matplotlib
from matplotlib import pyplot as plt

def run():
    cv2.namedWindow(self.srcWindowName)  # 加工前の映像表示ウィンドウ生成
    cv2.namedWindow(self.dstWindowName)  # 加工後の映像表示ウィンドウ生成
    cap = cv2.VideoCapture(0)
    while True:
        ret, src = cap.read()
        if ret:
            dst = convert(src)  # 加工
            cv2.imshow(self.srcWindowName, src)
            cv2.imshow(self.dstWindowName, dst)

            # ヒストグラム
            img_hist = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
            hist = cv2.calcHist([img_hist],[0],None,[256],[0,256])
            plt.plot(hist)
            plt.xlim([0,256])
            plt.ylim([0,10000])
            plt.pause(.01)
            plt.cla()  # 現在描写されているグラフを消去

        key = cv2.waitKey(1)
        if key == 27:  # ESCキー押されたら終了
            break

    cap.release()
    cv2.destroyAllWindows()

エラー

上記のコードを実行すると、以下のようなエラーが発生しました。

2018-02-21 17:42:24.083 python[11468:1380593] -[QNSApplication _setup:]: unrecognized selector sent to instance 0x7feff8ecedb0
2018-02-21 17:42:24.086 python[11468:1380593] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[QNSApplication _setup:]: unrecognized selector sent to instance 0x7feff8ecedb0'
*** First throw call stack:
(
        0   CoreFoundation                      0x00007fffbd5122cb __exceptionPreprocess + 171
        1   libobjc.A.dylib                     0x00007fffd232948d objc_exception_throw + 48
        2   CoreFoundation                      0x00007fffbd593f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
        3   CoreFoundation                      0x00007fffbd484755 ___forwarding___ + 1061
        4   CoreFoundation                      0x00007fffbd4842a8 _CF_forwarding_prep_0 + 120
        5   Tk                                  0x0000000116b19c02 TkpInit + 471
        6   Tk                                  0x0000000116a952a9 Tk_Init + 1794
        7   _tkinter.cpython-36m-darwin.so      0x000000011696edd4 Tcl_AppInit + 84
        8   _tkinter.cpython-36m-darwin.so      0x0000000116969c4f _tkinter_create + 1071
        9   python                              0x000000010d53ef46 _PyCFunction_FastCallDict + 166
        10  python                              0x000000010d5c764e call_function + 478
        11  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        12  python                              0x000000010d5c8126 _PyEval_EvalCodeWithName + 2566
        13  python                              0x000000010d5c8bc6 _PyFunction_FastCallDict + 662
        14  python                              0x000000010d4f5eba _PyObject_FastCallDict + 346
        15  python                              0x000000010d4f5fec _PyObject_Call_Prepend + 156
        16  python                              0x000000010d4f5c15 PyObject_Call + 101
        17  python                              0x000000010d5573ee slot_tp_init + 158
        18  python                              0x000000010d5536a9 type_call + 313
        19  python                              0x000000010d4f5e84 _PyObject_FastCallDict + 292
        20  python                              0x000000010d4f62d5 _PyObject_FastCallKeywords + 197
        21  python                              0x000000010d5c7622 call_function + 434
        22  python                              0x000000010d5c073d _PyEval_EvalFrameDefault + 4989
        23  python                              0x000000010d5c8878 fast_function + 568
        24  python                              0x000000010d5c7629 call_function + 441
        25  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        26  python                              0x000000010d5c8126 _PyEval_EvalCodeWithName + 2566
        27  python                              0x000000010d5c8bc6 _PyFunction_FastCallDict + 662
        28  python                              0x000000010d4f5eba _PyObject_FastCallDict + 346
        29  python                              0x000000010d4f5fec _PyObject_Call_Prepend + 156
        30  python                              0x000000010d4f5c15 PyObject_Call + 101
        31  python                              0x000000010d5c0a07 _PyEval_EvalFrameDefault + 5703
        32  python                              0x000000010d5c8126 _PyEval_EvalCodeWithName + 2566
        33  python                              0x000000010d5c8919 fast_function + 729
        34  python                              0x000000010d5c7629 call_function + 441
        35  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        36  python                              0x000000010d5c8878 fast_function + 568
        37  python                              0x000000010d5c7629 call_function + 441
        38  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        39  python                              0x000000010d5c8126 _PyEval_EvalCodeWithName + 2566
        40  python                              0x000000010d5c8919 fast_function + 729
        41  python                              0x000000010d5c7629 call_function + 441
        42  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        43  python                              0x000000010d5c8126 _PyEval_EvalCodeWithName + 2566
        44  python                              0x000000010d5c8919 fast_function + 729
        45  python                              0x000000010d5c7629 call_function + 441
        46  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        47  python                              0x000000010d5c8878 fast_function + 568
        48  python                              0x000000010d5c7629 call_function + 441
        49  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        50  python                              0x000000010d5c8878 fast_function + 568
        51  python                              0x000000010d5c7629 call_function + 441
        52  python                              0x000000010d5c06b3 _PyEval_EvalFrameDefault + 4851
        53  python                              0x000000010d5c8126 _PyEval_EvalCodeWithName + 2566
        54  python                              0x000000010d5bf330 PyEval_EvalCode + 48
        55  python                              0x000000010d5f3339 PyRun_FileExFlags + 185
        56  python                              0x000000010d5f286d PyRun_SimpleFileExFlags + 285
        57  python                              0x000000010d60c1b3 Py_Main + 3427
        58  python                              0x000000010d4ea7d8 main + 248
        59  libdyld.dylib                       0x00007fffd2c0f235 start + 1
        60  ???                                 0x0000000000000002 0x0 + 2
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6

OpenCVとmatplotlib.pyplotが競合していた

どうやらOpenCVで生成したウィンドウがある状態で、pyplotの描画を行おうとすると、上記のエラーが発生してしまうようです。

上記のエラーでググるとstackoverflowなどでは、「明示的にTkAggを使う宣言をする」という解決策が大半だったのですが、原因は別のところにありました。

結果的にcv2.namedWindow(self.srcWindowName)cv2.imshow(self.srcWindowName, src)などのプレビュー描画処理をコメントアウトすることで、ヒストグラムは正常に表示されるようになりました。

プレビューしながら・・・という機能を作るためには、別プロセスでプレビュー機能を立ち上げたほうが良いかもしれません。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4