pyCUDAで画像処理に挑戦してみた(超入門編)
どうもこんにちは。
ちゃんとブログを更新しようと思っている今日この頃です。
前回の記事で、GPU環境をいい感じに整えることができるnVidia-dockerについてご紹介しました。
せっかく作って壊せるGPU環境が手に入ったので(?) 今回は、CUDAを使ったGPUプログラミングをやってみたいと思います。 ところで、CUDAで遊んでみたいけど、C++から叩くのは面倒なあ… という方は結構いらっしゃるのでは無いでしょうか。 もちろん、僕もそのタイプです。
そんな僕にピッタリのツールとしてpyCudaがあります。
Welcome to PyCUDA’s documentation! — PyCUDA 2017.1.1 documentation
PythonからCUDAのカーネルを呼ぶことができるライブラリです。しかし、情報があまりないんですよね…
今回は練習がてら、numpy array形式の画像をGPUで処理するようなコードを書いてみたいと思います。
環境
以下の環境で動作確認をしています。
準備
nVidia-dockerのコンテナとして環境を用意することにします。 ベースとして、以下のイメージを利用しました。
https://hub.docker.com/r/nightseas/pycuda/
ただ、上記イメージにはPillowが入っていなかったので足してあげます。 私の環境では、下記Dockerfileをビルドすると正常に動作しました。 ただし、ベースとしたイメージはPython2.7.12だったので、3系を使いたい方は別途環境を構築する必要がありそうです。 私もそのうちやってみます。
FROM nightseas/pycuda:latest RUN apt-get update && \ apt-get install -y python-tk RUN pip install pillow
やってみること
最初は基礎的なところから始めましょう。 8bitグレースケール画像の輝度を反転するだけのコードを書いてみたいと思います。
実装
# coding: utf-8 import pycuda.autoinit import pycuda.driver as cuda from pycuda.compiler import SourceModule import numpy as np from PIL import Image # # 以下CUDAカーネル # mod = SourceModule(""" __global__ void negative(unsigned char *image, int height, int width) { int pos_y = threadIdx.y + blockDim.y * blockIdx.y; // 画像のy方向の位置を取得。 int pos_x = threadIdx.x + blockDim.x * blockIdx.x; // 画像のx方向の位置を取得。 int idx = pos_y * height + pos_x; // 内部では1次元配列化しているので、インデックスはこのようになる image[idx] = 255 - image[idx]; //画素値を反転 } """) # # 画像の読みこみ # pil_image = Image.open("./lena_gray.png") # 画像の読み込み image = np.array(pil_image, np.uint8) # PIL Image型からnumpy arrayに変換。 height, width = image.shape[:2] # 今回は512x512pxの画像を利用 # # CUDA周りの準備 # cuda_kernel = mod.get_function("negative") # 上で定義したカーネルを呼び出す block = (512, 1, 1) # Block size (後述) grid = (512, 1, 1) # Grid size (後述) # # カーネルを実行 # cuda_kernel(cuda.InOut(image), # imageを参照渡しする。 np.int32(height), # int型定数はnumpyで明示的に型を定義する np.int32(width), block=block, grid=grid) # BlockとGridも引数として与える # # 処理後の画像を保存 # pil_output_image = Image.fromarray(image) pil_output_image.save("out.png")
CUDAにおける画素インデックスは、下記スライドのp59を見るとわかりやすいと思います。
www.slideshare.net
こんな感じで初歩のの初歩ですがCUDAを使った画像処理を行なうことができます。 次回(あるのか?)は、もうちょっと凝ったことにチャレンジしたいと思います。
2017/08/29追記 qiita.com Gridsize, Blocksizeは上記の記事を参考に修正しました。
もう依存関係に悩まない! nvidia-dockerでクリーンなGPU環境を作る
こんにちは. 前回の更新が2015年5月,今日は2017年8月の終わりです. 察していただけますと幸いです(?)
突然ですが,Dockerって便利ですよね. www.docker.com
数年前から話題になっているDockerですが, 恥ずかしながら,最近まで使ったことがありませんでした. しかし,いざ使ってみると,ライブラリのインストールとかでいちいちハマっていた時間を大きく短縮でき,新しいライブラリを試してみるまでの障壁が低くなりました. もちろん,Dockerならではのめんどくささみたいなのもありましたが,全体的に便利になったと思ってます.
ところで,色々なライブラリがリリースされ,それぞれ触ってみたいなーと思うカテゴリにDeep Learningがあります. 有名どころだけでもCaffe, Tensorflow, Chainer, Keras, PyTorch…なんて具合です. が,依存関係やらGPU周りのめんどくささで,インストールが面倒だと言う話はよく耳にするかと思います.
ということで,本記事ではOS未インストールのGPUマシンから,nvidia-dockerを使ってクリーンなGPU開発プラットフォームを作るまでを解説したいと思います.
はじめに:nvidia-dockerとは?
dockerのプロセス上からnVidia製GPUへのアクセスを可能にするユーティリティです. github.com
$docker [command]
を$nvidia-docker [command]
に置き換えるだけで,GPUへのアクセスが可能になるスゴいヤツです.
環境構築
Ubuntuのインストール
当たり前ですが,OSをインストールしないことには始まりません. が,GPU付きUbuntuのインストールって面倒なんですね. まさかここで詰むとは…という感じでした.
まずUSBメモリにUbuntu16.04 LTSのisoを焼き,ダイアログ通りインストールします.インストール完了後に再起動をすると,なんと起動しないではありませんか!
この問題と解決策は,様々な方が記事にしてくださっています.
参考文献1 qiita.com
2017/08/28追記: なぜかうまくリンクが貼れないので,「trouble shooting – グラボ増設してLinux install したら黒い画面」で検索していただけるとヒットすると思います.
問題は,nVidiaグラボとUbuntuのブートローダの相性が悪いということらしいです… 私は参考文献2の方法でインストールしました. 要約しますと
とりあえずUbuntuをインストール
インストールディスクを取り外さず,再起動
インストールディスクを起動し,「Try Ubuntu without installing」で"e"キーを押下
ブートローダの種類を"quiet splash"から"nomodeset"に変更する
F10で実行すると,Ubuntuの試用版が起動
アンマウントの後,再起動をかけるとUbuntuが立ち上がる
というような手順になります.なんでこんな面倒なの…
UbuntuにCUDAのドライバをインストール
こちらのブログを参考にさせていただきました.
まず,下記のCUDA Websiteから.debのダウンロードリンクを取得します.
CUDA Toolkit Download | NVIDIA Developer
ここで,OS > Archtechture > distribution > Version > Installer type(deb(Network))
と選択します.
Ubuntuにインストールする場合は,下記のような選択になるかと思います.
その後は,指示通りに
$ wget [上記サイトの"download(2.6kB)"のリンク先] $ sudo dpkg -i cuda-repo-ubuntu1604_8.0.61-1_amd64.deb $ sudo apt-get update $ sudo apt-get install cuda
を実行してあげることで,特にハマることなく完了できました.
nvcc -V
などでインストールが正しく完了しているかがわかります.
Dockerのインストール
Dockerをふつうにインストールします.ややハマりどころがありました.
$ sudo apt-get install Docker.io $ sudo usermod -aG docker `whoami` # sudo無しでDockerを動くようにする
すると,Dockerが立ち上がらないのですが,下記URLにあるように,Ubuntuを再起動すれば解決しました. qiita.com
次に,(私の環境では必要があったので)Dockerにプロキシを設定します. ちなみに,Dockerの設定に書くプロキシサーバのURLがどうも名前解決がされず,IP表示で全て書いています. これは環境によるのかDockerの問題なのかはわかっておりません.ご存じの方はおしえてくださると幸いです. 以下では,プロキシサーバのURLをxxx.xxx.xxx.xxx:xxxx/ とおくことにします.
$ mkdir -p /etc/systemd/system/docker.service.d $ touch /etc/systemd/system/docker.service.d/http-proxy.conf
作成したhttp-proxy.conf
内にプロキシサーバのURLを書いてあげます.
[Service] Environment="HTTP_PROXY=http://xxx.xxx.xxx.xxx:xxxx/"
同様にhttp-proxy.conf
も作成します.
[Service] Environment="HTTPS_PROXY=http://xxx.xxx.xxx.xxx:xxxx/"
Dockerを再起動します.
$ sudo systemctl daemon-reload $ sudo systemctl restart docker
これでDockerのインストールは完了です.
nvidia-dockerをインストールする
ご存じの方も多いと思いますが,通常のDockerからはGPUにアクセスすることができません. こんなときに用いるのがnvidia-dockerです. nvidia-dockerのインストールも,ハマりどころは少なかったです.
$ wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0-rc.3/nvidia-docker_1.0.0.rc.3-1_amd64.deb ` $ sudo dpkg -i /tmp/nvidia-docker*.deb && rm /tmp/nvidia-docker*.deb`
コレだけの手順で動くはずです.とりあえず動かしてみましょう. CUDA入りのUbuntuイメージをpullし,GPUの状態を確認するnvidia-smiを実行してみます.
nvidia-docker run nvidia/cuda nvidia-smi
するとこんな感じになりました.DockerプロセスからGPUにアクセス可能なことが確認できました. ちなみに通常のDockerだと
$docker run nvidia/cuda nvidia-smi bash: nvidia-smi: command not found
になってしまいます.
以上で環境構築は終わりです. 後はDocker Imageを立ててGPUをぶん回すだけですね. それでは皆様,楽しいGPUライフを!
【Python】ササッとTwitter Botを作ってみる
ゆるいプログラミングネタです. PythonでTwitterに天気を自動投稿させてみました. 今更感もありますが……
使ったもの
下ごしらえ
pip install python-twitter
でpython-twitterを導入します.
つくる
TwitWeather.py
という名前で作成しました.
アタマ
#!/usr/bin/env python # -*- coding: utf-8 -*- import twitter from system import conf # ./system/conf.pyにAPIキーなどを記述しています. import urllib # 天気取得時に使用 import urllib2 import json # const api = twitter.Api( consumer_key = conf.consumer_key, consumer_secret = conf.consumer_secret, access_token_key = conf.access_token_key, access_token_secret = conf.access_token_secret, ) # system/conf.pyからAPIキーなどを読んできます.
天気取得
def get_weather(): city = 'Ikoma,jp' url = 'http://api.openweathermap.org/data/2.5/forecast/daily?' query = { 'q': 'Ikoma,jp', 'mode': 'json', 'units': 'metric', 'cnt': '1', } req = urllib.urlencode(query) res = urllib2.urlopen(url + req) line = res.readline() #print line desc = [] desc.append(city) weather = json.loads(line)['list'][0]['weather'][0]['description'] desc.append(str(weather)) desc.append('min:') temp_min = json.loads(line)['list'][0]['temp']['min'] desc.append(str(temp_min)) desc.append('max:') temp_max = json.loads(line)['list'][0]['temp']['max'] desc.append(str(temp_max)) return desc
天気の取得にはOpenWeatherMap current weather and forecastを使いました.
クエリ http://api.openweathermap.org/data/2.5/forecast/daily?q=Ikoma,jp&mode=json&units=metric&cnt=1を投げると
{"cod":"200","message":0.0585,"city":{"id":1861749,"name":"Ikoma","coord":{"lon":135.699997,"lat":34.683331},"country":"JP","population":0,"sys":{"population":0}},"cnt":1,"list":[{"dt":1431914400,"temp":{"day":16.89,"min":16.45,"max":16.89,"night":16.45,"eve":16.89,"morn":16.89},"pressure":995.29,"humidity":96,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":1.59,"deg":120,"clouds":92,"rain":6.9}]}
が返ってきます.
ちなみに,jsonをパッと確認する際にはJSON整形サービスをよく利用させてもらっています.
今回は 天気,最低気温,最高気温 を表示したかったので上記のようにしています.
それらの情報をdesc
として返しています.
ツイート
def tweet(desc): content = '.@mhr380' for item in desc: content += ' ' content += item content += ' """Tweeted by Bot"""' print content status = api.PostUpdate(content)
先ほど返したdesc
をツイートしますが,コードはこれだけです.
APIにツイートしたい内容を渡してあげるだけです.
APIキーなど
https://apps.twitter.com/app/newに必要事項を入力するとAPIキーがもらえます.
それを,system/conf.py
に記述します.
#!/usr/bin/env python # -*- coding: utf-8 -*- consumer_key = 'xxxxxxxx' consumer_secret ='xxxxxxxx' access_token_key = 'xxxxxxxx' access_token_secret = 'xxxxxxxx'
herokuの準備
今回はheroku上で動かします.設定ファイルとしてProcfile
(拡張子なし) とrequirements.txt
が必要になります.
まずProcfile
は
bot: python TwitWeather.py
のように記述します.
次に,requirements.txt
には,用いた外部ライブラリおよびそのバージョンを記述します.
今回使用したライブラリはpython-twitter
のみで,そのバージョンはpip list
で調べることができます.
で,requirements.txt
には
python-twitter==2.2
と記述します.
デプロイ
heroku上にデプロイします.ご存知の通り,デプロイにはgitを用いるので,コミットしておきましょう. なお,手順などはこちらのブログ記事を参考に行いました.
firstspring1845.hatenablog.com
完成?
こんな感じで,勝手に天気をツイートしてくれます.
今後
(もうちょいテクノロジー感のあることをしたい)
参考
Python&Qtでアプリを作って,.app形式にするまでのメモ
最近ようやくGUI的なものを作るようになったので,一連の流れを備忘します. お題は,研究で使おうかなーと思っていた画像データセット*1を展開するためのアプリです. (もちろんGUIである必要性などは全くないですが……)
使ったもの
メイン
- Python 2.7.9
- Python-Qt4(GUIフレームワーク)
- Py2app(.pyファイルを.app形式に変換してくれるすごいやつ)
- インストールは
pip install py2app
でOK.
- インストールは
アプリの目的のために使ったもの
- OpenCV
- NumPy
- h5py(データセットの形式.h5を扱うためのモジュール.http://www.h5py.org)
つくる
作ったものはこちら.
GUI部と演算(?)部は分けております.
出来上がりはこんな感じ.
.app形式に変換する
こちらの記事を参考にしました. http://www.atsuhiro-me.net/python/dev/py2app
- まず,
pip install py2app
で,py2appをインストール. py2applet --make-setup hd5Extractor_gui.py
を実行すると,'setup.py'が生成される.- ちなみに自動生成された'setup.py'の中身はこんな感じ.
python setup.py py2app -A
により,ビルドを実行../dist/
と./build/
が生成され,./dist/
の中に.app
形式の実行ファイルが生成される.
みたいな流れになっております.
こんな形でプログラムを固めておくと,スクリプトがある場所を探す手間もなく,いつものアプリケーションを開くように実行することができ,結構ラクだなーと思ったりしています.
OpenMPとOpenCVを使って書いたC++のコードをCMakeでビルドするときのメモ.
お久しぶりです.(すごくお久しぶりです)
OpenMPとOpenCVを使って書いたC++のコードをCMakeでビルドするときのメモ.
の前に.
CMake
いろんなライブラリを使ったソースをコンパイルするときにMakefileを頑張って書くのは面倒なので,ありがたく使っています.
使い方としては,CMakeLists.txtに
「◯◯というライブラリを使いたいからどうにかして!」みたいなノリで書いて,cmake <path/to/CMakeLists.txt>
を実行すると,うまいこと(大量の中間ファイルを
吐き出しながら)Makefileを生成してくれます.
なお,最初に参考にしたのはこちら
*2
*3
.
OpenMP
OpenMPは、並列コンピューティング環境を利用するために用いられる標準化された基盤。OpenMPは主に共有メモリ型並列計算機で用いられる。*4
とても小さな労力で並列化が可能ということで,最近使い始めました.
CMakeLists.txt
で,こちらがOpenMPとOpenCVに対応したCMakeLists.txtです.
cmake_minimum_required(VERSION 2.8) project( sample ) find_package( OpenMP ) if (OPENMP_FOUND) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif() find_package( OpenCV REQUIRED ) add_executable( sample sample.cpp ) target_link_libraries( sample ${OpenCV_LIBS} )
このあとにmake
でビルドしてあげると,簡単に実行ファイルを生成することができます.
MacのターミナルでPOV-Ray
なんでこの情報にたどり着くのが遅かったのか……
brew install povray
でPOV-Rayがインストールできました。
先人に感謝。
関西CVPRML勉強会で知見を広げてきた
こんばんは、ミハラです。 10/4(土)に大阪府立大i-siteなんばで行われた「関西CV・PRML勉強会(@kansaicvprml)」へ初参加してきましたので、その感想をつらつらと。
内容
今回は、CVPR,ECCVで発表された最新論文の紹介を通して、 普段の研究・開発分野とは異なる技術について知る機会にしようという趣旨だそうです。
4名の発表者が最新論文についてプレゼンすると聞いてワクワクしていたのですが、 色々あって*1発表することになってました。
以下に概要をば。
発表1
最初は@lachesis1120さんによる領域分割をめっちゃ早くやろう! というCVPR2014の論文*2のご紹介。
領域分割計算を高速に行うために、求めた領域から効率よく物体候補を算出するGroupingアルゴリズムの提案で、 画像ピラミッドを生成し、いろんなスケールでの領域分割を行い、別々に一般的な手法で領域分割を行って、「だいたいこのへんが境界だろう」という情報を統合してから、詳細な分割を行うというのが概要だったように思います(合ってますかね?)。
ただやっぱり情報量が増えるので、固有ベクトルの計算を高速化してあげようというのがすごいところだそうで。
発表2
続いては@progranateさんのご発表です。手ブレ画像を復元する技術はすでにありますが、縞状アーティファクト(リンギングと呼ぶ)が発生してしまいますが、それを検出して綺麗にしてあげましょう! という論文*3のご紹介でした。
デコンボリューション自体は色々な手法があるわけですが、この論文では検出に重点を置いていたようで。 なぜ手ブレを除去するとリンギングが発生するか、どうやってそれを取り除くか、などの説明がわかりやすくて、お手本にしたい発表だと終始感じておりました。
あと、ECCV参加記がとっても面白かったです。
(ヨーロッパではSuperdry 極度乾燥(しなさい)という洋服ブランドが流行っているとか)
発表3
我が師匠(勝手にそう思ってる)田中さんのご発表は、プロジェクタでパターンを投影してあげると測距・法線・BRDF計測など色々なことができますが、プロジェクタの被写界深度が浅いため、限られた領域でしかうまく測定ができないという問題や、半透明物体のようなものの測定誤差を改善しよう! という論文*4でした。
パターン投影で3次元復元をしようと思ったら、やっぱり半透明物体は距離推定の誤差が大きくなるわけですが、この手法ではそういうミスを減らしてあげているようで、結構正確に推定がなされていてびっくりでした。
発表4
私の発表でした。 ライトフィールドを取得して、邪魔な遮蔽物を消してしまおう! という論文*5の紹介をさせていただきました。
発表5
@beat_itudeさんのご発表で、 写真に写っている人が着用している服などをピクセル単位でラベリングしてあげよう! という論文*6のご紹介でした。 ICCV2011で提案された進化版SVMみたいなやつ*7を適用していたりと 最新技術ゴリゴリでしたが、わかりやすく解説していただき、機械学習系に関して知見が深まりました。 しかし、結果として示されていた衣服推定精度はすごいと感心せざるを得ませんでした。
まとめ的な
聴講した感想
皆さんわかりやすくご発表していただいたのですが、やっぱり自分の数学力・機械学習系の知識の無さで、全てを理解することができなかったというのが正直なところです。 しかし、確実に知識の裾野は広がったなというのが感想です。 最適化・固有値問題・(余裕があればPR・ML)について理解を深めていかなきゃと感じました。 (追記) データ項+スムースネス項のエネルギー最小化問題が定番手法になってるので、使いこなせるようにならなきゃ……
自分の発表
発表者がDホルダー、D学生で私だけM1だったので、皆さんと比較して発表の質は低かったなと感じました。 やっぱり論文中の数式が全然追えてなかったのですが、あの場では皆さん気になるところだったかと思いますので、ちゃんと理解して説明するべきだったなというのが心残りです。
その他
懇親会たのしかったです。色々ごちそうさまでした。
最後に
次回も参加します! (発表するかは未定)
あと、記事に掲載した発表概要に誤り*8があればぜひ教えていただきたいです。
*2:P. Arbelaez, et al. , "Multiscale Combinatorial Grouping", CVPR, 2014
*3:A. Mosleh, et al., Image Deconvolution Ringing Artifact Detection and Removal via PSF Frequency Analysis, ECCV2014
*4:S. Achar, et al., Multi Focus Structured Light for RecoveringScene Shape and Global Illumination, ECCV2014
*5:T. Yang, et al., All-in-Focus Synthetic Aperture Imaging, ECCV2014
*6:W. Yang, et al., Clothing Co-Parsing by Joint Image Segmentation and Labeling
*7:T. Malisiewicz, et al., Ensemble of Exemplar-SVMs for Object Detection and Beyond, ICCV2011
*8:10.6 一部修正しました