@ -0,0 +1,26 @@ |
||||
if(NOT WITH_VTK OR ANDROID OR IOS) |
||||
return() |
||||
endif() |
||||
|
||||
if (HAVE_QT5) |
||||
message(STATUS "VTK is disabled because OpenCV is linked with Q5. Some VTK disributives are compiled with Q4 and therefore can't be linked together Qt5.") |
||||
return() |
||||
endif() |
||||
|
||||
find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture vtkIOExport NO_MODULE) |
||||
|
||||
if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) |
||||
find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) |
||||
endif() |
||||
|
||||
if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) |
||||
find_package(VTK 5.8 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) |
||||
endif() |
||||
|
||||
if(VTK_FOUND) |
||||
set(HAVE_VTK ON) |
||||
message(STATUS "Found VTK ver. ${VTK_VERSION} (usefile: ${VTK_USE_FILE})") |
||||
else() |
||||
set(HAVE_VTK OFF) |
||||
message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or set $VTK_DIR enviroment variable to VTK install subdirectory with VTKConfig.cmake file (for windows)") |
||||
endif() |
@ -0,0 +1,51 @@ |
||||
#!/bin/sh |
||||
|
||||
BASE_DIR=`dirname $0` |
||||
OPENCV_TEST_PATH=$BASE_DIR/@TEST_PATH@ |
||||
OPENCV_TEST_DATA_PATH=$BASE_DIR/sdk/etc/testdata/ |
||||
|
||||
if [ $# -ne 1 ]; then |
||||
echo "Device architecture is not preset in command line" |
||||
echo "Tests are available for architectures: `ls -m ${OPENCV_TEST_PATH}`" |
||||
echo "Usage: $0 <target_device_arch>" |
||||
return 1 |
||||
else |
||||
TARGET_ARCH=$1 |
||||
fi |
||||
|
||||
if [ -z `which adb` ]; then |
||||
echo "adb command was not found in PATH" |
||||
return 1 |
||||
fi |
||||
|
||||
adb push $OPENCV_TEST_DATA_PATH /sdcard/opencv_testdata |
||||
|
||||
adb shell "mkdir -p /data/local/tmp/opencv_test" |
||||
SUMMARY_STATUS=0 |
||||
for t in "$OPENCV_TEST_PATH/$TARGET_ARCH/"opencv_test_* "$OPENCV_TEST_PATH/$TARGET_ARCH/"opencv_perf_*; |
||||
do |
||||
test_name=`basename "$t"` |
||||
report="$test_name-`date --rfc-3339=date`.xml" |
||||
adb push $t /data/local/tmp/opencv_test/ |
||||
adb shell "export OPENCV_TEST_DATA_PATH=/sdcard/opencv_testdata && /data/local/tmp/opencv_test/$test_name --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:/data/local/tmp/opencv_test/$report" |
||||
adb pull "/data/local/tmp/opencv_test/$report" $report |
||||
TEST_STATUS=0 |
||||
if [ -e $report ]; then |
||||
if [ `grep -c "<fail" $report` -ne 0 ]; then |
||||
TEST_STATUS=2 |
||||
fi |
||||
else |
||||
TEST_STATUS=3 |
||||
fi |
||||
if [ $TEST_STATUS -ne 0 ]; then |
||||
SUMMARY_STATUS=$TEST_STATUS |
||||
fi |
||||
done |
||||
|
||||
if [ $SUMMARY_STATUS -eq 0 ]; then |
||||
echo "All OpenCV tests finished successfully" |
||||
else |
||||
echo "OpenCV tests finished with status $SUMMARY_STATUS" |
||||
fi |
||||
|
||||
return $SUMMARY_STATUS |
@ -0,0 +1,25 @@ |
||||
#!/bin/sh |
||||
|
||||
OPENCV_TEST_PATH=@CMAKE_INSTALL_PREFIX@/@OPENCV_TEST_INSTALL_PATH@ |
||||
export OPENCV_TEST_DATA_PATH=@CMAKE_INSTALL_PREFIX@/share/OpenCV/testdata |
||||
|
||||
SUMMARY_STATUS=0 |
||||
for t in "$OPENCV_TEST_PATH/"opencv_test_* "$OPENCV_TEST_PATH/"opencv_perf_*; |
||||
do |
||||
report="`basename "$t"`-`date --rfc-3339=date`.xml" |
||||
"$t" --perf_min_samples=1 --perf_force_samples=1 --gtest_output=xml:"$report" |
||||
TEST_STATUS=$? |
||||
if [ $TEST_STATUS -ne 0 ]; then |
||||
SUMMARY_STATUS=$TEST_STATUS |
||||
fi |
||||
done |
||||
|
||||
rm -f /tmp/__opencv_temp.* |
||||
|
||||
if [ $SUMMARY_STATUS -eq 0 ]; then |
||||
echo "All OpenCV tests finished successfully" |
||||
else |
||||
echo "OpenCV tests finished with status $SUMMARY_STATUS" |
||||
fi |
||||
|
||||
return $SUMMARY_STATUS |
@ -0,0 +1,2 @@ |
||||
# Environment setup for OpenCV testing |
||||
export OPENCV_TEST_DATA_PATH=@CMAKE_INSTALL_PREFIX@/share/OpenCV/testdata |
After Width: | Height: | Size: 31 KiB |
@ -0,0 +1,159 @@ |
||||
.. _creating_widgets: |
||||
|
||||
Creating Widgets |
||||
**************** |
||||
|
||||
Goal |
||||
==== |
||||
|
||||
In this tutorial you will learn how to |
||||
|
||||
.. container:: enumeratevisibleitemswithsquare |
||||
|
||||
* Create your own widgets using WidgetAccessor and VTK. |
||||
* Show your widget in the visualization window. |
||||
|
||||
Code |
||||
==== |
||||
|
||||
You can download the code from :download:`here <../../../../samples/cpp/tutorial_code/viz/creating_widgets.cpp>`. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
#include <opencv2/viz/vizcore.hpp> |
||||
#include <opencv2/viz/widget_accessor.hpp> |
||||
#include <iostream> |
||||
|
||||
#include <vtkPoints.h> |
||||
#include <vtkTriangle.h> |
||||
#include <vtkCellArray.h> |
||||
#include <vtkPolyData.h> |
||||
#include <vtkPolyDataMapper.h> |
||||
#include <vtkIdList.h> |
||||
#include <vtkActor.h> |
||||
#include <vtkProp.h> |
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
/** |
||||
* @class WTriangle |
||||
* @brief Defining our own 3D Triangle widget |
||||
*/ |
||||
class WTriangle : public viz::Widget3D |
||||
{ |
||||
public: |
||||
WTriangle(const Point3f &pt1, const Point3f &pt2, const Point3f &pt3, const viz::Color & color = viz::Color::white()); |
||||
}; |
||||
|
||||
/** |
||||
* @function WTriangle::WTriangle |
||||
*/ |
||||
WTriangle::WTriangle(const Point3f &pt1, const Point3f &pt2, const Point3f &pt3, const viz::Color & color) |
||||
{ |
||||
// Create a triangle |
||||
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); |
||||
points->InsertNextPoint(pt1.x, pt1.y, pt1.z); |
||||
points->InsertNextPoint(pt2.x, pt2.y, pt2.z); |
||||
points->InsertNextPoint(pt3.x, pt3.y, pt3.z); |
||||
|
||||
vtkSmartPointer<vtkTriangle> triangle = vtkSmartPointer<vtkTriangle>::New(); |
||||
triangle->GetPointIds()->SetId(0,0); |
||||
triangle->GetPointIds()->SetId(1,1); |
||||
triangle->GetPointIds()->SetId(2,2); |
||||
|
||||
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New(); |
||||
cells->InsertNextCell(triangle); |
||||
|
||||
// Create a polydata object |
||||
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New(); |
||||
|
||||
// Add the geometry and topology to the polydata |
||||
polyData->SetPoints(points); |
||||
polyData->SetPolys(cells); |
||||
|
||||
// Create mapper and actor |
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
mapper->SetInput(polyData); |
||||
#else |
||||
mapper->SetInputData(polyData); |
||||
#endif |
||||
|
||||
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
// Store this actor in the widget in order that visualizer can access it |
||||
viz::WidgetAccessor::setProp(*this, actor); |
||||
|
||||
// Set the color of the widget. This has to be called after WidgetAccessor. |
||||
setColor(color); |
||||
} |
||||
|
||||
/** |
||||
* @function main |
||||
*/ |
||||
int main() |
||||
{ |
||||
/// Create a window |
||||
viz::Viz3d myWindow("Creating Widgets"); |
||||
|
||||
/// Create a triangle widget |
||||
WTriangle tw(Point3f(0.0,0.0,0.0), Point3f(1.0,1.0,1.0), Point3f(0.0,1.0,0.0), viz::Color::red()); |
||||
|
||||
/// Show widget in the visualizer window |
||||
myWindow.showWidget("TRIANGLE", tw); |
||||
|
||||
/// Start event loop |
||||
myWindow.spin(); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
Explanation |
||||
=========== |
||||
|
||||
Here is the general structure of the program: |
||||
|
||||
* Extend Widget3D class to create a new 3D widget. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
class WTriangle : public viz::Widget3D |
||||
{ |
||||
public: |
||||
WTriangle(const Point3f &pt1, const Point3f &pt2, const Point3f &pt3, const viz::Color & color = viz::Color::white()); |
||||
}; |
||||
|
||||
* Assign a VTK actor to the widget. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
// Store this actor in the widget in order that visualizer can access it |
||||
viz::WidgetAccessor::setProp(*this, actor); |
||||
|
||||
* Set color of the widget. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
// Set the color of the widget. This has to be called after WidgetAccessor. |
||||
setColor(color); |
||||
|
||||
* Construct a triangle widget and display it in the window. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Create a triangle widget |
||||
WTriangle tw(Point3f(0.0,0.0,0.0), Point3f(1.0,1.0,1.0), Point3f(0.0,1.0,0.0), viz::Color::red()); |
||||
|
||||
/// Show widget in the visualizer window |
||||
myWindow.showWidget("TRIANGLE", tw); |
||||
|
||||
Results |
||||
======= |
||||
|
||||
Here is the result of the program. |
||||
|
||||
.. image:: images/red_triangle.png |
||||
:alt: Creating Widgets |
||||
:align: center |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 7.3 KiB |
@ -0,0 +1,118 @@ |
||||
.. _launching_viz: |
||||
|
||||
Launching Viz |
||||
************* |
||||
|
||||
Goal |
||||
==== |
||||
|
||||
In this tutorial you will learn how to |
||||
|
||||
.. container:: enumeratevisibleitemswithsquare |
||||
|
||||
* Open a visualization window. |
||||
* Access a window by its name. |
||||
* Start event loop. |
||||
* Start event loop for a given amount of time. |
||||
|
||||
Code |
||||
==== |
||||
|
||||
You can download the code from :download:`here <../../../../samples/cpp/tutorial_code/viz/launching_viz.cpp>`. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
#include <opencv2/viz/vizcore.hpp> |
||||
#include <iostream> |
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
/** |
||||
* @function main |
||||
*/ |
||||
int main() |
||||
{ |
||||
/// Create a window |
||||
viz::Viz3d myWindow("Viz Demo"); |
||||
|
||||
/// Start event loop |
||||
myWindow.spin(); |
||||
|
||||
/// Event loop is over when pressed q, Q, e, E |
||||
cout << "First event loop is over" << endl; |
||||
|
||||
/// Access window via its name |
||||
viz::Viz3d sameWindow = viz::getWindowByName("Viz Demo"); |
||||
|
||||
/// Start event loop |
||||
sameWindow.spin(); |
||||
|
||||
/// Event loop is over when pressed q, Q, e, E |
||||
cout << "Second event loop is over" << endl; |
||||
|
||||
/// Event loop is over when pressed q, Q, e, E |
||||
/// Start event loop once for 1 millisecond |
||||
sameWindow.spinOnce(1, true); |
||||
while(!sameWindow.wasStopped()) |
||||
{ |
||||
/// Interact with window |
||||
|
||||
/// Event loop for 1 millisecond |
||||
sameWindow.spinOnce(1, true); |
||||
} |
||||
|
||||
/// Once more event loop is stopped |
||||
cout << "Last event loop is over" << endl; |
||||
return 0; |
||||
} |
||||
|
||||
Explanation |
||||
=========== |
||||
|
||||
Here is the general structure of the program: |
||||
|
||||
* Create a window. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Create a window |
||||
viz::Viz3d myWindow("Viz Demo"); |
||||
|
||||
* Start event loop. This event loop will run until user terminates it by pressing **e**, **E**, **q**, **Q**. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Start event loop |
||||
myWindow.spin(); |
||||
|
||||
* Access same window via its name. Since windows are implicitly shared, **sameWindow** is exactly the same with **myWindow**. If the name does not exist, a new window is created. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Access window via its name |
||||
viz::Viz3d sameWindow = viz::get("Viz Demo"); |
||||
|
||||
* Start a controlled event loop. Once it starts, **wasStopped** is set to false. Inside the while loop, in each iteration, **spinOnce** is called to prevent event loop from completely stopping. Inside the while loop, user can execute other statements including those which interact with the window. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Event loop is over when pressed q, Q, e, E |
||||
/// Start event loop once for 1 millisecond |
||||
sameWindow.spinOnce(1, true); |
||||
while(!sameWindow.wasStopped()) |
||||
{ |
||||
/// Interact with window |
||||
|
||||
/// Event loop for 1 millisecond |
||||
sameWindow.spinOnce(1, true); |
||||
} |
||||
|
||||
Results |
||||
======= |
||||
|
||||
Here is the result of the program. |
||||
|
||||
.. image:: images/window_demo.png |
||||
:alt: Launching Viz |
||||
:align: center |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 2.5 KiB |
@ -0,0 +1,94 @@ |
||||
.. _Table-Of-Content-Viz: |
||||
|
||||
**OpenCV Viz** |
||||
----------------------------------------------------------- |
||||
|
||||
.. include:: ../../definitions/tocDefinitions.rst |
||||
|
||||
+ |
||||
.. tabularcolumns:: m{100pt} m{300pt} |
||||
.. cssclass:: toctableopencv |
||||
|
||||
================== =============================================================================== |
||||
|VizLaunchingViz| **Title:** :ref:`launching_viz` |
||||
|
||||
*Compatibility:* > OpenCV 3.0.0 |
||||
|
||||
*Author:* Ozan Tonkal |
||||
|
||||
You will learn how to launch a viz window. |
||||
|
||||
================== =============================================================================== |
||||
|
||||
.. |VizLaunchingViz| image:: ../launching_viz/images/window_demo.png |
||||
:height: 120pt |
||||
:width: 90pt |
||||
|
||||
+ |
||||
.. tabularcolumns:: m{100pt} m{300pt} |
||||
.. cssclass:: toctableopencv |
||||
|
||||
================ ============================================================================ |
||||
|WidgetPose| **Title:** :ref:`widget_pose` |
||||
|
||||
*Compatibility:* > OpenCV 3.0.0 |
||||
|
||||
*Author:* Ozan Tonkal |
||||
|
||||
You will learn how to change pose of a widget. |
||||
|
||||
================ ============================================================================ |
||||
|
||||
.. |WidgetPose| image:: ../widget_pose/images/widgetpose.png |
||||
:height: 90pt |
||||
:width: 90pt |
||||
|
||||
+ |
||||
.. tabularcolumns:: m{100pt} m{300pt} |
||||
.. cssclass:: toctableopencv |
||||
|
||||
================== ============================================================================ |
||||
|Transformations| **Title:** :ref:`transformations` |
||||
|
||||
*Compatibility:* > OpenCV 3.0.0 |
||||
|
||||
*Author:* Ozan Tonkal |
||||
|
||||
You will learn how to transform between global and camera frames. |
||||
|
||||
================== ============================================================================ |
||||
|
||||
.. |Transformations| image:: ../transformations/images/global_view_point.png |
||||
:height: 120pt |
||||
:width: 90pt |
||||
|
||||
+ |
||||
.. tabularcolumns:: m{100pt} m{300pt} |
||||
.. cssclass:: toctableopencv |
||||
|
||||
================== ============================================================================ |
||||
|CreatingWidgets| **Title:** :ref:`creating_widgets` |
||||
|
||||
*Compatibility:* > OpenCV 3.0.0 |
||||
|
||||
*Author:* Ozan Tonkal |
||||
|
||||
You will learn how to create your own widgets. |
||||
|
||||
================== ============================================================================ |
||||
|
||||
.. |CreatingWidgets| image:: ../creating_widgets/images/red_triangle.png |
||||
:height: 120pt |
||||
:width: 90pt |
||||
|
||||
.. raw:: latex |
||||
|
||||
\pagebreak |
||||
|
||||
.. toctree:: |
||||
:hidden: |
||||
|
||||
../launching_viz/launching_viz |
||||
../widget_pose/widget_pose |
||||
../transformations/transformations |
||||
../creating_widgets/creating_widgets |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,202 @@ |
||||
.. _transformations: |
||||
|
||||
Transformations |
||||
*************** |
||||
|
||||
Goal |
||||
==== |
||||
|
||||
In this tutorial you will learn how to |
||||
|
||||
.. container:: enumeratevisibleitemswithsquare |
||||
|
||||
* How to use makeTransformToGlobal to compute pose |
||||
* How to use makeCameraPose and Viz3d::setViewerPose |
||||
* How to visualize camera position by axes and by viewing frustum |
||||
|
||||
Code |
||||
==== |
||||
|
||||
You can download the code from :download:`here <../../../../samples/cpp/tutorial_code/viz/transformations.cpp>`. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
#include <opencv2/viz/vizcore.hpp> |
||||
#include <iostream> |
||||
#include <fstream> |
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
/** |
||||
* @function cvcloud_load |
||||
* @brief load bunny.ply |
||||
*/ |
||||
Mat cvcloud_load() |
||||
{ |
||||
Mat cloud(1, 1889, CV_32FC3); |
||||
ifstream ifs("bunny.ply"); |
||||
|
||||
string str; |
||||
for(size_t i = 0; i < 12; ++i) |
||||
getline(ifs, str); |
||||
|
||||
Point3f* data = cloud.ptr<cv::Point3f>(); |
||||
float dummy1, dummy2; |
||||
for(size_t i = 0; i < 1889; ++i) |
||||
ifs >> data[i].x >> data[i].y >> data[i].z >> dummy1 >> dummy2; |
||||
|
||||
cloud *= 5.0f; |
||||
return cloud; |
||||
} |
||||
|
||||
/** |
||||
* @function main |
||||
*/ |
||||
int main(int argn, char **argv) |
||||
{ |
||||
if (argn < 2) |
||||
{ |
||||
cout << "Usage: " << endl << "./transformations [ G | C ]" << endl; |
||||
return 1; |
||||
} |
||||
|
||||
bool camera_pov = (argv[1][0] == 'C'); |
||||
|
||||
/// Create a window |
||||
viz::Viz3d myWindow("Coordinate Frame"); |
||||
|
||||
/// Add coordinate axes |
||||
myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); |
||||
|
||||
/// Let's assume camera has the following properties |
||||
Point3f cam_pos(3.0f,3.0f,3.0f), cam_focal_point(3.0f,3.0f,2.0f), cam_y_dir(-1.0f,0.0f,0.0f); |
||||
|
||||
/// We can get the pose of the cam using makeCameraPose |
||||
Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); |
||||
|
||||
/// We can get the transformation matrix from camera coordinate system to global using |
||||
/// - makeTransformToGlobal. We need the axes of the camera |
||||
Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos); |
||||
|
||||
/// Create a cloud widget. |
||||
Mat bunny_cloud = cvcloud_load(); |
||||
viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); |
||||
|
||||
/// Pose of the widget in camera frame |
||||
Affine3f cloud_pose = Affine3f().translate(Vec3f(0.0f,0.0f,3.0f)); |
||||
/// Pose of the widget in global frame |
||||
Affine3f cloud_pose_global = transform * cloud_pose; |
||||
|
||||
/// Visualize camera frame |
||||
if (!camera_pov) |
||||
{ |
||||
viz::WCameraPosition cpw(0.5); // Coordinate axes |
||||
viz::WCameraPosition cpw_frustum(Vec2f(0.889484, 0.523599)); // Camera frustum |
||||
myWindow.showWidget("CPW", cpw, cam_pose); |
||||
myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose); |
||||
} |
||||
|
||||
/// Visualize widget |
||||
myWindow.showWidget("bunny", cloud_widget, cloud_pose_global); |
||||
|
||||
/// Set the viewer pose to that of camera |
||||
if (camera_pov) |
||||
myWindow.setViewerPose(cam_pose); |
||||
|
||||
/// Start event loop. |
||||
myWindow.spin(); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
Explanation |
||||
=========== |
||||
|
||||
Here is the general structure of the program: |
||||
|
||||
* Create a visualization window. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Create a window |
||||
viz::Viz3d myWindow("Transformations"); |
||||
|
||||
* Get camera pose from camera position, camera focal point and y direction. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Let's assume camera has the following properties |
||||
Point3f cam_pos(3.0f,3.0f,3.0f), cam_focal_point(3.0f,3.0f,2.0f), cam_y_dir(-1.0f,0.0f,0.0f); |
||||
|
||||
/// We can get the pose of the cam using makeCameraPose |
||||
Affine3f cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); |
||||
|
||||
* Obtain transform matrix knowing the axes of camera coordinate system. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// We can get the transformation matrix from camera coordinate system to global using |
||||
/// - makeTransformToGlobal. We need the axes of the camera |
||||
Affine3f transform = viz::makeTransformToGlobal(Vec3f(0.0f,-1.0f,0.0f), Vec3f(-1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), cam_pos); |
||||
|
||||
* Create a cloud widget from bunny.ply file |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Create a cloud widget. |
||||
Mat bunny_cloud = cvcloud_load(); |
||||
viz::WCloud cloud_widget(bunny_cloud, viz::Color::green()); |
||||
|
||||
* Given the pose in camera coordinate system, estimate the global pose. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Pose of the widget in camera frame |
||||
Affine3f cloud_pose = Affine3f().translate(Vec3f(0.0f,0.0f,3.0f)); |
||||
/// Pose of the widget in global frame |
||||
Affine3f cloud_pose_global = transform * cloud_pose; |
||||
|
||||
* If the view point is set to be global, visualize camera coordinate frame and viewing frustum. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Visualize camera frame |
||||
if (!camera_pov) |
||||
{ |
||||
viz::WCameraPosition cpw(0.5); // Coordinate axes |
||||
viz::WCameraPosition cpw_frustum(Vec2f(0.889484, 0.523599)); // Camera frustum |
||||
myWindow.showWidget("CPW", cpw, cam_pose); |
||||
myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose); |
||||
} |
||||
|
||||
* Visualize the cloud widget with the estimated global pose |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Visualize widget |
||||
myWindow.showWidget("bunny", cloud_widget, cloud_pose_global); |
||||
|
||||
* If the view point is set to be camera's, set viewer pose to **cam_pose**. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Set the viewer pose to that of camera |
||||
if (camera_pov) |
||||
myWindow.setViewerPose(cam_pose); |
||||
|
||||
Results |
||||
======= |
||||
|
||||
#. Here is the result from the camera point of view. |
||||
|
||||
.. image:: images/camera_view_point.png |
||||
:alt: Camera Viewpoint |
||||
:align: center |
||||
|
||||
#. Here is the result from global point of view. |
||||
|
||||
.. image:: images/global_view_point.png |
||||
:alt: Global Viewpoint |
||||
:align: center |
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,162 @@ |
||||
.. _widget_pose: |
||||
|
||||
Pose of a widget |
||||
**************** |
||||
|
||||
Goal |
||||
==== |
||||
|
||||
In this tutorial you will learn how to |
||||
|
||||
.. container:: enumeratevisibleitemswithsquare |
||||
|
||||
* Add widgets to the visualization window |
||||
* Use Affine3 to set pose of a widget |
||||
* Rotating and translating a widget along an axis |
||||
|
||||
Code |
||||
==== |
||||
|
||||
You can download the code from :download:`here <../../../../samples/cpp/tutorial_code/viz/widget_pose.cpp>`. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
#include <opencv2/viz/vizcore.hpp> |
||||
#include <opencv2/calib3d/calib3d.hpp> |
||||
#include <iostream> |
||||
|
||||
using namespace cv; |
||||
using namespace std; |
||||
|
||||
/** |
||||
* @function main |
||||
*/ |
||||
int main() |
||||
{ |
||||
/// Create a window |
||||
viz::Viz3d myWindow("Coordinate Frame"); |
||||
|
||||
/// Add coordinate axes |
||||
myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); |
||||
|
||||
/// Add line to represent (1,1,1) axis |
||||
viz::WLine axis(Point3f(-1.0f,-1.0f,-1.0f), Point3f(1.0f,1.0f,1.0f)); |
||||
axis.setRenderingProperty(viz::LINE_WIDTH, 4.0); |
||||
myWindow.showWidget("Line Widget", axis); |
||||
|
||||
/// Construct a cube widget |
||||
viz::WCube cube_widget(Point3f(0.5,0.5,0.0), Point3f(0.0,0.0,-0.5), true, viz::Color::blue()); |
||||
cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0); |
||||
|
||||
/// Display widget (update if already displayed) |
||||
myWindow.showWidget("Cube Widget", cube_widget); |
||||
|
||||
/// Rodrigues vector |
||||
Mat rot_vec = Mat::zeros(1,3,CV_32F); |
||||
float translation_phase = 0.0, translation = 0.0; |
||||
while(!myWindow.wasStopped()) |
||||
{ |
||||
/* Rotation using rodrigues */ |
||||
/// Rotate around (1,1,1) |
||||
rot_vec.at<float>(0,0) += CV_PI * 0.01f; |
||||
rot_vec.at<float>(0,1) += CV_PI * 0.01f; |
||||
rot_vec.at<float>(0,2) += CV_PI * 0.01f; |
||||
|
||||
/// Shift on (1,1,1) |
||||
translation_phase += CV_PI * 0.01f; |
||||
translation = sin(translation_phase); |
||||
|
||||
Mat rot_mat; |
||||
Rodrigues(rot_vec, rot_mat); |
||||
|
||||
/// Construct pose |
||||
Affine3f pose(rot_mat, Vec3f(translation, translation, translation)); |
||||
|
||||
myWindow.setWidgetPose("Cube Widget", pose); |
||||
|
||||
myWindow.spinOnce(1, true); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
Explanation |
||||
=========== |
||||
|
||||
Here is the general structure of the program: |
||||
|
||||
* Create a visualization window. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Create a window |
||||
viz::Viz3d myWindow("Coordinate Frame"); |
||||
|
||||
* Show coordinate axes in the window using CoordinateSystemWidget. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Add coordinate axes |
||||
myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); |
||||
|
||||
* Display a line representing the axis (1,1,1). |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Add line to represent (1,1,1) axis |
||||
viz::WLine axis(Point3f(-1.0f,-1.0f,-1.0f), Point3f(1.0f,1.0f,1.0f)); |
||||
axis.setRenderingProperty(viz::LINE_WIDTH, 4.0); |
||||
myWindow.showWidget("Line Widget", axis); |
||||
|
||||
* Construct a cube. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Construct a cube widget |
||||
viz::WCube cube_widget(Point3f(0.5,0.5,0.0), Point3f(0.0,0.0,-0.5), true, viz::Color::blue()); |
||||
cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0); |
||||
myWindow.showWidget("Cube Widget", cube_widget); |
||||
|
||||
* Create rotation matrix from rodrigues vector |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Rotate around (1,1,1) |
||||
rot_vec.at<float>(0,0) += CV_PI * 0.01f; |
||||
rot_vec.at<float>(0,1) += CV_PI * 0.01f; |
||||
rot_vec.at<float>(0,2) += CV_PI * 0.01f; |
||||
|
||||
... |
||||
|
||||
Mat rot_mat; |
||||
Rodrigues(rot_vec, rot_mat); |
||||
|
||||
* Use Affine3f to set pose of the cube. |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
/// Construct pose |
||||
Affine3f pose(rot_mat, Vec3f(translation, translation, translation)); |
||||
myWindow.setWidgetPose("Cube Widget", pose); |
||||
|
||||
* Animate the rotation using wasStopped and spinOnce |
||||
|
||||
.. code-block:: cpp |
||||
|
||||
while(!myWindow.wasStopped()) |
||||
{ |
||||
... |
||||
|
||||
myWindow.spinOnce(1, true); |
||||
} |
||||
|
||||
Results |
||||
======= |
||||
|
||||
Here is the result of the program. |
||||
|
||||
.. raw:: html |
||||
|
||||
<div align="center"> |
||||
<iframe width="420" height="315" src="https://www.youtube.com/embed/22HKMN657U0" frameborder="0" allowfullscreen></iframe> |
||||
</div> |
@ -0,0 +1,509 @@ |
||||
/*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.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, 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 the copyright holders 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*/
|
||||
|
||||
#ifndef __OPENCV_CORE_AFFINE3_HPP__ |
||||
#define __OPENCV_CORE_AFFINE3_HPP__ |
||||
|
||||
#ifdef __cplusplus |
||||
|
||||
#include <opencv2/core/core.hpp> |
||||
|
||||
namespace cv |
||||
{ |
||||
template<typename T> |
||||
class Affine3 |
||||
{ |
||||
public: |
||||
typedef T float_type; |
||||
typedef Matx<float_type, 3, 3> Mat3; |
||||
typedef Matx<float_type, 4, 4> Mat4; |
||||
typedef Vec<float_type, 3> Vec3; |
||||
|
||||
Affine3(); |
||||
|
||||
//Augmented affine matrix
|
||||
Affine3(const Mat4& affine); |
||||
|
||||
//Rotation matrix
|
||||
Affine3(const Mat3& R, const Vec3& t = Vec3::all(0)); |
||||
|
||||
//Rodrigues vector
|
||||
Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); |
||||
|
||||
//Combines all contructors above. Supports 4x4, 4x3, 3x3, 1x3, 3x1 sizes of data matrix
|
||||
explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0)); |
||||
|
||||
//From 16th element array
|
||||
explicit Affine3(const float_type* vals); |
||||
|
||||
static Affine3 Identity(); |
||||
|
||||
//Rotation matrix
|
||||
void rotation(const Mat3& R); |
||||
|
||||
//Rodrigues vector
|
||||
void rotation(const Vec3& rvec); |
||||
|
||||
//Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix;
|
||||
void rotation(const Mat& data); |
||||
|
||||
void linear(const Mat3& L); |
||||
void translation(const Vec3& t); |
||||
|
||||
Mat3 rotation() const; |
||||
Mat3 linear() const; |
||||
Vec3 translation() const; |
||||
|
||||
//Rodrigues vector
|
||||
Vec3 rvec() const; |
||||
|
||||
Affine3 inv(int method = cv::DECOMP_SVD) const; |
||||
|
||||
// a.rotate(R) is equivalent to Affine(R, 0) * a;
|
||||
Affine3 rotate(const Mat3& R) const; |
||||
|
||||
// a.rotate(R) is equivalent to Affine(rvec, 0) * a;
|
||||
Affine3 rotate(const Vec3& rvec) const; |
||||
|
||||
// a.translate(t) is equivalent to Affine(E, t) * a;
|
||||
Affine3 translate(const Vec3& t) const; |
||||
|
||||
// a.concatenate(affine) is equivalent to affine * a;
|
||||
Affine3 concatenate(const Affine3& affine) const; |
||||
|
||||
template <typename Y> operator Affine3<Y>() const; |
||||
|
||||
template <typename Y> Affine3<Y> cast() const; |
||||
|
||||
Mat4 matrix; |
||||
|
||||
#if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H |
||||
Affine3(const Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>& affine); |
||||
Affine3(const Eigen::Transform<T, 3, Eigen::Affine>& affine); |
||||
operator Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>() const; |
||||
operator Eigen::Transform<T, 3, Eigen::Affine>() const; |
||||
#endif |
||||
}; |
||||
|
||||
template<typename T> static |
||||
Affine3<T> operator*(const Affine3<T>& affine1, const Affine3<T>& affine2); |
||||
|
||||
template<typename T, typename V> static |
||||
V operator*(const Affine3<T>& affine, const V& vector); |
||||
|
||||
typedef Affine3<float> Affine3f; |
||||
typedef Affine3<double> Affine3d; |
||||
|
||||
static Vec3f operator*(const Affine3f& affine, const Vec3f& vector); |
||||
static Vec3d operator*(const Affine3d& affine, const Vec3d& vector); |
||||
|
||||
template<typename _Tp> class DataType< Affine3<_Tp> > |
||||
{ |
||||
public: |
||||
typedef Affine3<_Tp> value_type; |
||||
typedef Affine3<typename DataType<_Tp>::work_type> work_type; |
||||
typedef _Tp channel_type; |
||||
|
||||
enum { generic_type = 0, |
||||
depth = DataType<channel_type>::depth, |
||||
channels = 16, |
||||
fmt = DataType<channel_type>::fmt + ((channels - 1) << 8), |
||||
type = CV_MAKETYPE(depth, channels) |
||||
}; |
||||
|
||||
typedef Vec<channel_type, channels> vec_type; |
||||
}; |
||||
} |
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/// Implementaiton
|
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3() |
||||
: matrix(Mat4::eye()) |
||||
{} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3(const Mat4& affine) |
||||
: matrix(affine) |
||||
{} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3(const Mat3& R, const Vec3& t) |
||||
{ |
||||
rotation(R); |
||||
translation(t); |
||||
matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; |
||||
matrix.val[15] = 1; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3(const Vec3& _rvec, const Vec3& t) |
||||
{ |
||||
rotation(_rvec); |
||||
translation(t); |
||||
matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; |
||||
matrix.val[15] = 1; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3(const cv::Mat& data, const Vec3& t) |
||||
{ |
||||
CV_Assert(data.type() == cv::DataType<T>::type); |
||||
|
||||
if (data.cols == 4 && data.rows == 4) |
||||
{ |
||||
data.copyTo(matrix); |
||||
return; |
||||
} |
||||
else if (data.cols == 4 && data.rows == 3) |
||||
{ |
||||
rotation(data(Rect(0, 0, 3, 3))); |
||||
translation(data(Rect(3, 0, 1, 3))); |
||||
return; |
||||
} |
||||
|
||||
rotation(data); |
||||
translation(t); |
||||
matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; |
||||
matrix.val[15] = 1; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3(const float_type* vals) : matrix(vals) |
||||
{} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T> cv::Affine3<T>::Identity() |
||||
{ |
||||
return Affine3<T>(cv::Affine3<T>::Mat4::eye()); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
void cv::Affine3<T>::rotation(const Mat3& R) |
||||
{ |
||||
linear(R); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
void cv::Affine3<T>::rotation(const Vec3& _rvec) |
||||
{ |
||||
double rx = _rvec[0], ry = _rvec[1], rz = _rvec[2]; |
||||
double theta = std::sqrt(rx*rx + ry*ry + rz*rz); |
||||
|
||||
if (theta < DBL_EPSILON) |
||||
rotation(Mat3::eye()); |
||||
else |
||||
{ |
||||
const double I[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; |
||||
|
||||
double c = std::cos(theta); |
||||
double s = std::sin(theta); |
||||
double c1 = 1. - c; |
||||
double itheta = theta ? 1./theta : 0.; |
||||
|
||||
rx *= itheta; ry *= itheta; rz *= itheta; |
||||
|
||||
double rrt[] = { rx*rx, rx*ry, rx*rz, rx*ry, ry*ry, ry*rz, rx*rz, ry*rz, rz*rz }; |
||||
double _r_x_[] = { 0, -rz, ry, rz, 0, -rx, -ry, rx, 0 }; |
||||
Mat3 R; |
||||
|
||||
// R = cos(theta)*I + (1 - cos(theta))*r*rT + sin(theta)*[r_x]
|
||||
// where [r_x] is [0 -rz ry; rz 0 -rx; -ry rx 0]
|
||||
for(int k = 0; k < 9; ++k) |
||||
R.val[k] = static_cast<float_type>(c*I[k] + c1*rrt[k] + s*_r_x_[k]); |
||||
|
||||
rotation(R); |
||||
} |
||||
} |
||||
|
||||
//Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix;
|
||||
template<typename T> inline |
||||
void cv::Affine3<T>::rotation(const cv::Mat& data) |
||||
{ |
||||
CV_Assert(data.type() == cv::DataType<T>::type); |
||||
|
||||
if (data.cols == 3 && data.rows == 3) |
||||
{ |
||||
Mat3 R; |
||||
data.copyTo(R); |
||||
rotation(R); |
||||
} |
||||
else if ((data.cols == 3 && data.rows == 1) || (data.cols == 1 && data.rows == 3)) |
||||
{ |
||||
Vec3 _rvec; |
||||
data.reshape(1, 3).copyTo(_rvec); |
||||
rotation(_rvec); |
||||
} |
||||
else |
||||
CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
void cv::Affine3<T>::linear(const Mat3& L) |
||||
{ |
||||
matrix.val[0] = L.val[0]; matrix.val[1] = L.val[1]; matrix.val[ 2] = L.val[2]; |
||||
matrix.val[4] = L.val[3]; matrix.val[5] = L.val[4]; matrix.val[ 6] = L.val[5]; |
||||
matrix.val[8] = L.val[6]; matrix.val[9] = L.val[7]; matrix.val[10] = L.val[8]; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
void cv::Affine3<T>::translation(const Vec3& t) |
||||
{ |
||||
matrix.val[3] = t[0]; matrix.val[7] = t[1]; matrix.val[11] = t[2]; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
typename cv::Affine3<T>::Mat3 cv::Affine3<T>::rotation() const |
||||
{ |
||||
return linear(); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
typename cv::Affine3<T>::Mat3 cv::Affine3<T>::linear() const |
||||
{ |
||||
typename cv::Affine3<T>::Mat3 R; |
||||
R.val[0] = matrix.val[0]; R.val[1] = matrix.val[1]; R.val[2] = matrix.val[ 2]; |
||||
R.val[3] = matrix.val[4]; R.val[4] = matrix.val[5]; R.val[5] = matrix.val[ 6]; |
||||
R.val[6] = matrix.val[8]; R.val[7] = matrix.val[9]; R.val[8] = matrix.val[10]; |
||||
return R; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
typename cv::Affine3<T>::Vec3 cv::Affine3<T>::translation() const |
||||
{ |
||||
return Vec3(matrix.val[3], matrix.val[7], matrix.val[11]); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
typename cv::Affine3<T>::Vec3 cv::Affine3<T>::rvec() const |
||||
{ |
||||
cv::Vec3d w; |
||||
cv::Matx33d u, vt, R = rotation(); |
||||
cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A); |
||||
R = u * vt; |
||||
|
||||
double rx = R.val[7] - R.val[5]; |
||||
double ry = R.val[2] - R.val[6]; |
||||
double rz = R.val[3] - R.val[1]; |
||||
|
||||
double s = std::sqrt((rx*rx + ry*ry + rz*rz)*0.25); |
||||
double c = (R.val[0] + R.val[4] + R.val[8] - 1) * 0.5; |
||||
c = c > 1.0 ? 1.0 : c < -1.0 ? -1.0 : c; |
||||
double theta = acos(c); |
||||
|
||||
if( s < 1e-5 ) |
||||
{ |
||||
if( c > 0 ) |
||||
rx = ry = rz = 0; |
||||
else |
||||
{ |
||||
double t; |
||||
t = (R.val[0] + 1) * 0.5; |
||||
rx = std::sqrt(std::max(t, 0.0)); |
||||
t = (R.val[4] + 1) * 0.5; |
||||
ry = std::sqrt(std::max(t, 0.0)) * (R.val[1] < 0 ? -1.0 : 1.0); |
||||
t = (R.val[8] + 1) * 0.5; |
||||
rz = std::sqrt(std::max(t, 0.0)) * (R.val[2] < 0 ? -1.0 : 1.0); |
||||
|
||||
if( fabs(rx) < fabs(ry) && fabs(rx) < fabs(rz) && (R.val[5] > 0) != (ry*rz > 0) ) |
||||
rz = -rz; |
||||
theta /= std::sqrt(rx*rx + ry*ry + rz*rz); |
||||
rx *= theta; |
||||
ry *= theta; |
||||
rz *= theta; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
double vth = 1/(2*s); |
||||
vth *= theta; |
||||
rx *= vth; ry *= vth; rz *= vth; |
||||
} |
||||
|
||||
return cv::Vec3d(rx, ry, rz); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T> cv::Affine3<T>::inv(int method) const |
||||
{ |
||||
return matrix.inv(method); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T> cv::Affine3<T>::rotate(const Mat3& R) const |
||||
{ |
||||
Mat3 Lc = linear(); |
||||
Vec3 tc = translation(); |
||||
Mat4 result; |
||||
result.val[12] = result.val[13] = result.val[14] = 0; |
||||
result.val[15] = 1; |
||||
|
||||
for(int j = 0; j < 3; ++j) |
||||
{ |
||||
for(int i = 0; i < 3; ++i) |
||||
{ |
||||
float_type value = 0; |
||||
for(int k = 0; k < 3; ++k) |
||||
value += R(j, k) * Lc(k, i); |
||||
result(j, i) = value; |
||||
} |
||||
|
||||
result(j, 3) = R.row(j).dot(tc.t()); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T> cv::Affine3<T>::rotate(const Vec3& _rvec) const |
||||
{ |
||||
return rotate(Affine3f(_rvec).rotation()); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T> cv::Affine3<T>::translate(const Vec3& t) const |
||||
{ |
||||
Mat4 m = matrix; |
||||
m.val[ 3] += t[0]; |
||||
m.val[ 7] += t[1]; |
||||
m.val[11] += t[2]; |
||||
return m; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T> cv::Affine3<T>::concatenate(const Affine3<T>& affine) const |
||||
{ |
||||
return (*this).rotate(affine.rotation()).translate(affine.translation()); |
||||
} |
||||
|
||||
template<typename T> template <typename Y> inline |
||||
cv::Affine3<T>::operator Affine3<Y>() const |
||||
{ |
||||
return Affine3<Y>(matrix); |
||||
} |
||||
|
||||
template<typename T> template <typename Y> inline |
||||
cv::Affine3<Y> cv::Affine3<T>::cast() const |
||||
{ |
||||
return Affine3<Y>(matrix); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T> cv::operator*(const cv::Affine3<T>& affine1, const cv::Affine3<T>& affine2) |
||||
{ |
||||
return affine2.concatenate(affine1); |
||||
} |
||||
|
||||
template<typename T, typename V> inline |
||||
V cv::operator*(const cv::Affine3<T>& affine, const V& v) |
||||
{ |
||||
const typename Affine3<T>::Mat4& m = affine.matrix; |
||||
|
||||
V r; |
||||
r.x = m.val[0] * v.x + m.val[1] * v.y + m.val[ 2] * v.z + m.val[ 3]; |
||||
r.y = m.val[4] * v.x + m.val[5] * v.y + m.val[ 6] * v.z + m.val[ 7]; |
||||
r.z = m.val[8] * v.x + m.val[9] * v.y + m.val[10] * v.z + m.val[11]; |
||||
return r; |
||||
} |
||||
|
||||
static inline |
||||
cv::Vec3f cv::operator*(const cv::Affine3f& affine, const cv::Vec3f& v) |
||||
{ |
||||
const cv::Matx44f& m = affine.matrix; |
||||
cv::Vec3f r; |
||||
r.val[0] = m.val[0] * v[0] + m.val[1] * v[1] + m.val[ 2] * v[2] + m.val[ 3]; |
||||
r.val[1] = m.val[4] * v[0] + m.val[5] * v[1] + m.val[ 6] * v[2] + m.val[ 7]; |
||||
r.val[2] = m.val[8] * v[0] + m.val[9] * v[1] + m.val[10] * v[2] + m.val[11]; |
||||
return r; |
||||
} |
||||
|
||||
static inline |
||||
cv::Vec3d cv::operator*(const cv::Affine3d& affine, const cv::Vec3d& v) |
||||
{ |
||||
const cv::Matx44d& m = affine.matrix; |
||||
cv::Vec3d r; |
||||
r.val[0] = m.val[0] * v[0] + m.val[1] * v[1] + m.val[ 2] * v[2] + m.val[ 3]; |
||||
r.val[1] = m.val[4] * v[0] + m.val[5] * v[1] + m.val[ 6] * v[2] + m.val[ 7]; |
||||
r.val[2] = m.val[8] * v[0] + m.val[9] * v[1] + m.val[10] * v[2] + m.val[11]; |
||||
return r; |
||||
} |
||||
|
||||
|
||||
|
||||
#if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3(const Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>& affine) |
||||
{ |
||||
cv::Mat(4, 4, cv::DataType<T>::type, affine.matrix().data()).copyTo(matrix); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::Affine3(const Eigen::Transform<T, 3, Eigen::Affine>& affine) |
||||
{ |
||||
Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)> a = affine; |
||||
cv::Mat(4, 4, cv::DataType<T>::type, a.matrix().data()).copyTo(matrix); |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::operator Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>() const |
||||
{ |
||||
Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)> r; |
||||
cv::Mat hdr(4, 4, cv::DataType<T>::type, r.matrix().data()); |
||||
cv::Mat(matrix, false).copyTo(hdr); |
||||
return r; |
||||
} |
||||
|
||||
template<typename T> inline |
||||
cv::Affine3<T>::operator Eigen::Transform<T, 3, Eigen::Affine>() const |
||||
{ |
||||
return this->operator Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>(); |
||||
} |
||||
|
||||
#endif /* defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H */ |
||||
|
||||
|
||||
#endif /* __cplusplus */ |
||||
|
||||
#endif /* __OPENCV_CORE_AFFINE3_HPP__ */ |