こんにちは,米国データサイエンティストのかめ(@usdatascientist)です.
データサイエンスのためのPython入門第28回です(講座の目次はこちら).今日はOpenCVというライブラリを使って,Pythonで画像を読み込んで表示してみようと思います!
(「データサイエンスのためのPython講座」動画版がでました!詳細はこちら)
データサイエンティストが扱うデータは,今まで扱っていたような(タイタニックデータのような)表形式のデータだけではありません.
PNGファイルのような画像データやmp3のような音声ファイルやmp4のような動画,DICOMデータのような医用画像データなど,文字通り「データ」と名前がつくもの’全て’です.
特に画像データは,昨今の深層学習によるブレークスルーの中心的なモダリティであり,近年多くの研究者が他分野から画像処理・画像認識に流れており,目まぐるしいスピードで研究が進んでいる分野でもあります.
私も仕事では画像データを扱っていますし,私の専門分野でもあります.
ひと昔前は画像分野の多くの研究がC++で実装されていましたが,最近はPythonが主流だと思います.多くの論文の実装がPythonで書かれています.
おそらく読者の中には画像データをそもそも扱ったことがない人もいると思いますが,今回は本当に触りだけ扱うので,心配しないでください.
画像を読み込んで表示する だけです.画像処理や画像認識のアルゴリズムは出てきません.それらを説明すると新たな講座ができてしまう量になるのでw
でも,せっかくPythonでデータサイエンスを学習するならいずれは深層学習や画像認識にも手をだして,いわゆる「AI」の開発にも興味を持って欲しいです.
目次
OpenCV
コンピュータ・ビジョンのためのオープンソースライブラリです.
「コンピュータ・ビジョン」というのはコンピュータに画像や動画を理解させる研究分野だと思ってください.例えばデジカメで写真をとるときに,人の顔に枠がでますよね?あれは顔認識アルゴリズムがデジカメに組み込まれているのですが,あれもコンピュータ・ビジョンの分野です.
他にもGoogleの画像検索とか,Kinectの姿勢推定もコンピュータ・ビジョンです.
私も大学院の研究や仕事でコンピュータ・ビジョンを扱っています.本当に魅力たっぷりの分野なので,是非いろんな人にその魅力を伝えたいんですが,今回の講座の趣旨とそれるので自粛しますw
OpenCVは「コンピュータ・ビジョン」のアルゴリズムを簡単に使えるライブラリで,画像を扱う際には必須のライブラリです.
例えば画像の輪郭だけ書いてくれたり色空間(白黒とか)を変更したり,いろんなことがめちゃくちゃ簡単にできます.
もともとはC++で書かれたライブラリですが,Pythonラッパーもかなりアクティブに開発されており,Pythonで問題なく使えます.
Python用画像処理系ライブラリには他に,Python Imaging Library (PIL)と呼ばれるものがありますが,OpenCVの方が深層学習系のライブラリ(TensorFlow, PyTorchやCaffeなど)との相性もよく,最近ではPILよりOpenCVの方が使われていると思います.
私のチームでも,PILを使っている人はほとんどいませんし,私も開発はすべてOpenCVでコードを書いてます.
OpenCVをインストール&インポート
それでは早速OpenCVをインストールしましょう.
今までのライブラリ(NumPy, Pandas, matplotlibやSeaborn)はAnacondaに入っていたので特にインストールは不要だったんですが,OpenCVはAnacondaに入ってません!!
なので別途インストールが必要です.ついにこの日が来てしまいましたね!
基本的には $pip install opencv-python でインストール可能ですが,場合によっては事前に関連パッケージのインストールが必要です.
せっかくなのでこれを機にDocker環境の更新手順を紹介したいと思います.
以下は第一回に沿って環境をセットアップした人向けです.
1.Dockerコンテナに入ってopencvをインストール
以下のコマンドでDockerコンテナに入ります.(コンテナ名は $docker ps で確認しましょう.この辺りの操作がアヤしい人は,Docker講座の第3回参照してね)
1 2 3 4 5 |
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ec5e9afb20f6 d723190a8650 "jupyter lab --ip=0.…" 6 weeks ago Up 2 weeks 0.0.0.0:8888->8888/tcp my-lab $ docker exec -it my-lab bash root@ec5e9afb20f6:/# |
コンテナに入れました.
2. OpenCVをインストール
そしたら $pip install opencv-python でopencvライブラリをインストールします.私の環境ではopencvを入れる前に以下のコマンドで関連パッケージをインストールする必要がありました.(参考ページ)
1 2 |
$ apt-get update $ apt-get install -y libsm6 libxext6 libxrender-dev libglib2.0-0 libgl1-mesa-dev |
おそらくみなさんも同じかと思いますが,バージョンによって異なると思うので必要に応じてググってみてください.
1 2 3 4 5 6 7 8 9 |
root@ec5e9afb20f6:/# pip install opencv-python Collecting opencv-python Downloading https://files.pythonhosted.org/packages/34/a3/403dbaef909fee9f9f6a8eaff51d44085a14e5bb1a1ff7257117d744986a/opencv_python-4.2.0.32-cp37-cp37m-manylinux1_x86_64.whl (28.2MB) |████████████████████████████████| 28.2MB 152kB/s Requirement already satisfied: numpy>=1.14.5 in /opt/anaconda3/lib/python3.7/site-packages (from opencv-python) (1.17.2) Installing collected packages: opencv-python Successfully installed opencv-python-4.2.0.32 WARNING: You are using pip version 19.3.1; however, version 20.0.2 is available. You should consider upgrading via the 'pip install --upgrade pip' command. |
3. OpenCVをインポートしてみる
インストールが完了したら,JupyterHubでopencvをインポートできることを確認しましょう.
opencvをインポートするには import cv2 でOKです.
1 |
import cv2 |
cv2を使ってOpenCVの色々な関数を使えるようになります!
4. Dockerfileを更新する
次回Dockerfileをrunした時用に,第一回で作成したDockerfileに以下のコマンドを追記しておきましょう
1 2 3 4 |
# install OpenCV RUN apt-get update RUN apt-get install -y libsm6 libxext6 libxrender-dev libglib2.0-0 libgl1-mesa-dev RUN pip install opencv-python |
一番後ろの行に追記する形でいいと思いますが,今回はpipのupgrade前に追記しました.全体のファイルは以下のようになります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
FROM ubuntu:latest # update RUN apt-get -y update && apt-get install -y \ sudo \ wget \ vim \ libsm6 \ libxext6 \ libxrender-dev \ libglib2.0-0 \ libgl1-mesa-dev #install anaconda3 WORKDIR /opt # download anaconda package and install anaconda # archive -> https://repo.continuum.io/archive/ RUN wget https://repo.continuum.io/archive/Anaconda3-2019.10-Linux-x86_64.sh && \ sh /opt/Anaconda3-2019.10-Linux-x86_64.sh -b -p /opt/anaconda3 && \ rm -f Anaconda3-2019.10-Linux-x86_64.sh # set path ENV PATH /opt/anaconda3/bin:$PATH # update pip and conda RUN pip install --upgrade pip WORKDIR / RUN mkdir /work # install OpenCV RUN pip install opencv-python # install jupyterlab ENTRYPOINT ["jupyter", "lab","--ip=0.0.0.0","--allow-root", "--LabApp.token=''"] |
Dockerfileの更新についてはDocker講座第5回を参照ください.
今回はrunしませんが,各自必要な時にrunしてみてください.
OpenCVを使って画像を表示する
今回はlennaの画像でも使おうかなと思います.↓の画像をダウンロードして,「lenna.png」という名前で,Dockerからアクセスできるところ(私の環境では~/Desktop/ds_pythonフォルダ)においてください.(第一回でdocker runした際の-vオプションです.)
この写真,実はコンピュータ・ビジョン界隈では非常に有名な写真で,様々な論文で,「サンプル画像」として使われています. もともとはPLAYBOY誌のグラビア(ヌード)写真から切り取った写真で,1970年代前半に最初に使われたらしく,当初は「けしからん」と論争を巻き起こしたとか.今ではすっかりおなじみの画像になりました.ちなみに「Lena Forsen」が本名ですが,正しい発音に近いlennaが一般的に使われてます.(どっちでもいいわっ)
- cv2.imread()で画像をNumPy Arrayで読み込む
cv2で画像を読み込むには cv2.imread() 関数にファイルパスを指定して読み込みます.読み込んだあとは,その画像をNumPy Arrayとして扱うことができます.
1 2 |
import cv2 lenna = cv2.imread('lenna.png') |
lennaの中身をみるとndarrayになっているのがわかると思います.そうです,第6回でやったndarrayです.ndarrayがアヤしい人はNumPy編を復習してください.
1 |
lenna.shape |
1 |
(220, 220, 3) |
読み込んだndarrayは(220, 220, 3)というshapeのndarrayであることがわかります.
これは画像の(高さ, 横幅, channel数)を表しています.高さと横幅は当然ピクセル数で,channelというのは画像の色を表現するのに使うもので,Red, Green, Blueの3channelであり,「RGB」というchannelでデータが保存されるのが一般的です.(後述しますが,OpenCVはデフォルトで「BGR」です.気をつけてください.)
この説明だけだとピンとこない人もいると思います.
もう少し詳しく説明すると,色を表現するにはいくつか方法があり,その一つに「赤・緑・青の3色の光を足し合わせる(加法混色)」という方法があります.
各ピクセルの値はその光(Rなら赤)の強さを表しており,それを輝度値(Intensity)と呼びます.OpenCVではデフォルトで0~255の256(8bit)階調で表します.通常,画像は8bitで保存されます.
輝度値が0ということは光が0なので暗く,255というのは輝度値がMAXなので明るくなります.R, G, Bの各channelで255の値を持つピクセルは,それらを合わせると白になり,0なら黒になります.
・・・何となく分かりましたか?多分一番最初は理解するのはむずかしいんじゃないかな.今まで画像をデジタルのデータとして扱ってきたことがないと思うのでピンとこないかもしれませんが,今完全に理解する必要はないと思います.
- plt.imshow()で画像を表示する
それでは,読み込んだndarrayをjupyterで表示してみましょう.
画像を表示するには第20回で紹介したmatplotlibを使います.
plt.imshow() という関数にndarrayを入れると,ndarrayを画像として表示してくれます.
1 2 3 4 |
import matplotlib.pyplot as plt %matplotlib inline plt.imshow(lenna) |
ちゃんとlenaの画像が表示されました!
・・・が,なんか青いですよね?
実はこれ,OpenCVは画像を読み込む際に色空間をBGRで読んでいて,matplotlibではRGBで表示しているからです.
つまり,青と赤が逆になってしまっているってこと
現代一般的に使われるのはRGBなんですが,OpenCVはBGRで読み込みます.これには歴史的背景があるんですが,今日は触れません.興味がある方はググってみてください.
とにかくこれがややこしい上に予期せぬバグを起こしやすいです.初学者は特に注意です.
lennaの画像は幸いRとBが逆になると明らかに見た目が違うんで気づきますけど,そうでない画像も多いです.
すると気づかずRとBを逆に捉えていて,「あるコードではRGB,別のコードではBGRで処理してた」なんてこともありえます.
- ではどうすればいいか?→BGRからRGBに変換する
BGRで読み込んだ画像をRGBに変換しましょう.OpenCVには様々な色空間を変換する関数が用意れています.
cv2.cvtColor() 関数を使うことで様々な色空間の変換が可能です.(cvtはconvertの略です)使い方はちょっと不思議です. cv2.cvtColor() の第一引数にndarrayを,第二引数に「なにからなにへの変換」なのかを示すcodeを指定します.
codeはcv2モジュールに入っています.cv2.COLOR_に続く変数がそれです.Jupyterではcv2.COLORと打ってTabキーを押すと補完候補をみることができます.
今回はBGRをRGBに変換するので cv2.COLOR_BGR2RGB を入れます.ほんと見られない形なので,慣れるのに時間かかりますが,慣れるとパッと打てるようになります.
1 2 |
lenna_rgb = cv2.cvtColor(lenna, cv2.COLOR_BGR2RGB) plt.imshow(lenna_rgb) |
C++ネイティブのライブラリでインタフェースを揃えてるので,このように少し違和感のある書き方になってしまいますが,慣れるしかないです.
OpenCVはほんとにできることが多くて,私も毎日のように使っているライブラリです.画像処理って処理が目に見えるのでやり始めると結構楽しいので,是非色々試してみてほしいです.
さらに勉強したい人は,英語ですがこちらに色々と教材があります.みてみてください.
ちょっとした画像処理をするならこちらが分かりやすいと思います.
まとめ
今回は画像を読み込んで表示する方法と,色空間の変更について紹介しました.
ほんとに触り部分しか触れていませんが,今回の内容をまとめると
- OpenCVはC++で書かれた画像処理ライブラリ
- import cv2でOpenCVをインポート
- cv2.imread(ファイルパス)でNumPy Arrayとして画像を読み込む
- plt.imshow()にNumPy Arrayを入れることで画像として表示する
- OpenCVはデフォルトでBGRとして画像を読み込む一方,matplotlibはデフォルトでRGBとして画像を扱う
- cv2.cvtColor(img, cv2.COLOR_BGR2RGB)でBGRからRGBにchannelの並び(色空間)を変更する
OpenCVはほぼ99%画像を扱う際に使うライブラリです.画像を使わない人は,OpenCVを使うことはないと思います.
今回はこの辺で
そろそろ本講座も終わりに近いです...!
それでは!
追記:次回書きました.次回はデータサイエンス頻出のglob()関数について基本的な使い方とよくある応用例を紹介します!