2017年6月24日土曜日

OpenCV-Python で読み込んだ画像を、wxPython で表示したい。

結論

実現は容易。 (※2017/6/24 全面改訂)

wx.BitmapFromBuffer() で、OpenCV で読み込んだ画像データ (np.ndarray) から wx.Bitmap を作成できる。

ただし、OpenCV で読み込んだ画像データは BGR形式であるため、事前に RGB形式に変換しておく必要あり。


import wx
import cv2
import numpy as np

def create_wx_bitmap_from_cv2_image(cv2_image):
    # type: (np.ndarray) -> wx.Bitmap

    height, width = cv2_image.shape[:2]
    cv2_image_rgb = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2RGB)

    return wx.BitmapFromBuffer(width, height, cv2_image_rgb)

上記関数を用いたサンプルコード

実行結果

2017年6月17日土曜日

wxPython 3.0.2.0 (Windows版) をインストールする際の注意事項 (「ImportError: No module named wx」対策)

要旨

  • wxPython 3.0.2.0 (64-bit Python 2.7) の Windows Binaries インストーラ (wxPython3.0-win64-3.0.2.0-py27.exe) には、不具合がある。

  • 上記インストーラは、wxPyhon のモジュールを、Python が認識できない場所にインストールしてしまう。

    誤: python\Lib\site-packages\wx-3.0-msw\wx
    正: python\Lib\site-packages\wx

  • また、インストールオプションによっては、wxPythonモジュール自体をインストールしない場合がある。


wxPython (3.0) のインポートエラー発生時に確認すべきこと

  1. site-packages 直下に、「wx」というディレクトリがあるか?
    → この記事で言及している事象が発生しているのならば、存在しないはず。

  2. site-packages 直下に、「wx-3.0-msw」というディレクトリがあるか?
    → こちらについては、インストーラが正常終了したのであれば、存在するはず。

  3. site-packages\wx-3.0-msw 直下に、「wx」というディレクトリがあるか?
    → インストールオプションにより結果は異なる。詳細は後述。


wxPython (3.0) のインポートエラーの解決方法

ケースA: 上記 3. の答えが 「YES」 の場合

症状: wxPython モジュール自体はインストールできているが、インストール先の場所が正しくない。

wx」ディレクトリを、一つ上の階層(= site-packages 直下) に移動させることで、インポートエラーが解消する。


ケースB: 上記 3. の答えが 「NO」 の場合

症状: wxPython モジュール自体がインストールできていない。

この事象が発生するのは、インストール時のインストールオプションで「Compact installation」を選んだ場合である。(おそらく、wxPython インストーラの不具合)

解決するためには、wxPyhon の再インストールが必要。

最も手っ取り早いのは、wxPython を「Full installation」で入れなおせばよい。

しかしながら、あくまで「Compact installation」相当でインストールしたい場合には、一度「Full installation」を選んでから、不要なチェックボックスを外せばよい。

※以降は、上記 ケースA と同じ。


(余談) 「Compact installation」インストールオプションの不具合について

「Compact installation」インストールオプションを選択すると、なぜか「wxPython modules and library」が OFF かつ 非活性(チェック不可) となる。

気づかずにこのままインストールを進めると、(アンインストーラ以外は)何もインストールされずにインストーラが正常終了する。

OpenCV-Python 動画再生メモ for Windows

※このメモの前提となる環境

  • OpenCV 3.2.0
  • Python 2.7.13 (x64)
  • Windows 7 (Professional) SP1, 64bit

cv2.VideoCapture で mp4ファイル等が再生できない場合の解決方法。

※前提: サンプルデータのaviファイルは再生できること。

  • 原因: OpenCV に同梱されている ffmpegのDLL (opencv_ffmpeg*_*.dll) に、パスが通っていない。 パスを通すか、カレントディレクトリにコピーすることで、ffmpeg が対応している動画であれば、 OpenCV でも開けるようになる。

  • ffmpegのDLL は、「opencv\build\bin」直下 に格納されている。


cv2.VideoCapture で開いている動画のコーデック(FourCC)を特定する方法。

import cv2

def decode_fourcc(v):
  v = int(v)
  return "".join([chr((v >> 8 * i) & 0xFF) for i in range(4)])

cap = cv2.VideoCapture("input.mp4")
print decode_fourcc(cap.get(cv2.CAP_PROP_FOURCC))
  • FourCC の取得自体は簡単で、cv2.VideoCapture のインスタンス cap に対して
    cap.get(cv2.CAP_PROP_FOURCC)」 するだけである。

  • ただし、この戻り値は float 値 (FourCC バイト列のint表現をfloat化したもの) になっている。

  • そのため、文字列として FourCC を得るためには、デコードする必要がある。
    FourCC のバイト列をデコードするための API は用意されていないため、上記の「decode_fourcc()」のような関数を自作して対応する。(元ネタ: video_v4l2.py)

  • なお、FourCC をエンコードするための API (ヘルパ関数) は用意されている。
    cv2.VideoWriter_fourcc(c1,c2,c3,c4)

    使用例: cv2.VideoWriter_fourcc('a', 'v', 'c', '1')

参考: ビデオコーデック に対する FourCC の一覧


画像の寸法 (縦や横方向のピクセル数) を調べる方法。

  • np.ndarray.shape の第1要素が「縦」、第2要素が「横」方向のピクセル数である。

  • 動画のフレーム画像の場合でも、全く同じ。

import cv2
import numpy as np

img = cv2.imread(filename)  # type: np.ndarray
height, width = img.shape[:2]

OpenCV の ドキュメント(APIリファレンス) について

Python で OpenCV をする場合、少し古いかもしれないが、
Sphinx HTML」の方を参照したほうがよさそう。(2017年6月現在)

※APIリファレンス「以外」の部分、たとえばチュートリアル (OpenCV-Python Tutorials) については、この限りではない。(= 今後も更新されていくと思われる「Doxygen HTML」系統の最新版を見たほうがよい)

Open Live Writer (0.6.2) の実行には、おそらく .NET Framework の 4.6 が必要

総括

Windows 7 環境等で Open Live Writer (0.6.2) がまったく起動しない場合、Microsoft .NET Framework 4.6 をインストールすることで解決できる可能性がある。
※.NET Framework の バージョン4 や バージョン4.5 ではなく、バージョン4.6 が必要。


経緯

Open Live Writer (0.6.2) をインストールしてみたが、まったく起動しなかった。
※起動直後に「OpenLiveWriter.exe は動作を停止しました」(APPCRASH) になる。再現性あり。

上記事象が発生した際の当方のPC環境は、下記の通り。

  • OS: Windows 7 (Professional) SP1, 64bit
  • .NET Framework: バージョン2.0/3.0/3.5/4.5 導入済

Open Live Writer をデバッグしてみた。

  • OpenLiveWriter.ApplicationMain.Main で、「System.MissingMethodException」が発生している。
    ※メソッド「System.Array.Empty()」が見つからない模様。

  • System.Array.Empty(T) メソッド のリファレンス を確認したところ、

    バージョン情報
    .NET Framework
    4.6 以降で使用可能

    との記載があった。

  • Microsoft .NET Framework 4.6 をインストールしたところ、エラーが解消された。


参考リンク