OpenCV

OpenCVでカメラキャリブレーション

OpenCVを使ったカメラキャリブレーションをググると,まずCでの実装例が出てきて,次に比較的新しいpythonでの実装例が出てくるが,C++での実装例がいまいちヒットしない.

加えて,カメラキャリブレーションは基本的にあらかじめ用意したデータについて行うが,私は普段Webカメラを利用するので,データの収集とキャリブレーションを同時にできるといいな,というのがあった.

ので,作った.

リポジトリはこっち
https://github.com/Lait-au-Cafe/calibration

本当はできるだけシンプルにしたかったのだが,冒頭で述べたようにプリセットのデータがなくてもできるようにしつつ,でもプリセットのデータがあってもできる,という仕様にした結果少し複雑になってしまったように思う.

当該リポジトリを利用する際にはビルドにOpenCV3.xとpkg-configが必要なのに注意.

OpenCL with OpenCV (OpenCV-CL)を使ってみた.-RGB編-

前回は取得したフレームをcvtColorでグレー画像に変換してからOpenCL側へ渡す,というまどろっこしいことをしていましたが,実際カラー画像を扱えないとお話にならないので何とか使えないかと試行錯誤.

CUDAの場合はuchar3は構造体として実装されているようで[要出典],uchar(=グレー画像)の場合とほとんど同様に扱うことができるが,OpenCLのuchar3は少し違った仕様になっているようで,ucharの場合をそのまま拡張しただけではうまくいかない.(CUDAのコードも適当に整理して上げたいですね).

ucharなどをスカラ型と呼ぶのに対し,uchar3などはベクタ型と呼ばれますが,このベクタ型の配列にアクセスする場合はvloadnやvstorenを使う.

参考サイト
How vector pointers work in openCL
Vector Data Load and Store Functions

それを考慮して実際にRGB画像を扱って各要素にアクセスした例が以下.

やっていることは至極単純なグレースケール化のみ.
今回もよくわかっていない点として,widthがいつでもUMatのpitchと等しくなるのか,という点.
例えば,CUDAの場合はx+y * widthとやるとうまくいかなくて,x+y * pitchのようにしなければいけない.つまり要素数はwidth分だが,各行当たりのメモリはもう少し余裕をもって確保されている.このpitchの値はcudaMallocPitchでメモリをアロケートする際に一緒にもらえる.
今回のOpenCV-CLの場合はOpenCV側の提供するUMatを使っているため問題ないのだろうか.
一応UMatもプロパティとしてstepやoffsetを持っているため,これを考慮せずにindexingしても大丈夫なんだろうかいやでも今のところうまくいってるしなあ,という感じ.
つまるところ,まだまだ検証の足りないコードなのでindexing周りで不具合が生じる可能性がある.

ちなみにindexingまわりで不具合があると出力画像はこんな風になりがち.
DXsiYnIVwAAS8bV

今日は以上.

OpenCL with OpenCV (OpenCV-CL)を使ってみた.

ここに “””つらみ””” があります.

image

環境を統一しようにもなかなか険しいものがある.(NvidiaのOpenCLはCUDAのドライバ入れれば動く…?)
世界に試されている.
でも今出先なので(=Geforceを積んでいるデスクトップ環境が使えないので),ノートPC上でできる環境を適当に決めて実装しないと無限に「グレブナ基底と代数多様体入門Ⅰ」を読んでしまう.無限に某ーロッパ企画のゲームをプレイする某員長の動画を見てしまう.

色々と考えた結果,OpenCVの環境作ればOpenCLが使えるらしいことを知って,じゃあこのOpenCL使ったらいいか,という気持ちになった.
OpenCVは全体的にドキュメンテーションに難があってほとんど参考にならないが,神先駆者様がいたのでこれをほとんどコピペでとりあえずサンプルコードを動かしてみた.

negaposi

とりあえずサンプルは動いたが今後手を加えていくとうまくいかなくなるかもしれないのでしばらく様子見.
カーネルコードをロードしてコンパイルするあたりでRustのシャドーイングを使いたくなったが残念ながらこれはC++なのでそうは問屋が卸さない.
世界中のスクリプトがすべてRustに置き換わらないかな.
せめて世界中の言語がすべて強い静的型付き言語にならないかな.

RustからC++を呼び出すこともなんとなく考えたが,参考サイトに
“C++ exceptions can mostly be caught in D, but that’s not a thing in Rust at all. “
とあって,確かになぁ…という気持ちになった.
ただでさえセーフな言語からアンセーフな言語を呼び出すのは厳しいのに,エラーハンドリングのやり方などの言語仕様も異なるとなると,考えることが増えそう(曖昧).

コードの印象としては,カーネルコードのロード,コンパイル,呼び出しの流れはPyOpenCLのほうが若干すっきりしていた気がする.(以前書いたPyOpenCLではホストコード中にカーネルコードを書いていたのに対し,今回は別ファイルにカーネルコードを書いているため,ファイルを読み込む処理が追加されているため煩雑に感じるのかもしれない).
カーネルコードの引数指定の部分は知らないと絶対にわからない仕様(詳しくは参考サイト様参照)なのにドキュメンテーションには記載が見当たらなかったので,このあたり敷居が高いなと感じた.

今回のコードで少し不思議に感じたのは,フレームのグレースケール画像(gray)が更新されたときにデバイスのバッファ(d_frame)へデータを送らなくてもちゃんと更新が反映された点.UMatは今回の例のように直接imshowに渡せるようだし,情報の受け渡しはOpenCV側がやってくれているのだろう.
つまり,cv::UMat d_frame = gray.getUMat(…);が実行された時点で,grayへの書き込みが自動的にd_frameに反映されるようにお膳立てしてくれているのかもしれない.(というかそもそも実体がGPU上に移るのかもしれない).
確信はないけど.

とりあえず今日はここまで.

参考サイト様
OpenCV 3.0.0での独自カーネルOpenCL
UMatの内部処理(OpenCL編)
Any updates on calling C++ from Rust

GolangでもOpenCVしたい!!!

人間の三大欲求の一つに「GolangでOpenCVをやりたい」というものがあります.
満たす必要があったので満たしました.

今回の環境はWindowsだったので, 基本的にはこちらで紹介されている通りにすればできました.
WindowsでgolangからOpenCVを呼び出してみた – ねずみとりんご

またWindowsでのGolang環境としてはVisual Studio Codeを使うといい感じです.
VSCodeでGoの開発環境を作成する方法まとめ

今回一点嵌ったのは, OpenCV3.0をGolangで使うことができないという点でした.
以前入れたOpenCVが3.0.0だったのでこれを流用しようと思ったのですが, gocはコンパイラとしてgccを利用するのに対し, OpenCV3.0以降ではgccでヘッダ周りをコンパイルできないため, GolangでOpenCVを用いるには適当に古いバージョンを持ってくる必要があります. 参考にしたサイトではOpenCV2.4.9を使用していたためこれを真似たところ, うまくいきました.
Opencv3 compilation issue with C API #6585

またこれ以外にも, C++のライブラリを使用する際には注意が必要です.
cgoでGolangとC++ライブラリをリンクするとき、何が起きているのか

以下はサンプルコードとなります. コードはこちらを参考にGoに移植しました.
カメラ画像を表示(C言語)

以上.

CUDA + OpenCVでWebカメラから取得した画像を変換

とりあえず簡単にグレースケールを作成.
実行すると画像の下の端が切れて悲しい. 理由は分からない.
実装した感想ですが, 「textureをつかえ」という感じなので, cudaBindTextureToArrayを使ってテクスチャを使っていきたい.
とりあえずミニマムで実装するとこんな感じになるんじゃないでしょうか.

参考 : http://fareastprogramming.hatenadiary.jp/entry/2016/11/10/181234
あとはCUDA落とした時に入ってるCUDA SamplesのsimpleTextureなども参考になるかと思います.

Visual StudioでOpenCVを使うメモ

開発環境をUnityからCUDAに移すときにWebカメラから取得した画像が欲しかったのでOpenCVと連携する必要があり, 長年忌避していたOpenCVを導入することになったのでメモ.
Visual Studioはこの辺の設定が難しいので苦手.
ちなみに試してみたのは昨日だけど記憶力が残念なので忘れている点がありそうなので注意.
今回落としたのはOpenCV 3.3.0, OSはWindows10

  1. このへんからソースを落としてきていい感じのディレクトリに移す(曖昧)
  2. [Project]->[Property]->[VC++ Directories]->[Include Directories]に”opencv\build\include”へのパスを追加する.
  3. [Project]->[Property]->[VC++ Directories]->[Library Directories]に”opencv\build\x64\vc14\lib”へのパスを追加する.
  4. ここまでやってビルドしてもリンカ周りで怒られる. かなしい.

  5. [Project]->[Property]->[Linker]->[General]->[Additional Library Directories]に”opencv\build\x64\vc14\lib”へのパスを追加する.
  6. [Project]->[Property]->[Linker]->[Input]->[Additional Dependencies]に”opencv\build\x64\vc14\lib”内の.libファイルの名前を追加.
    (今回はopencv_world330.lib, opencv_world330d.libの二つでした. )
    2017/11/17追記:この両方を追加するのは誤りでした. デバッグ時にはopencv_world330d.libを, リリース時にはopencv_world330.libを指定してください.
  7. ここまでやるとビルドは通るが.dllがないとキレられる. 厳しい世の中.

  8. “opencv\build\x64\vc14\bin”に先ほど追加した.libに対応する.dll(拡張子を除いた名前が同じ)があるのでこれを”C:\Windows\System32”, “C:\Windows\SysWOW64″にコピーする.
  9. 私の場合はこれで動きました.

上の作業は多分必要十分でなく, 冗長になっていると思います. 必要ない手順がどれなのかはわからない.
わかる人には自明だし, わからない人にはわからない. よってこの記事の情報量は0.
以上.

参考 : https://qiita.com/imura/items/d5fadbbcf1830019adce