Jan Erik Solem:実践 コンピュータビジョン

Python で Scikit と OpenCV を使う

作成日:2021-02-05
最終更新日:

概要

原題は "Programming Computer Vision with Python"。 まえがきから引用する。

簡単に言えば、 コンピュータビジョンの応用プログラミングに興味のある人を刺激するアイデアの泉のような入門書を目指しました。

感想

本書は、Python 2.7 、OpenCV 2.4.3 を前提としているので、注意したい。

なお、本書のサポートぺージは下記にある。
http://programmingcomputervision.com
プログラムコードや画像データは上記から入手できる。
また、著者のサポートページが GitHub で公開されている。
https://github.com/jesolem/PCV
訳者のブログ(aizoaikawa.hatenablog.com)によれば、 「原書の英語はふつうですが、コードに間違いが多くありました。もちろん日本語版では修正済みです。」 ということである。訳者が修正したコードは、下記ページの「関連ファイル」タブから入手できる。
https://www.oreilly.co.jp/books/9784873116075/

私は、Windows Subsystem for Linux 2(WSL2) の Ubuntu 20.04 で以下試してみた。

なお、以下に書かれていることとは別に、 Python 2 系統で書かれているコードを Python 3 系統に直す作業もあった。 後述する。

第1章

第1章の「基本的な画像処理」では、p.1 PIL (Python Imaging Library) を説明しているが、 2021 年 2 月では更新されていない。 現在では、Pillow を使う。

また、p.4 で紹介されている Matplotlib の使い方として、
from pylab import *
を紹介しているが、現在では、
import matplotlib.pyplot as plt
のほうが普通だろう。これに関しては、p.29 で説明されている。 つまり、本書のサンプルコードが import * のように書かれている理由は、 サンプルコードが読みやすく簡潔になるからだ、というのが筆者の主張である。 ただ、私が読んでいる Python 関係の本では、ほとんどが ... as plt のように名前空間を保持する書き方をしている。

第2章

sift

sift.py がうまく動かない。
$ python3 2.2.3.sift.py
processed tmp.pgm to empire.sift
/mnt/c/Users/username/documents/program/PCV/chap2/sift.py:25: UserWarning: loadtxt: Empty input file: "empire.sift"
f = loadtxt(filename)
Traceback (most recent call last):
File "2.2.3.sift.py", line 12, in <module>
l1,d1 = sift.read_features_from_file('empire.sift')
File "/mnt/c/Users/satosi/documents/program/PCV/chap2/sift.py", line 26, in read_features_from_file
return f[:,:4],f[:,4:] # 特徴点の配置と記述子
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

その後調べてみると、どのような pgm ファイルであってもこの sift コマンドは 0 x 0 画像だといってくる。
$ sift -v empire.pgm
sift: <== 'empire.pgm'
sift: image is 0 by 0 pixels

まさかと思って、Windows 10 (Home Edition) でバイナリを実行したが、同じとなる。なんということだ。 vlfeat に defeated という気分だ。なお、この empire.pgm は Gimp で表示できる。当然、画像形式も正しい。
$ file empire.pgm
empire.pgm: Netpbm image data, size = 569 x 800, rawbits, greymap

他に考えられることとして、Shared Object が見つからない問題も考えたが、$ ldd sift とやっても問題はなさそうだ。

仕方がない。ダウングレードしてみよう。一番新しいのは 0.9.21 だったが、 本書で最新だった 0.9.16 に変えてみる。

$ sift -v empire.pgm
sift: <== 'empire.pgm'
sift: image is 569 by 800 pixels

今度は縦横ともに正しい画素数が表示されている。 ということは 0.9.16 から 0.9.21 のどこかでデグレードしたということか。まあいい。これで sift を続けてみよう。

$ sift -v empire.pgm -o empire.sift --edge-thresh 10 --peak-thresh 5
sift: <== 'empire.pgm'
sift: image is 569 by 800 pixels
$ head empire.sift
(後略)

10 秒弱計算に時間がかかるが、ともかく sift が動いた。 このあと、SIFT 特徴点のスケールを円で表示した画像も生成・表示できた。

Panoramio

p.46 や p.250 で述べられている、Panoramio は、Google が提供していたが、現在はサービスを終了している。 ではどうすればよいか。今回の目的では、ホワイトハウスの写真を20枚、JPEG で用意すればいいだろう。 ただ、私は20枚も用意するのが面倒なので、14枚だけ用意した。 正面玄関が写っているものと、バルコニーが写っているものの2種類に分かれる。

第3章

訳者のサンプルコードに合わせて解説されている文書で、 flickr から5種類のコードをダウンロードするように書かれている。 しかし、blank_billboard.jpg についてはリンク先に画像がなかった。次の画像を代わりに使った。 当然、その後の四隅に設定する点の位置は異なる。

https://buidln.clipdealer.com/000/074/912/previews/16--74912-Large%20blank%20billboard%20Time%20lapse.jpg

第4章

本書の p.84 や p.251 で、あるいは訳者による本書コードの解説で、 オックスフォード大学の多視点データセットからのデータの取得先が
http://www.robots.ox.ac.uk/~vgg/data/data-mview.html
となっているが、2021-02-15 現在は
http://www.robots.ox.ac.uk/~vgg/data/mview/
に変更されている。

第5章

p.105 にあるカメラ行列のデータセットの URL が変更されていることは、第4章と同様である。

p.105 のコードにある、# 対応関係を読み込む コードは
corr = np.genfromtxt('2D/nview-corners',dtype='int',missing='*')
となっているが、現在の numpy では
corr = np.genfromtxt('2D/nview-corners', dtype='int', missing_values='*')
である。
https://github.com/takeshi-a/pcv_note/blob/master/chap5/pcv_05_1_metron.ipynb
参照。

以下は省略する。

第6章

第2章の結果を一部用いていることに注意。結果は割愛する。

第7章

第7章で、準備として、http://www.vis.uky.edu/~stewe/ukbench/ にある ukbench.zip をダウンロードし、 そのうちの ukbench00000.jpg から ukbench00999.png をサブディレクトリ first1000 にコピーすることになっている。 しかし、上記ページは Not Found である。仕方がないので、
https://archive.org/download/ukbench
から同じように first1000 にコピーする。1.5 GB 以上あるので注意すること。

さて、訳者によるコード 7.2.1.mk_imlist.py を実施し、続いて 7.2.1.mk_sift.py を実行したら、次のエラーが出た。
sh: 1: sift: not found
processed tmp.pgm to first1000/ukbench00000.sift
(後略)

これは何を言っているかというと、sift というシェルのコマンドがないことを言っている。 なぜこういうことが起きたかというと、第2章で訳者がいう、下記を実施していなかったからだ:
外部プログラムとして、VLFeatのsiftを用いるので、実行できるようにsiftにパスを通しておいてください。
あわてて、https://www.vlfeat.org からダウンロードした。2021-02-14 現在、 VLFeat は 0.9.21 になっている。

バイナリの sift をインストールして、7.2.1.mk_sift.py を実行するのは 1 分未満だった。 案外短い。ところが、次を実行してみたら、どうも 7.2.1.mk_sift.py は失敗だったようだ。

$ python3 7.2.1.mk_voc.py
/mnt/c/Users/username/documents/program/PCV/chap7/sift.py:25: UserWarning: loadtxt: Empty input file: "first1000/ukbench00000.sift" f = loadtxt(filename)
Traceback (most recent call last):
File "7.2.1.mk_voc.py", line 15, in <module>
voc.train(featlist,1000,10)
File "/mnt/c/Users/satosi/documents/program/PCV/chap7/vocabulary.py", line 25, in train
descr.append(sift.read_features_from_file(featurefiles[0])[1])
File "/mnt/c/Users/satosi/documents/program/PCV/chap7/sift.py", line 26, in read_features_from_file
return f[:,:4],f[:,4:] # 特徴点の配置と記述子
IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

UserWarning の、Empty input file: "first1000/ukbench00000.sift" が怪しい。確かに、 このファイルは 0 バイトである。ということは、sift コマンドがうまく動作しなかったのか。

結局第2章まで遡って調べた。結局 sift コマンド単体のバグだった。第2章参照。

第8章

私の環境で p.182-183 のコードを実行した結果は次の通り。こんなものだろう。 <「P」(Point)が「V」と誤認識されやすい>と本書にあるが、それは私の実験でも同様だ。

	Accuracy: 0.7259615384615384
	Confusion matrix for
	['A' 'B' 'C' 'F' 'P' 'V']
	[[26.  0.  2.  0.  1.  1.]
	 [ 0. 28.  2. 14.  1.  1.]
	 [ 0.  0. 27.  0.  0.  0.]
	 [ 0.  1.  0. 26.  0.  0.]
	 [ 0.  1.  4.  0. 20.  2.]
	 [ 3.  2.  1.  7. 14. 24.]]	

第9章

p.206 の次の行
from scipy.misc import imresize
がエラーとなる。
cannot import name 'imresize' from 'scipy.misc'
この対応としては、この行の代わりに
from PIL import Image
を宣言し、imresize を使っている次の行
im = imresize(im,0.07,interp='bilinear')
を次で置き換える:
im = array(Image.fromarray(im).resize((int(im.shape[1]*0.07),int(im.shape[0]*0.07)), Image.BILINEAR))
2倍以上長くなってしまった。scipy.misc の imresize のオプションは融通が効いていて、 第2引数に浮動小数点数を与えれば画像の縦横の拡大縮小の比率と解釈された。しかし、 現在は scipy.misc の imresize は廃止されてしまった。代替の一つが PIL の Image にある resize を使うことである。 しかし、この resize は拡大縮小の比率を与える方法としては拡大縮小後の幅と高さをタプルとして明示的に与えるインターフェースしかない。 したがって、このようなまだるっこしい書き方をせざるを得ない。 もう一つ注意すべきは resize に与えるタプルの順序で、幅 (width) と高さ(height)はこの順序である。 im.shape には画素の行数(すなわち高さ)、画素の列数(すなわち幅)、画素の深さ( RGB なので 3) がこの順でタプルとして取り出されるので、上記のコードとなっている。元の empire.jpg の shape は、 (800, 569, 3) であった。
なお、p.207 の図 9-2 のキャプションには、画像は 54 x 38 に間引いている。という説明がある。 800 * 0.07 = 56, 569 * 0.7 = 39.83 であるから、このコードで間引くと 56 * 39 になり、少しずれがある。

第10章

本書 p.221 の画像は横長(ランドスケープ)になっているが、著者が用意する電子データは縦長(ポートレート)になっている。 左側の原画像に関しては、本書に掲載されている画像を右に90度回転すると、電子データの画像になる。 右側の画像はおそらくランドスケープのまま積分画像処理をしたのだろう。

本書 p.222 の開始点から塗りつぶしをする処理を実行したところ、以下のメッセージが大量に繰り返し出力された:
QObject::moveToThread: Current thread (0x55c289167ac0) is not the object's thread (0x55c289c0a690).
Cannot move to target thread (0x55c289167ac0)
これは私の環境が、waitkey() に関するバグがあることを示している。以下は、 waitkey() をコメントアウトした。

本書 p.223 のコードでは、
AttributeError: module 'cv2.cv2' has no attribute 'SURF'
これは、 pip を使って導入した OpenCV では SURF は使えないということである。 OpenCV と Python による機械学習プログラミング参照。

Python 3 系への変換:

Python 3 系に変換する作業があった。次の通り。

関連書籍

書誌情報

書 名実践 コンピュータビジョン
著 者Jan Erik Solem
訳 者相川 愛三
発行日2013 年 3 月 21 日 初版第1刷
発行所オライリー・ジャパン
発売元オーム社
定 価3000 円(税別)
サイズ
ISBN978-4-87311-607-5
その他越谷市南部図書室で借りて読む
NDC

まりんきょ学問所コンピュータの部屋コンピュータの本画像処理 > Jan Erik Solem:実践 コンピュータビジョン


MARUYAMA Satosi