はじめに
この記事ではcv::cuda::GpuMatの画像データをhighguiのウィンドウに表示する方法について紹介します.
前提条件
- CUDAが動作するPC上で動作させる必要あり
-
cv::cuda::GpuMatを使うため
-
cv::cuda::GpuMatを使うため
- OpenCVをビルドする際にWITH_CUDAを有効にする必要あり
-
cv::cuda::GpuMatを使うため
-
cv::cuda::GpuMatを使うため
- OpenCVをビルドする際にWITH_OPENGLを有効にする必要あり
- ウィンドウ描画にOpenGLの機能を用いるため
GpuMatデータの表示方法
cv::cuda::GpuMatの画像データをhighguiのウィンドウに表示する方法は大まかに以下の3パターンがあります.
- ホストメモリに転送して表示する
- highgui(OpenGL)を使って表示する
- ogl::Texture2Dを使って表示する
ホストメモリに転送して表示する
おそらく一般的に用いられているのは,
- cv::cuda::GpuMatのデータをdownloadメソッド等を使ってホスト側に転送する
-
cv::imshow
関数を使って表示する
という手順で表示する方法です.ただし,表示のためにホスト側にデータを転送する処理が入ってしまいます.
highgui(OpenGL)を使って表示する
downloadメソッド等の転送処理を介さずに表示する方法として最も簡単なのは
-
cv::namedWindow
関数のフラグとしてcv::WINDOW_OPENGLをセットする -
cv::imshow
関数にcv::cuda::GpuMatの変数を直接渡す
という手順で表示する方法です.highguiの内部処理では後述する**「ogl::Texture2Dを使って表示する」**とほぼ同じ処理が動いています.
ogl::Texture2Dを使って表示する
OpenCVにはOpenGLとの連携を行うための機能が入っています(詳細は公式ドキュメントを参照ください).
ここではcv::ogl::Texture2D
を使った方法について紹介することとします.
cv::ogl::Texture2D
を使ってGpuMatデータを表示するには,
-
cv::namedWindow
関数のフラグとしてcv::WINDOW_OPENGLをセットする - cv::cuda::GpuMatのデータからcv::ogl::Texture2Dのデータを生成する
-
cv::setOpenGlDrawCallback
関数によりOpenGLコールバック関数をセットする -
cv::updateWindow
関数によりウィンドウ描画内容を更新する
という手順で実現できます.
ウィンドウ描画内容の更新タイミング等を制御したい場合はこちらの方法を用いた方がよいかもしれません.
ウィンドウサイズ変更
画像サイズに応じて表示するウィンドウサイズを変えたい場合は,cv::resizeWindow
関数を呼ぶ必要があります.
サンプルコード
- ホストメモリに転送して表示する
- highgui(OpenGL)を使って表示する
- ogl::Texture2Dを使って表示する
これまで紹介した上記3つの方法を用いてcv::cuda::GpuMatの画像データをhighguiのウィンドウに表示するサンプルコードです.
#include <opencv2/core.hpp>
#include <opencv2/core/opengl.hpp>
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaimgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
void drawTexture_cb(void* userdata)
{
cv::ogl::Texture2D* texture = static_cast<cv::ogl::Texture2D*>(userdata);
cv::ogl::render(*texture);
}
int main(int argc, char *argv[])
{
cv::Mat src = cv::imread("lena.jpg", cv::IMREAD_UNCHANGED), dst;
if(src.empty())
{
return -1;
}
cv::cuda::GpuMat d_src(src), d_dst;
cv::cuda::cvtColor(d_src, d_dst, cv::COLOR_BGR2GRAY);
// highgui(normal)を使った表示
d_dst.download(dst); // ホストメモリに転送する
cv::namedWindow("normal", cv::WINDOW_AUTOSIZE);
cv::imshow("normal", dst);
// highgui(OpenGL)を使った表示
cv::namedWindow("highgui(OpenGL)", cv::WINDOW_AUTOSIZE | cv::WINDOW_OPENGL);
cv::imshow("highgui(OpenGL)", d_dst);
// ogl::Texture2Dを使った表示
cv::namedWindow("highgui(Texture2D)", cv::WINDOW_OPENGL);
cv::ogl::Texture2D texture(d_dst);
cv::resizeWindow("highgui(Texture2D)", d_dst.cols, d_dst.rows);
cv::setOpenGlContext("highgui(Texture2D)");
cv::setOpenGlDrawCallback("highgui(Texture2D)", drawTexture_cb, &texture);
cv::updateWindow("highgui(Texture2D)");
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
おわりに
この記事ではcv::cuda::GpuMatの画像データをhighguiのウィンドウに表示する方法について紹介しました.
備考
筆者は以下の環境で動作確認しました.
- OpenCV 3.1.0
- Windows 10 Pro(64bit)
- Visual Studio 2013 Update5
- NVIDIA CUDA Toolkit 7.5