I have the following function which extracts a sub-image from an OpenCV cv::Mat
void Process(int a,int b,int c,int d)
{
// Extract img(a:b,c:d) each time
subImg = img(cv::Range(a, b), cv::Range(c,d));
}
I call Process() in a loop. On each invocation, the values of a,b,c,d keep changing. If subImg has been declared as cv::Mat subImg;, can I do the above ? i.e. Can OpenCV dynamically resize subImg or do I have to go for a pointer-based approach where I declare:
cv::Mat* subImg; // Initialized to NULL in constructor
and modify the function as follows:
void Process(int a,int b,int c,int d)
{
// Extract img(a:b,c:d) each time
if(subImg) delete subImg;
subImg = img(cv::Range(a, b), cv::Range(c,d)).clone();
}
You can do this with cv::Mat subImg;. cv::Mat uses reference counting, and sub-matrix knows that it belongs to bigger matrix, so memory will be deallocated properly.
Related
Situation
I realized that I've been writing a lot of LeafSystem classes that do very lightweight manipulation the input data and spits it out as output data. They are all state-less and their only difference is the conversion function.
An example of this is a class which simply re-orders the input data or a class that simply strips away irrelevant input data.
Hence, I thought to write a LeafSystem class which takes this "conversion function" as argument to skip the headache of having to create a brand new class each time I want to process the input data in a slightly different way.
The idea is a constructor that takes a std::function of the form, along with input and output vector size.
std::function<void(const Eigen::VectorBlock<const drake::VectorX<T>>&, Eigen::VectorBlock<drake::VectorX<T>>& )>;
The "conversion function" can be implemented in this functor.
An example usecase would be if I wanted to convert a 3D state data (x, y, z, roll, pitch, yaw) into 2D state data (x, y, yaw), I could just write a functor such as
void 3Dto2D(const Eigen::VectorBlock<const drake::VectorX<T>>& input, Eigen::VectorBlock<drake::VectorX<T>>& output)
{
output[0] = input[0]; //x
output[1] = input[1]; //y
output[2] = input[5]; //yaw
output[3] = input[6]; //x_dot
output[4] = input[7]; //y_dot
output[5] = input[11]; //yaw_dot
}
And pass this functor into this "StateConverter".
Problem
The issue I'm facing is regarding the scalar-converting copy constructor. How do I implement it when the class has type specific member objects?
The main body of this class is as follows (for completeness)
using ConversionFunc = std::function<void(const Eigen::VectorBlock<const drake::VectorX<T>>&, Eigen::VectorBlock<drake::VectorX<T>>& )>;;
// Some black magic to handle alias explicit template instantiation
template <typename T>
StateConverter<T>::StateConverter(ConversionFunc func, const unsigned int input_size, const unsigned int output_size) :
systems::LeafSystem<T>(systems::SystemTypeTag<StateConverter>{}),
input_idx(this->DeclareVectorInputPort("input_port", systems::BasicVector<T>(input_size)).get_index()),
output_idx(this->DeclareVectorOutputPort("output_port", systems::BasicVector<T>(output_size), &StateConverter::convert).get_index())
{
convert_func = func;
}
template <typename T>
void StateConverter<T>::convert(const drake::systems::Context<T>& context, systems::BasicVector<T>* output) const
{
const auto state = this->EvalVectorInput(context, input_idx)->get_value();
auto mutable_output = output->get_mutable_value();
convert_func(state, mutable_output);
}
Partial Solution
I ended up creating a struct that holds all 3 required instances of the templated function
struct ConversionFunc
{
std::function<void(const Eigen::VectorBlock<const drake::VectorX<double>>&, Eigen::VectorBlock<drake::VectorX<double>>& )> double_impl;
std::function<void(const Eigen::VectorBlock<const drake::VectorX<drake::AutoDiffXd>>&, Eigen::VectorBlock<drake::VectorX<drake::AutoDiffXd>>& )> autodiff_impl;
std::function<void(const Eigen::VectorBlock<const drake::VectorX<drake::symbolic::Expression>>&, Eigen::VectorBlock<drake::VectorX<drake::symbolic::Expression>>& )> symbolic_impl;
};
Which is what gets passed in the copy constructor
I create the struct as follows
template <typename T>
void convert_func(const Eigen::VectorBlock<const VectorX<T>>& state, Eigen::VectorBlock<VectorX<T>>& output)
{
// Some example conversions
output[0] = state[4];
output[1] = state[6];
output[2] = state[12];
output[3] = state[14];
}
// I'm sure there's some way to automatically create these instantiations in the constructor of ConversionFunc...
ConversionFunc func;
func.double_impl = convert_func<double>;
func.autodiff_impl = convert_func<drake::AutoDiffXd>;
func.symbolic_impl = convert_func<drake::symbolic::Expression>;
And pass it to my Converter as follows
auto converter = builder.AddSystem(std::make_unique<StateConverter<double>>(func, 16, 4));
Problem
Unfortunately, this method seems to be leaking memory causing std::bad_alloc to be thrown...
I am aware there are several ways to read and write a pixel value of an OpenCV cv::Mat image/matrix.
A common one is the .at<typename T>(int, int) method http://opencv.itseez.com/2.4/modules/core/doc/basic_structures.html#mat-at .
However, this requires the typename to be known, for instance .at<double>.
The same thing applies to more direct pointer access OpenCV get pixel channel value from Mat image .
How can I read a pixel value without knowing its type? For instance, it would be ok to receive a more generic CvScalar value in return. Efficiency is not an issue, as I would like to read rather small matrices.
Kind of. You can construct cv::Mat_ and provide explicit type for elements, after that you don't have to write element type each time. Quoting opencv2/core/mat.hpp
While Mat is sufficient in most cases, Mat_ can be more convenient if you use a lot of element
access operations and if you know matrix type at the compilation time. Note that
Mat::at(int y,int x) and Mat_::operator()(int y,int x) do absolutely the same
and run at the same speed, but the latter is certainly shorter.
Mat_ and Mat are very similar. Again quote from mat.hpp:
The class Mat_<_Tp> is a thin template wrapper on top of the Mat class. It does not have any
extra data fields. Nor this class nor Mat has any virtual methods. Thus, references or pointers to
these two classes can be freely but carefully converted one to another.
You can use it like this
Mat_<Vec3b> dummy(3,3);
dummy(1, 2)[0] = 10;
dummy(1, 2)[1] = 20;
dummy(1, 2)[2] = 30;
cout << dummy(1, 2) << endl;
Why I said 'kind of' in the first place? Because if you want to pass this Mat_ somewhere - you have to specify it's type. Like this:
void test(Mat_<Vec3b>& arr) {
arr(1, 2)[0] = 10;
arr(1, 2)[1] = 20;
arr(1, 2)[2] = 30;
cout << arr(1, 2) << endl;
}
...
Mat_<Vec3b> dummy(3,3);
test(dummy);
Technically, you are not specifying your type during a pixel read, but actually you still have to know it and cast the Mat to the appropriate type beforehand.
I guess you can find a way around this using some low-level hacks (for example make a method that reads Mat's type, calculates element size and stride, and then accesses raw data using pointer arithmetic and casting...). But I don't know any 'clean' way to do this using OpenCV's functionality.
If you already know the type, you can use Mat_<> type for easy access. If you don't know the type, you can:
convert the data to double, so data won't be truncated in any case
switch over the number of channels to access correctly the double matrix. Note that you can have at most of 4 channels, since Scalar has at most 4 elements.
The following code will convert only the selected element of the source matrix to a double value (with N channels).
You get a Scalar containing the value at position row, col in the source matrix.
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Scalar valueAt(const Mat& src, int row, int col)
{
Mat dst;;
src(Rect(col, row, 1, 1)).convertTo(dst, CV_64F);
switch (dst.channels())
{
case 1: return dst.at<double>(0);
case 2: return dst.at<Vec2d>(0);
case 3: return dst.at<Vec3d>(0);
case 4: return dst.at<Vec4d>(0);
}
return Scalar();
}
int main()
{
Mat m(3, 3, CV_32FC3); // You can use any type here
randu(m, Scalar(0, 0, 0, 0), Scalar(256, 256, 256, 256));
Scalar val = valueAt(m, 1, 2);
cout << val << endl;
return 0;
}
I have the following code:
//newImg is a mat of an image and orderedKeyPoint is the result from Fast
cv::FREAK extractor;
cv::Mat queryDescriptors;
extractor.compute(newImg, orderedKeyPoint, queryDescriptors);
I am trying to access individual freak descriptors using queryDescriptors.at< ???>(r,0) where r is an arbitrary valid row value but I am not sure of the type. All documentation states that it is just a descriptor, but is that of type Mat or double or something else? Is this the best way of doing it?
cv::Mat descriptor2 = queryDescriptors.at<cv::Mat>(2,0);
I would like to be able to reconstruct queryDescriptors (Mat of descriptors) from individual descriptors by taking them and putting them in the row values of a cv::Mat, ex:
queryDescriptors.at<cv::Mat>(2,0) = descriptor2;
Any help or insight would be greatly appreciated,
Isaac
the FREAK descriptor is a uchar Mat with 64 cols and numkeypoints rows.
so, to get to an element of it:
uchar elm = descriptor.at<uchar>(row,col);
where row is the keypoint id, and col is the element id.
If you have a look into \opencv\modules\features2d\src\freak.cpp you can see:
int FREAK::descriptorSize() const
{
return FREAK_NB_PAIRS / 8; // descriptor length in bytes
}
int FREAK::descriptorType() const
{
return CV_8U;
}
int FREAK::defaultNorm() const
{
return NORM_HAMMING;
}
} // END NAMESPACE CV
So uchar seems to be the type as berak already suggested.
I am passing a Mat to another function and changing it inside the called function. I had expected that being a more complex type it was automatically passed by reference so that the matrix would have changed in the calling function, but it doesn't. Could someone point me at the explanation of how to correctly return a changed Mat from a function?
Here's the code snippet:
void callingFunction(Mat img)
{
Mat tst(100,500,CV_8UC3, Scalar(0,255,0));
saveImg(tst, "Original image", true);
testImg(tst);
saveImg(tst, "Want it to be same as inside testImg but is same as Original", true);
}
void testImg(Mat img)
{
int rs = 50; // rows
int cs = 100; // columns
img = Mat(rs, cs, CV_8UC3, Scalar(255,0,0));
Mat roi(img, Rect(0, 0, cs, rs/2));
roi = Scalar(0,0,255); // change a subsection to a different color
saveImg(img, "inside testImg", true);
}
Thanks!
You have to define Mat as parameter-reference (&). Here's edited code:
void callingFunction(Mat& img)
{
Mat tst(100,500,CV_8UC3, Scalar(0,255,0));
saveImg(tst, "Original image", true);
testImg(tst);
saveImg(tst, "Want it to be same as inside testImg but is same as Original", true);
}
void testImg(Mat& img)
{
int rs = 50; // rows
int cs = 100; // columns
img = Mat(rs, cs, CV_8UC3, Scalar(255,0,0));
Mat roi(img, Rect(0, 0, cs, rs/2));
roi = Scalar(0,0,255); // change a subsection to a different color
saveImg(img, "inside testImg", true);
}
I wondered about the same question myself, so I would like to further clarify the answer given by #ArtemStorozhuk (which is correct).
The OpenCV documentation is misleading here, because it appears you're passing the matrix by value, but in fact the constructor of cv::OutputArray is defined as follows:
_OutputArray::_OutputArray(Mat& m)
so it gets the matrix by reference!
Since operations like cv::Mat::create create a new matrix, the operation releases the reference and set the couter to 1. Thus, in order to keep the result in the calling function, you have to pass the matrix by reference.
If its true that you have to explicitly pass by reference, then how do all the OpenCV functions work? None of them pass values by reference, yet they somehow seem to write to the passed in Mat just fine. For example, here is the declaration for the Sobel function in imgproc.hpp:
//! applies generalized Sobel operator to the image
CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, int ksize=3,
double scale=1, double delta=0,
int borderType=BORDER_DEFAULT );
as you can see, it passes in src and dst without a &. And yet I know that after I call the Sobel with an empty dst, it will end up filled. No '&' involved.
I posted a question here earlier that I think I can answer if someone can help me with the following:
I have a function
double func(void* data)
I want to pass in an object or struct. (In my case an armadillo matrix or even just and std::vector).
How do I pass a pointer to an object as an argument to func() and then, once inside func(), how do I recast the void pointer into its original type?
Edit: Here's what ended up working, where mat is the Armadillo matrix class:
mat A(2,2);
A << 1 << 2 << endr << 3 << 4; // A=[1,2; 3,4]
func(&A);
and in func:
double func(void* data) {
mat* pB = (mat*)(data);
mat B = pB[0];
}
The matrix B and A now contain the same data.
If I understand you correctly you need something like this.
double func(void* data_v) {
struct my_type * data = data_v;
}
func((void*)my_data);