Conversion of 3x1 or 1x3 cv::Mat to cv::Point3d? - c++

I'm dealing with some code in which a do a lot of 3x3 matrix multiplications an also some translation of 3d points using rotation matrices, etc. I decided to use OpenCV core functionalities for the mathematical operations. The possibility to use the recent constructor added to the cv::Mat class to convert a cv::Point3d directly to a 3x1 cv::Mat reduces and simplifies the code greatly.
What I am wondering now is if there is a simple way to convert a 3x1 or 1x3 cv::Mat to an cv::Point3d? I always can do something like:
cv::Mat mat(3,1,CV_64FC1);
cv::Point3d p (mat.at<double>(0,0), mat.at<double>(1,0), mat.at<double>(2,0));
or
cv::Mat mat(3,1,CV_64FC1);
const double *data = mat.ptr<double>(0);
cv::Point3d p (data[0], data[1], data[2]);
I am very worried about the performance (avoid the 3 calls to at method).

cv::Point3d has a constructor which allows direct creation from cv::Mat:
cv::Mat mat(3,1,CV_64FC1);
cv::Point3d p(mat);
Another possibility you may not have considered is using cv::Matx instead of cv::Mat for your mathematical operations. I find it is easier to use, and offers more functionality, like multiplication of Point types without needing a conversion:
cv::Point3d p(1,2,3);
cv::Matx33d m = cv::Matx33d::eye();
cv::Point3d p2 = m * p;
cv::Matx is also statically allocated, rather than dynamically (like cv::Mat), in case you really need that extra little bit of performance. However, as in all performance-related advice: make sure what you're optimizing is actually a bottleneck by profiling.

Related

OpenCV: Stack Vectors to Mat

I got 3 Vec3f and want to stack them to a 3x3 Matrix (C++).
Is there a nice way to to so? In python its easy with numpy, however I dont know if there is a better way than assigin every single value from Vector to the corresponding Mat entry?
Cheers
Yes you can. It depends on the precise packing arrangement that you want, but the simplest way is to simply copy their bytes into a properly sized Mat.
You access the bytes of a single Vec3f instance Vec3f v by using &v[0]. You access the bytes of a matrix Mat m by using m.data (not a function).
Here's an example:
cv::Mat m(3, 3, CV_32FC3);
cv::Vec3f vecs[3];
memcpy((void*)m.data, (const void*)&vecs[0][0], m.width * m.height * 3 * sizeof(float));

2D fourier transform with Eigen and FFTW

I'm trying to do a real-valued 2d Fourier Transform with FFTW. My data is stored in a dynamically sized Eigen Matrix. Here's the wrapper class I wrote:
FFT2D.h:
#include <Eigen>
class FFT2D {
public:
enum FFT_TYPE {FORWARD=0, REVERSE=1};
FFT2D(EMatrix &input, EMatrix &output, FFT_TYPE type_ = FORWARD);
~FFT2D();
void execute();
private:
EMatrix& input;
EMatrix& output;
fftw_plan plan;
FFT_TYPE type;
};
FFT2D.cpp:
#include "FFT2D.h"
#include <fftw3.h>
#include "Defs.h"
FFT2D::FFT2D(EMatrix &input_, EMatrix &output_, FFT_TYPE type_)
: type(type_), input(input_), output(output_) {
if (type == FORWARD)
plan = fftw_plan_dft_2d((int) input.rows(), (int) input.cols(),
(fftw_complex *) &input(0), (fftw_complex *) &output(0),
FFTW_FORWARD, FFTW_ESTIMATE);
else
// placeholder for ifft-2d code, unwritten
}
FFT2D::~FFT2D() {
fftw_destroy_plan(plan);
}
void FFT2D::execute() {
fftw_execute(plan); // seg-fault here
}
And a definition for EMatrix:
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> EMatrix;
The problem is, is I'm getting a seg fault in FFT2D::execute(). I know I'm setting something up wrong in the constructor, and I've tried a number of different ways, but I can't seem to make any headway on this.
Things I've tried include: changing EMatrix typedef to Eigen::ColMajor, passing (fftw_complex *) input.data() to fftw_plan_dft_2d, using different fftw plans (fftw_plan_dft_r2c_2d).
My C++ is (clearly) rusty, but at the end of the day what I need is to do a 2D FT on a real-valued 2D Eigen Matrix of doubles. Thanks in advance.
The major problem here is that there is no such thing as "real-valued Fourier transform". It's just a Fourier transform of something with zero imaginary part, but the zeroes still have to be there, as you can see from fftw_complex definition:
typedef double fftw_complex[2];
This makes sense as the output can (and probably will) have non-zero imaginary part.
The output will have some symmetric properties though, i.e. in case of 1D transform it would be an even function.
As a result the (fftw_complex *) &input(0) cast doesn't really work - FFTW expects twice as many double values as you pass to it.
The solution is to interleave your matrix raw data with zeroes, and there is a number of ways to do that. Few examples:
You could copy the whole matrix into a new array before passing it to FFTW, adding the zeroes in process.
You could reserve the space for zeroes in the matrix itself - this way you'll be able to avoid copying, but it will probably require a lot of refactoring:)
The best way I can think of is to use std::complex<double> as a scalar. This will somewhat hurt your notice of "real-valued FFT", but again there is hardly such thing in the first place. Instead you'll be able to keep all your real-value operations as they are, and the layout of std::complex will fit fftw_complex perfectly.
There could be some other things to consider here, like storage order (FFTW operates on arrays in row-major order, so Eigen matrices should comply) and the validity of linear access to Eigen matrix data (seems OK to me).

Eigen LDLT Cholesky decomposition in-place

I am trying to get Eigen3 to solve a linear system A * X = B with an in-place Cholesky decomposition. I cannot afford to have any temporaries of the size of A pushed on the stack, but I am free to destroy A in the process.
Unfortunately,
A.llt().solveInPlace(B);
is out of question, since A.llt() implicitly pushes a temporary matrix of the size of A on the stack. For the LLT case, I could get access to the necessary functionality like so:
// solve A * X = B in-place for positive-definite A
template <typename AType, typename BType>
void AllInPlaceSolve(AType& A, BType& B)
{
typedef Eigen::internal::LLT_Traits<AType, Eigen::Upper> TraitsType;
TraitsType::inplace_decomposition(A);
TraitsType::getL(A).solveInPlace(B);
TraitsType::getU(A).solveInPlace(B);
}
This works fine, but I am worried that:
My matrices A might be positive semidefinite only, in which case a LDLT decomposition is required
The LLT decomposition calculates sqrt() unnecessarily for the solution of the system
I could not find a way to hook in Eigen's LDLT functionality similarly to the code above, since the code is structured very differently.
So my question is: Is there a way to use Eigen3 for solving a linear system using LDLT decompositions using no more scratch space than for the diagonal matrix D?
One option is to allocate a LDLT solver only once, and call the compute method:
LDLT<MatType> ldlt(size);
// ...
ldlt.compute(A);
x = ldlt.solve(b);
If that's also not an option, you can const cast the matrix stored by the ldlt object:
LDLT<MatType> ldlt(MatType::Identity(size,size));
MatType& A = const_cast<MatType&>(ldlt.matrixLDLT());
plays with A, and then:
ldlt.compute(A);
x = ldlt.solve(b);
This is ugly, but this should work as long as MatType is column major.

Best way to convert an Eigen Vector4 type to Vector3?

I want to extract the three first values of a Vector4 type in Eigen, into a Vector3 type. So far I am doing it in a for-loop. Is there a smarter way to do it?
The .head() member function returns the first n elements of a vector. If n is a compile-time constant, then you can use the templated variant (as in the code example below) and the Eigen library will automatically unroll the loop.
Eigen::Vector4f vec4;
// initialize vec4
Eigen::Vector3f vec3 = vec4.head<3>();
In the Eigen documentation, see Block operations for an introduction to similar operations for extracting parts of vectors and matrices, and DenseBase::head() for the specific function.
The answer of #Jitse Niesen is correct. Maybe this should be a comment on the original question, but I found this question because I had some confusion about Eigen. In case the original questioner, or some future reader has the same confusion, I wanted to provide some additional explanation.
If the goal is to transform 3d (“position”) vectors by a 4x4 homogeneous transformation matrix, as is common in 3d graphics (e.g. OpenGL etc), then Eigen provides a cleaner way to do that with its Transform template class, often represented as the concrete classes Affine3f or Affine3d (as tersely described here). So while you can write such a transform like this:
Eigen::Matrix4f transform; // your 4x4 homogeneous transformation
Eigen::Vector3f input; // your input
Eigen::Vector4f input_temp;
input_temp << input, 1; // input padded with w=1 for 4d homogeneous space
Eigen::Vector4f output_temp = transform * input_temp;
Eigen::Vector3f output = output_temp.head<3>() / output_temp.w(); // output in 3d
You can more concisely write it like this:
Eigen::Affine3f transform; // your 4x4 homogeneous transformation
Eigen::Vector3f input; // your input
Eigen::Vector3f output = transform * input;
That is: an Eigen::Affine3f is a 4x4 homogeneous transformation that maps from 3d to 3d.
Yeah, because you know the size is static (3 elements) you should unroll the loop and copy them explicitly. This optimization might be performed by the compiler already, but it can't hurt to do it yourself just in case.

Implementing complex-valued matrix equation in OpenCV

I am attempting to implement a complex-valued matrix equation in OpenCV. I've prototyped in MATLAB which works fine. Starting off with the equation (exact MATLAB implementation):
kernel = exp(1i .* k .* Circ3D) .* z ./ (1i .* lambda .* Circ3D .* Circ3D)
In which
1i = complex number
k = constant (float)
Circ3D = real-valued matrix of known size
lambda = constant (float)
.* = element-wise multiplication
./ = element-wise division
The result is a complex-valued matrix. I succeeded in generating the necessary Circ3D matrix as a CV_32F, however the multiplication by the complex number i is giving me trouble. From the OpenCV documentation I understand that a complex matrix is simply a two-channel matrix (CV_32FC2).
The real trouble comes from how to define i. I've tried several options, among which defining i as
cv::Vec2d complex = cv::Vec2d(0,1);
and then multiplying by the matrix
kernel = complex * Circ3D
But this doesn't work (although I didn't expect it to). I suspect I need to do something with std::complex but I have no idea what (http://docs.opencv.org/modules/core/doc/basic_structures.html).
Thanks in advance for any help.
Edit: Just after writing this post I did make some progress, by defining i as follows:
std::complex<float> complex(0,1)
I am then able to assign complex values as follows:
kernel.at<std::complex<float>>(i,j) = cv::exp(complex * k * Circ3D.at<float>(i,j)) * ...
z / (complex * lambda * pow(Circ3D.at<float>(i,j),2));
However, this works in a loop, which makes the procedure incredibly slow. Any way to do it in one go?
OpenCV treats std::complex just like the simple pair of numbers (see example in the documentation). No special rules on arithmetic operations are applied. You overcome this by multiplying std::complex directly. So basically, this is simple: you either chose automatic complex arithmetic (as you are doing now), or automatic vectorization (when using OpenCV functions on matrices).
I think, in your case you should carry all the complex arithmetic by yourself. Store matrix of complex values C{ai + b} as two matrices A{a} and B{b}. Implement exponentiation by yourself. Multiplication on scalars and addition shouldn't be a problem.
There is also the function mulSpectrums, which lets you do element wise multiplication of complex matrices. So if K is your kernel matrix and I is some complex matrix, that is, CV_32FC2 (float two channel) you can do the following to compute the element wise multiplication,
// Make K a complex matrix
cv::Mat Ktmp[] = {cv::Mat_<float>(K), cv::Mat::zeros(K.size(), CV_32FC1)};
cv::Mat Kc;
cv::merge(Ktmp,2,Kc);
// Do matrix multiplication
cv::mulSpectrums(Kc,I,I,0);