mirror of https://github.com/opencv/opencv.git
* removed OpenGLFuncTab, now extensions are loaded internally * renamed GlTexture -> GlTexture2D * added support of GlBuffer and GlTexture2D to InputArray/OutputArray * added ELEMENT_ARRAY_BUFFER and PIXEL_PACK_BUFFER targets * added copyFrom/copyTo method for GlBuffer and GlTexture2D * removed GlFont * removed pointCloudShow * removed OpenGLCleanCallbackpull/258/merge
parent
2eebd8d939
commit
08fbf667f9
22 changed files with 5989 additions and 2907 deletions
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,625 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp" |
||||
|
||||
#if defined(HAVE_CUDA) && defined(HAVE_OPENGL) |
||||
|
||||
/////////////////////////////////////////////
|
||||
// GlBuffer
|
||||
|
||||
PARAM_TEST_CASE(GlBuffer, cv::Size, MatType) |
||||
{ |
||||
cv::Size size; |
||||
int type; |
||||
|
||||
virtual void SetUp() |
||||
{ |
||||
size = GET_PARAM(0); |
||||
type = GET_PARAM(1); |
||||
} |
||||
}; |
||||
|
||||
TEST_P(GlBuffer, Constructor1) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlBuffer buf(size.height, size.width, type); |
||||
|
||||
EXPECT_EQ(size.height, buf.rows()); |
||||
EXPECT_EQ(size.width, buf.cols()); |
||||
EXPECT_EQ(type, buf.type()); |
||||
|
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, Constructor2) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlBuffer buf(size, type); |
||||
|
||||
EXPECT_EQ(size.height, buf.rows()); |
||||
EXPECT_EQ(size.width, buf.cols()); |
||||
EXPECT_EQ(type, buf.type()); |
||||
|
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, ConstructorFromMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
|
||||
cv::GlBuffer buf(gold); |
||||
|
||||
cv::Mat bufData; |
||||
buf.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 0); |
||||
|
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, ConstructorFromGpuMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
cv::gpu::GpuMat d_gold(gold); |
||||
|
||||
cv::GlBuffer buf(d_gold); |
||||
|
||||
cv::Mat bufData; |
||||
buf.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 0); |
||||
|
||||
buf.release(); |
||||
d_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, ConstructorFromGlBuffer) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlBuffer buf_gold(size, type); |
||||
cv::GlBuffer buf(buf_gold); |
||||
|
||||
EXPECT_EQ(buf_gold.bufId(), buf.bufId()); |
||||
EXPECT_EQ(buf_gold.rows(), buf.rows()); |
||||
EXPECT_EQ(buf_gold.cols(), buf.cols()); |
||||
EXPECT_EQ(buf_gold.type(), buf.type()); |
||||
|
||||
buf.release(); |
||||
buf_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, ConstructorFromGlTexture2D) |
||||
{ |
||||
const int depth = CV_MAT_DEPTH(type); |
||||
const int cn = CV_MAT_CN(type); |
||||
|
||||
if (depth != CV_32F || cn == 2) |
||||
return; |
||||
|
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, 1.0); |
||||
cv::GlTexture2D tex_gold(gold); |
||||
|
||||
cv::GlBuffer buf(tex_gold); |
||||
|
||||
cv::Mat bufData; |
||||
buf.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 1e-2); |
||||
|
||||
buf.release(); |
||||
tex_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, Create) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlBuffer buf; |
||||
buf.create(size.height, size.width, type); |
||||
|
||||
EXPECT_EQ(size.height, buf.rows()); |
||||
EXPECT_EQ(size.width, buf.cols()); |
||||
EXPECT_EQ(type, buf.type()); |
||||
|
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, CopyFromMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
|
||||
cv::GlBuffer buf; |
||||
buf.copyFrom(gold); |
||||
|
||||
cv::Mat bufData; |
||||
buf.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 0); |
||||
|
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, CopyFromGpuMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
cv::gpu::GpuMat d_gold(gold); |
||||
|
||||
cv::GlBuffer buf; |
||||
buf.copyFrom(d_gold); |
||||
|
||||
cv::Mat bufData; |
||||
buf.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 0); |
||||
|
||||
buf.release(); |
||||
d_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, CopyFromGlBuffer) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
cv::GlBuffer buf_gold(gold); |
||||
|
||||
cv::GlBuffer buf; |
||||
buf.copyFrom(buf_gold); |
||||
|
||||
EXPECT_NE(buf_gold.bufId(), buf.bufId()); |
||||
|
||||
cv::Mat bufData; |
||||
buf.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 0); |
||||
|
||||
buf.release(); |
||||
buf_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, CopyFromGlTexture2D) |
||||
{ |
||||
const int depth = CV_MAT_DEPTH(type); |
||||
const int cn = CV_MAT_CN(type); |
||||
|
||||
if (depth != CV_32F || cn == 2) |
||||
return; |
||||
|
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, 1.0); |
||||
cv::GlTexture2D tex_gold(gold); |
||||
|
||||
cv::GlBuffer buf; |
||||
buf.copyFrom(tex_gold); |
||||
|
||||
cv::Mat bufData; |
||||
buf.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 1e-2); |
||||
|
||||
buf.release(); |
||||
tex_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, CopyToGpuMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
|
||||
cv::GlBuffer buf(gold); |
||||
cv::gpu::GpuMat dst; |
||||
buf.copyTo(dst); |
||||
|
||||
EXPECT_MAT_NEAR(gold, dst, 0); |
||||
|
||||
dst.release(); |
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, CopyToGlBuffer) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
cv::GlBuffer buf(gold); |
||||
|
||||
cv::GlBuffer dst; |
||||
buf.copyTo(dst); |
||||
|
||||
EXPECT_NE(buf.bufId(), dst.bufId()); |
||||
|
||||
cv::Mat bufData; |
||||
dst.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 0); |
||||
|
||||
dst.release(); |
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, CopyToGlTexture2D) |
||||
{ |
||||
const int depth = CV_MAT_DEPTH(type); |
||||
const int cn = CV_MAT_CN(type); |
||||
|
||||
if (depth != CV_32F || cn == 2) |
||||
return; |
||||
|
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, 1.0); |
||||
cv::GlBuffer buf(gold); |
||||
|
||||
cv::GlTexture2D tex; |
||||
buf.copyTo(tex); |
||||
|
||||
cv::Mat texData; |
||||
tex.copyTo(texData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, texData, 1e-2); |
||||
|
||||
tex.release(); |
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, Clone) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
cv::GlBuffer buf(gold); |
||||
|
||||
cv::GlBuffer dst = buf.clone(); |
||||
|
||||
EXPECT_NE(buf.bufId(), dst.bufId()); |
||||
|
||||
cv::Mat bufData; |
||||
dst.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 0); |
||||
|
||||
dst.release(); |
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, MapHost) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
cv::GlBuffer buf(gold); |
||||
|
||||
cv::Mat dst = buf.mapHost(); |
||||
|
||||
EXPECT_MAT_NEAR(gold, dst, 0); |
||||
|
||||
buf.unmapHost(); |
||||
|
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlBuffer, MapDevice) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type); |
||||
cv::GlBuffer buf(gold); |
||||
|
||||
cv::gpu::GpuMat dst = buf.mapDevice(); |
||||
|
||||
EXPECT_MAT_NEAR(gold, dst, 0); |
||||
|
||||
buf.unmapDevice(); |
||||
|
||||
buf.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
INSTANTIATE_TEST_CASE_P(OpenGL, GlBuffer, testing::Combine(DIFFERENT_SIZES, ALL_TYPES)); |
||||
|
||||
/////////////////////////////////////////////
|
||||
// GlTexture2D
|
||||
|
||||
PARAM_TEST_CASE(GlTexture2D, cv::Size, MatType) |
||||
{ |
||||
cv::Size size; |
||||
int type; |
||||
int depth; |
||||
int cn; |
||||
cv::GlTexture2D::Format format; |
||||
|
||||
virtual void SetUp() |
||||
{ |
||||
size = GET_PARAM(0); |
||||
type = GET_PARAM(1); |
||||
|
||||
depth = CV_MAT_DEPTH(type); |
||||
cn = CV_MAT_CN(type); |
||||
format = cn == 1 ? cv::GlTexture2D::DEPTH_COMPONENT : cn == 3 ? cv::GlTexture2D::RGB : cn == 4 ? cv::GlTexture2D::RGBA : cv::GlTexture2D::NONE; |
||||
} |
||||
}; |
||||
|
||||
TEST_P(GlTexture2D, Constructor1) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlTexture2D tex(size.height, size.width, format); |
||||
|
||||
EXPECT_EQ(size.height, tex.rows()); |
||||
EXPECT_EQ(size.width, tex.cols()); |
||||
EXPECT_EQ(format, tex.format()); |
||||
|
||||
tex.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, Constructor2) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlTexture2D tex(size, format); |
||||
|
||||
EXPECT_EQ(size.height, tex.rows()); |
||||
EXPECT_EQ(size.width, tex.cols()); |
||||
EXPECT_EQ(format, tex.format()); |
||||
|
||||
tex.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, ConstructorFromMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
|
||||
cv::GlTexture2D tex(gold); |
||||
|
||||
cv::Mat texData; |
||||
tex.copyTo(texData, depth); |
||||
|
||||
EXPECT_MAT_NEAR(gold, texData, 1e-2); |
||||
|
||||
tex.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, ConstructorFromGpuMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
cv::gpu::GpuMat d_gold(gold); |
||||
|
||||
cv::GlTexture2D tex(d_gold); |
||||
|
||||
cv::Mat texData; |
||||
tex.copyTo(texData, depth); |
||||
|
||||
EXPECT_MAT_NEAR(gold, texData, 1e-2); |
||||
|
||||
tex.release(); |
||||
d_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, ConstructorFromGlBuffer) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
cv::GlBuffer buf_gold(gold); |
||||
|
||||
cv::GlTexture2D tex(buf_gold); |
||||
|
||||
cv::Mat texData; |
||||
tex.copyTo(texData, depth); |
||||
|
||||
EXPECT_MAT_NEAR(gold, texData, 1e-2); |
||||
|
||||
tex.release(); |
||||
buf_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, ConstructorFromGlTexture2D) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlTexture2D tex_gold(size, format); |
||||
cv::GlTexture2D tex(tex_gold); |
||||
|
||||
EXPECT_EQ(tex_gold.texId(), tex.texId()); |
||||
EXPECT_EQ(tex_gold.rows(), tex.rows()); |
||||
EXPECT_EQ(tex_gold.cols(), tex.cols()); |
||||
EXPECT_EQ(tex_gold.format(), tex.format()); |
||||
|
||||
tex.release(); |
||||
tex_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, Create) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::GlTexture2D tex; |
||||
tex.create(size.height, size.width, format); |
||||
|
||||
EXPECT_EQ(size.height, tex.rows()); |
||||
EXPECT_EQ(size.width, tex.cols()); |
||||
EXPECT_EQ(format, tex.format()); |
||||
|
||||
tex.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, CopyFromMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
|
||||
cv::GlTexture2D tex; |
||||
tex.copyFrom(gold); |
||||
|
||||
cv::Mat texData; |
||||
tex.copyTo(texData, depth); |
||||
|
||||
EXPECT_MAT_NEAR(gold, texData, 1e-2); |
||||
|
||||
tex.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, CopyFromGpuMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
cv::gpu::GpuMat d_gold(gold); |
||||
|
||||
cv::GlTexture2D tex; |
||||
tex.copyFrom(d_gold); |
||||
|
||||
cv::Mat texData; |
||||
tex.copyTo(texData, depth); |
||||
|
||||
EXPECT_MAT_NEAR(gold, texData, 1e-2); |
||||
|
||||
tex.release(); |
||||
d_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, CopyFromGlBuffer) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
cv::GlBuffer buf_gold(gold); |
||||
|
||||
cv::GlTexture2D tex; |
||||
tex.copyFrom(buf_gold); |
||||
|
||||
cv::Mat texData; |
||||
tex.copyTo(texData, depth); |
||||
|
||||
EXPECT_MAT_NEAR(gold, texData, 1e-2); |
||||
|
||||
tex.release(); |
||||
buf_gold.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, CopyToGpuMat) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
|
||||
cv::GlTexture2D tex(gold); |
||||
cv::gpu::GpuMat dst; |
||||
tex.copyTo(dst, depth); |
||||
|
||||
EXPECT_MAT_NEAR(gold, dst, 1e-2); |
||||
|
||||
dst.release(); |
||||
tex.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
TEST_P(GlTexture2D, CopyToGlBuffer) |
||||
{ |
||||
cv::namedWindow("test", cv::WINDOW_OPENGL); |
||||
|
||||
cv::Mat gold = randomMat(size, type, 0, depth == CV_8U ? 255 : 1); |
||||
|
||||
cv::GlTexture2D tex(gold); |
||||
|
||||
cv::GlBuffer dst; |
||||
tex.copyTo(dst, depth); |
||||
|
||||
cv::Mat bufData; |
||||
dst.copyTo(bufData); |
||||
|
||||
EXPECT_MAT_NEAR(gold, bufData, 1e-2); |
||||
|
||||
dst.release(); |
||||
tex.release(); |
||||
cv::destroyAllWindows(); |
||||
} |
||||
|
||||
INSTANTIATE_TEST_CASE_P(OpenGL, GlTexture2D, testing::Combine(DIFFERENT_SIZES, testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4))); |
||||
|
||||
#endif |
@ -1,357 +0,0 @@ |
||||
#include <cstring> |
||||
#include <cmath> |
||||
#include <iostream> |
||||
#include <sstream> |
||||
#include "opencv2/core/core.hpp" |
||||
#include "opencv2/core/opengl_interop.hpp" |
||||
#include "opencv2/highgui/highgui.hpp" |
||||
#include "opencv2/imgproc/imgproc.hpp" |
||||
#include "opencv2/calib3d/calib3d.hpp" |
||||
#include "opencv2/contrib/contrib.hpp" |
||||
|
||||
using namespace std; |
||||
using namespace cv; |
||||
using namespace cv::gpu; |
||||
|
||||
class PointCloudRenderer |
||||
{ |
||||
public: |
||||
PointCloudRenderer(const Mat& points, const Mat& img, double scale); |
||||
|
||||
void onMouseEvent(int event, int x, int y, int flags); |
||||
void draw(); |
||||
void update(int key, double aspect); |
||||
|
||||
int fov_; |
||||
|
||||
private: |
||||
int mouse_dx_; |
||||
int mouse_dy_; |
||||
|
||||
double yaw_; |
||||
double pitch_; |
||||
Point3d pos_; |
||||
|
||||
TickMeter tm_; |
||||
static const int step_; |
||||
int frame_; |
||||
|
||||
GlCamera camera_; |
||||
GlArrays pointCloud_; |
||||
string fps_; |
||||
}; |
||||
|
||||
bool stop = false; |
||||
|
||||
static void mouseCallback(int event, int x, int y, int flags, void* userdata) |
||||
{ |
||||
if (stop) |
||||
return; |
||||
|
||||
PointCloudRenderer* renderer = static_cast<PointCloudRenderer*>(userdata); |
||||
renderer->onMouseEvent(event, x, y, flags); |
||||
} |
||||
|
||||
static void openGlDrawCallback(void* userdata) |
||||
{ |
||||
if (stop) |
||||
return; |
||||
|
||||
PointCloudRenderer* renderer = static_cast<PointCloudRenderer*>(userdata); |
||||
renderer->draw(); |
||||
} |
||||
|
||||
int main(int argc, const char* argv[]) |
||||
{ |
||||
const char* keys = |
||||
"{ l left | | left image file name }" |
||||
"{ r right | | right image file name }" |
||||
"{ i intrinsic | | intrinsic camera parameters file name }" |
||||
"{ e extrinsic | | extrinsic camera parameters file name }" |
||||
"{ d ndisp | 256 | number of disparities }" |
||||
"{ s scale | 1.0 | scale factor for point cloud }" |
||||
"{ h help | | print help message }"; |
||||
|
||||
CommandLineParser cmd(argc, argv, keys); |
||||
|
||||
if (cmd.has("help")) |
||||
{ |
||||
cmd.printMessage(); |
||||
return 0; |
||||
} |
||||
|
||||
string left = cmd.get<string>("left"); |
||||
string right = cmd.get<string>("right"); |
||||
string intrinsic = cmd.get<string>("intrinsic"); |
||||
string extrinsic = cmd.get<string>("extrinsic"); |
||||
int ndisp = cmd.get<int>("ndisp"); |
||||
double scale = cmd.get<double>("scale"); |
||||
|
||||
if (!cmd.check()) |
||||
{ |
||||
cmd.printErrors(); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
if (left.empty() || right.empty()) |
||||
{ |
||||
cout << "Missed input images" << endl; |
||||
cout << "Avaible options:" << endl; |
||||
cmd.printMessage(); |
||||
return 0; |
||||
} |
||||
|
||||
if (intrinsic.empty() ^ extrinsic.empty()) |
||||
{ |
||||
cout << "Boss camera parameters must be specified" << endl; |
||||
cout << "Avaible options:" << endl; |
||||
cmd.printMessage(); |
||||
return 0; |
||||
} |
||||
|
||||
Mat imgLeftColor = imread(left, IMREAD_COLOR); |
||||
Mat imgRightColor = imread(right, IMREAD_COLOR); |
||||
|
||||
if (imgLeftColor.empty()) |
||||
{ |
||||
cout << "Can't load image " << left << endl; |
||||
return -1; |
||||
} |
||||
|
||||
if (imgRightColor.empty()) |
||||
{ |
||||
cout << "Can't load image " << right << endl; |
||||
return -1; |
||||
} |
||||
|
||||
Mat Q = Mat::eye(4, 4, CV_32F); |
||||
if (!intrinsic.empty() && !extrinsic.empty()) |
||||
{ |
||||
FileStorage fs; |
||||
|
||||
// reading intrinsic parameters
|
||||
fs.open(intrinsic, CV_STORAGE_READ); |
||||
if (!fs.isOpened()) |
||||
{ |
||||
cout << "Failed to open file " << intrinsic << endl; |
||||
return -1; |
||||
} |
||||
|
||||
Mat M1, D1, M2, D2; |
||||
fs["M1"] >> M1; |
||||
fs["D1"] >> D1; |
||||
fs["M2"] >> M2; |
||||
fs["D2"] >> D2; |
||||
|
||||
// reading extrinsic parameters
|
||||
fs.open(extrinsic, CV_STORAGE_READ); |
||||
if (!fs.isOpened()) |
||||
{ |
||||
cout << "Failed to open file " << extrinsic << endl; |
||||
return -1; |
||||
} |
||||
|
||||
Mat R, T, R1, P1, R2, P2; |
||||
fs["R"] >> R; |
||||
fs["T"] >> T; |
||||
|
||||
Size img_size = imgLeftColor.size(); |
||||
|
||||
Rect roi1, roi2; |
||||
stereoRectify(M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2); |
||||
|
||||
Mat map11, map12, map21, map22; |
||||
initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map11, map12); |
||||
initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, map21, map22); |
||||
|
||||
Mat img1r, img2r; |
||||
remap(imgLeftColor, img1r, map11, map12, INTER_LINEAR); |
||||
remap(imgRightColor, img2r, map21, map22, INTER_LINEAR); |
||||
|
||||
imgLeftColor = img1r(roi1); |
||||
imgRightColor = img2r(roi2); |
||||
} |
||||
|
||||
Mat imgLeftGray, imgRightGray; |
||||
cvtColor(imgLeftColor, imgLeftGray, COLOR_BGR2GRAY); |
||||
cvtColor(imgRightColor, imgRightGray, COLOR_BGR2GRAY); |
||||
|
||||
cvtColor(imgLeftColor, imgLeftColor, COLOR_BGR2RGB); |
||||
|
||||
Mat disp, points; |
||||
|
||||
StereoBM bm(0, ndisp); |
||||
|
||||
bm(imgLeftGray, imgRightGray, disp); |
||||
disp.convertTo(disp, CV_8U, 1.0 / 16.0); |
||||
|
||||
disp = disp(Range(21, disp.rows - 21), Range(ndisp, disp.cols - 21)).clone(); |
||||
imgLeftColor = imgLeftColor(Range(21, imgLeftColor.rows - 21), Range(ndisp, imgLeftColor.cols - 21)).clone(); |
||||
|
||||
reprojectImageTo3D(disp, points, Q); |
||||
|
||||
const string windowName = "OpenGL Sample"; |
||||
|
||||
namedWindow(windowName, WINDOW_OPENGL); |
||||
resizeWindow(windowName, 400, 400); |
||||
|
||||
PointCloudRenderer renderer(points, imgLeftColor, scale); |
||||
|
||||
createTrackbar("Fov", windowName, &renderer.fov_, 100); |
||||
setMouseCallback(windowName, mouseCallback, &renderer); |
||||
setOpenGlDrawCallback(windowName, openGlDrawCallback, &renderer); |
||||
|
||||
for(;;) |
||||
{ |
||||
int key = waitKey(10); |
||||
|
||||
if (key >= 0) |
||||
key = key & 0xff; |
||||
|
||||
if (key == 27) |
||||
{ |
||||
stop = true; |
||||
break; |
||||
} |
||||
|
||||
double aspect = getWindowProperty(windowName, WND_PROP_ASPECT_RATIO); |
||||
|
||||
key = tolower(key); |
||||
|
||||
renderer.update(key, aspect); |
||||
|
||||
updateWindow(windowName); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
const int PointCloudRenderer::step_ = 20; |
||||
|
||||
PointCloudRenderer::PointCloudRenderer(const Mat& points, const Mat& img, double scale) |
||||
{ |
||||
mouse_dx_ = 0; |
||||
mouse_dy_ = 0; |
||||
|
||||
fov_ = 0; |
||||
yaw_ = 0.0; |
||||
pitch_ = 0.0; |
||||
|
||||
frame_ = 0; |
||||
|
||||
camera_.setScale(Point3d(scale, scale, scale)); |
||||
|
||||
pointCloud_.setVertexArray(points); |
||||
pointCloud_.setColorArray(img, false); |
||||
|
||||
tm_.start(); |
||||
} |
||||
|
||||
inline int clamp(int val, int minVal, int maxVal) |
||||
{ |
||||
return max(min(val, maxVal), minVal); |
||||
} |
||||
|
||||
void PointCloudRenderer::onMouseEvent(int event, int x, int y, int /*flags*/) |
||||
{ |
||||
static int oldx = x; |
||||
static int oldy = y; |
||||
static bool moving = false; |
||||
|
||||
if (event == EVENT_LBUTTONDOWN) |
||||
{ |
||||
oldx = x; |
||||
oldy = y; |
||||
moving = true; |
||||
} |
||||
else if (event == EVENT_LBUTTONUP) |
||||
{ |
||||
moving = false; |
||||
} |
||||
|
||||
if (moving) |
||||
{ |
||||
mouse_dx_ = oldx - x; |
||||
mouse_dy_ = oldy - y; |
||||
} |
||||
else |
||||
{ |
||||
mouse_dx_ = 0; |
||||
mouse_dy_ = 0; |
||||
} |
||||
|
||||
const int mouseClamp = 300; |
||||
mouse_dx_ = clamp(mouse_dx_, -mouseClamp, mouseClamp); |
||||
mouse_dy_ = clamp(mouse_dy_, -mouseClamp, mouseClamp); |
||||
} |
||||
|
||||
static Point3d rotate(Point3d v, double yaw, double pitch) |
||||
{ |
||||
Point3d t1; |
||||
t1.x = v.x * cos(-yaw / 180.0 * CV_PI) - v.z * sin(-yaw / 180.0 * CV_PI); |
||||
t1.y = v.y; |
||||
t1.z = v.x * sin(-yaw / 180.0 * CV_PI) + v.z * cos(-yaw / 180.0 * CV_PI); |
||||
|
||||
Point3d t2; |
||||
t2.x = t1.x; |
||||
t2.y = t1.y * cos(pitch / 180.0 * CV_PI) - t1.z * sin(pitch / 180.0 * CV_PI); |
||||
t2.z = t1.y * sin(pitch / 180.0 * CV_PI) + t1.z * cos(pitch / 180.0 * CV_PI); |
||||
|
||||
return t2; |
||||
} |
||||
|
||||
void PointCloudRenderer::update(int key, double aspect) |
||||
{ |
||||
const Point3d dirVec(0.0, 0.0, -1.0); |
||||
const Point3d upVec(0.0, 1.0, 0.0); |
||||
const Point3d leftVec(-1.0, 0.0, 0.0); |
||||
|
||||
const double posStep = 0.1; |
||||
|
||||
const double mouseStep = 0.001; |
||||
|
||||
camera_.setPerspectiveProjection(30.0 + fov_ / 100.0 * 40.0, aspect, 0.1, 1000.0); |
||||
|
||||
yaw_ += mouse_dx_ * mouseStep; |
||||
pitch_ += mouse_dy_ * mouseStep; |
||||
|
||||
if (key == 'w') |
||||
pos_ += posStep * rotate(dirVec, yaw_, pitch_); |
||||
else if (key == 's') |
||||
pos_ -= posStep * rotate(dirVec, yaw_, pitch_); |
||||
else if (key == 'a') |
||||
pos_ += posStep * rotate(leftVec, yaw_, pitch_); |
||||
else if (key == 'd') |
||||
pos_ -= posStep * rotate(leftVec, yaw_, pitch_); |
||||
else if (key == 'q') |
||||
pos_ += posStep * rotate(upVec, yaw_, pitch_); |
||||
else if (key == 'e') |
||||
pos_ -= posStep * rotate(upVec, yaw_, pitch_); |
||||
|
||||
camera_.setCameraPos(pos_, yaw_, pitch_, 0.0); |
||||
|
||||
tm_.stop(); |
||||
|
||||
if (frame_++ >= step_) |
||||
{ |
||||
ostringstream ostr; |
||||
ostr << "FPS: " << step_ / tm_.getTimeSec(); |
||||
fps_ = ostr.str(); |
||||
|
||||
frame_ = 0; |
||||
tm_.reset(); |
||||
} |
||||
|
||||
tm_.start(); |
||||
} |
||||
|
||||
void PointCloudRenderer::draw() |
||||
{ |
||||
camera_.setupProjectionMatrix(); |
||||
camera_.setupModelViewMatrix(); |
||||
|
||||
render(pointCloud_); |
||||
|
||||
render(fps_, GlFont::get("Courier New", 16), Scalar::all(255), Point2d(3.0, 0.0)); |
||||
} |
@ -1,135 +0,0 @@ |
||||
#include <iostream> |
||||
#include <string> |
||||
|
||||
#include "opencv2/core/core.hpp" |
||||
#include "opencv2/core/gpumat.hpp" |
||||
#include "opencv2/core/opengl_interop.hpp" |
||||
#include "opencv2/gpu/gpu.hpp" |
||||
#include "opencv2/highgui/highgui.hpp" |
||||
#include "opencv2/contrib/contrib.hpp" |
||||
|
||||
using namespace std; |
||||
using namespace cv; |
||||
using namespace cv::gpu; |
||||
|
||||
struct Timer |
||||
{ |
||||
Timer(const string& msg_) |
||||
{ |
||||
msg = msg_; |
||||
|
||||
tm.reset(); |
||||
tm.start(); |
||||
} |
||||
|
||||
~Timer() |
||||
{ |
||||
tm.stop(); |
||||
cout << msg << " " << tm.getTimeMilli() << " ms\n"; |
||||
} |
||||
|
||||
string msg; |
||||
TickMeter tm; |
||||
}; |
||||
|
||||
int main(int argc, char* argv[]) |
||||
{ |
||||
if (argc < 2) |
||||
{ |
||||
cout << "Usage: " << argv[0] << " image" << endl; |
||||
return -1; |
||||
} |
||||
|
||||
try |
||||
{ |
||||
bool haveCuda = getCudaEnabledDeviceCount() > 0; |
||||
|
||||
const string openGlMatWnd = "OpenGL Mat"; |
||||
const string openGlBufferWnd = "OpenGL GlBuffer"; |
||||
const string openGlTextureWnd = "OpenGL GlTexture"; |
||||
const string openGlGpuMatWnd = "OpenGL GpuMat"; |
||||
const string matWnd = "Mat"; |
||||
|
||||
namedWindow(openGlMatWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); |
||||
namedWindow(openGlBufferWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); |
||||
namedWindow(openGlTextureWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); |
||||
if (haveCuda) |
||||
namedWindow(openGlGpuMatWnd, WINDOW_OPENGL | WINDOW_AUTOSIZE); |
||||
namedWindow("Mat", WINDOW_AUTOSIZE); |
||||
|
||||
Mat img = imread(argv[1]); |
||||
|
||||
if (haveCuda) |
||||
setGlDevice(); |
||||
|
||||
setOpenGlContext(openGlBufferWnd); |
||||
GlBuffer buf(img, GlBuffer::TEXTURE_BUFFER); |
||||
|
||||
setOpenGlContext(openGlTextureWnd); |
||||
GlTexture tex(img); |
||||
|
||||
GpuMat d_img; |
||||
if (haveCuda) |
||||
d_img.upload(img); |
||||
|
||||
cout << "=== First call\n\n"; |
||||
|
||||
{ |
||||
Timer t("OpenGL Mat "); |
||||
imshow(openGlMatWnd, img); |
||||
} |
||||
{ |
||||
Timer t("OpenGL GlBuffer "); |
||||
imshow(openGlBufferWnd, buf); |
||||
} |
||||
{ |
||||
Timer t("OpenGL GlTexture"); |
||||
imshow(openGlTextureWnd, tex); |
||||
} |
||||
if (haveCuda) |
||||
{ |
||||
Timer t("OpenGL GpuMat "); |
||||
imshow(openGlGpuMatWnd, d_img); |
||||
} |
||||
{ |
||||
Timer t("Mat "); |
||||
imshow(matWnd, img); |
||||
} |
||||
|
||||
waitKey(); |
||||
|
||||
cout << "\n=== Second call\n\n"; |
||||
|
||||
{ |
||||
Timer t("OpenGL Mat "); |
||||
imshow(openGlMatWnd, img); |
||||
} |
||||
{ |
||||
Timer t("OpenGL GlBuffer "); |
||||
imshow(openGlBufferWnd, buf); |
||||
} |
||||
{ |
||||
Timer t("OpenGL GlTexture"); |
||||
imshow(openGlTextureWnd, tex); |
||||
} |
||||
if (haveCuda) |
||||
{ |
||||
Timer t("OpenGL GpuMat "); |
||||
imshow(openGlGpuMatWnd, d_img); |
||||
} |
||||
{ |
||||
Timer t("Mat "); |
||||
imshow(matWnd, img); |
||||
} |
||||
|
||||
cout << "\n"; |
||||
|
||||
waitKey(); |
||||
} |
||||
catch(const exception& e) |
||||
{ |
||||
cout << e.what() << endl; |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,128 @@ |
||||
#include <iostream> |
||||
#include "cvconfig.h" |
||||
|
||||
#ifndef HAVE_OPENGL |
||||
int main() |
||||
{ |
||||
std::cerr << "Library was built without OpenGL support" << std::endl; |
||||
return -1; |
||||
} |
||||
#else |
||||
|
||||
#ifdef WIN32 |
||||
#define WIN32_LEAN_AND_MEAN 1 |
||||
#define NOMINMAX 1 |
||||
#include <windows.h> |
||||
#endif |
||||
|
||||
#if defined(__APPLE__) |
||||
#include <OpenGL/gl.h> |
||||
#include <OpenGL/glu.h> |
||||
#else |
||||
#include <GL/gl.h> |
||||
#include <GL/glu.h> |
||||
#endif |
||||
|
||||
#include "opencv2/core/core.hpp" |
||||
#include "opencv2/core/opengl_interop.hpp" |
||||
#include "opencv2/core/gpumat.hpp" |
||||
#include "opencv2/highgui/highgui.hpp" |
||||
|
||||
using namespace std; |
||||
using namespace cv; |
||||
using namespace cv::gpu; |
||||
|
||||
const int win_width = 800; |
||||
const int win_height = 640; |
||||
|
||||
struct DrawData |
||||
{ |
||||
GlArrays arr; |
||||
GlTexture2D tex; |
||||
GlBuffer indices; |
||||
}; |
||||
|
||||
void CV_CDECL draw(void* userdata); |
||||
|
||||
void CV_CDECL draw(void* userdata) |
||||
{ |
||||
static double angle = 0.0; |
||||
|
||||
DrawData* data = static_cast<DrawData*>(userdata); |
||||
|
||||
glMatrixMode(GL_PROJECTION); |
||||
glLoadIdentity(); |
||||
gluPerspective(45.0, (double)win_width / win_height, 0.1, 100.0); |
||||
|
||||
glMatrixMode(GL_MODELVIEW); |
||||
glLoadIdentity(); |
||||
gluLookAt(0, 0, 4, 0, 0, 0, 0, 1, 0); |
||||
glRotated(angle, 0, 1, 0); |
||||
|
||||
glEnable(GL_TEXTURE_2D); |
||||
data->tex.bind(); |
||||
|
||||
glDisable(GL_CULL_FACE); |
||||
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); |
||||
|
||||
render(data->arr, data->indices, RenderMode::TRIANGLES); |
||||
|
||||
angle += 0.3; |
||||
} |
||||
|
||||
int main(int argc, char* argv[]) |
||||
{ |
||||
if (argc < 2) |
||||
{ |
||||
cout << "Usage: " << argv[0] << " image" << endl; |
||||
return -1; |
||||
} |
||||
|
||||
Mat img = imread(argv[1]); |
||||
if (img.empty()) |
||||
{ |
||||
cerr << "Can't open image " << argv[1] << endl; |
||||
return -1; |
||||
} |
||||
|
||||
namedWindow("OpenGL", WINDOW_OPENGL); |
||||
resizeWindow("OpenGL", win_width, win_height); |
||||
|
||||
Mat_<Vec2f> vertex(1, 4); |
||||
vertex << Vec2f(-1, 1), Vec2f(-1, -1), Vec2f(1, -1), Vec2f(1, 1); |
||||
|
||||
Mat_<Vec2f> texCoords(1, 4); |
||||
texCoords << Vec2f(0, 0), Vec2f(0, 1), Vec2f(1, 1), Vec2f(1, 0); |
||||
|
||||
Mat_<int> indices(1, 6); |
||||
indices << 0, 1, 2, 2, 3, 0; |
||||
|
||||
DrawData data; |
||||
|
||||
data.arr.setVertexArray(vertex); |
||||
data.arr.setTexCoordArray(texCoords); |
||||
data.arr.setAutoRelease(false); |
||||
|
||||
data.indices.copyFrom(indices); |
||||
data.indices.setAutoRelease(false); |
||||
|
||||
data.tex.copyFrom(img); |
||||
data.tex.setAutoRelease(false); |
||||
|
||||
setOpenGlDrawCallback("OpenGL", draw, &data); |
||||
|
||||
for (;;) |
||||
{ |
||||
updateWindow("OpenGL"); |
||||
int key = waitKey(10); |
||||
if ((key & 0xff) == 27) |
||||
break; |
||||
} |
||||
|
||||
setOpenGlDrawCallback("OpenGL", 0, 0); |
||||
destroyAllWindows(); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#endif |
Loading…
Reference in new issue