I have an OpenCV function which return type is Mat.
How do I convert that to a 2 dimensional float array (** float)?
Probably very simple but I have not been able to do it myself.
A quick look at the documentation for the Mat class doesn't reveal any obvious 'convert to float**' operator, but you could probably do it by hand:
Mat mat = (Mat_<float>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);
// allocate and initialize a 2d float array
float **m = new float*[mat.Rows];
for (int r = 0; r < mat.Rows; ++r)
{
m[r] = new float[mat.Cols];
for (int c = 0; c < mat.Cols; ++c)
{
m[r][c] = mat.at(r, c);
}
}
// (use m for something)
// don't forget to clean up!
for (int r = 0; r < mat.Rows; ++r)
{
delete[] m[r];
}
delete[] m;
If you're not dead-set on using float**, you could use std::vector or boost::multi_array to avoid the awkward memory allocation/deallocation and reduce the potential for leaks.
You might also have some luck using Mat::ptr<float>(n) to get a float* to the nth row of a matrix, but if you don't copy the data out, I'm not sure what guarantees you'll have about how long that pointer will remain valid.
If you mean this,
float a[M][N]; //M and N are compile-time constants!
float **p = a; //error
then you cannot do that.
However, you can do this:
float (*p)[N] = a; //ok
But if that doesn't help you and you want float** at any cost, then use two for loops, and do that manually, copying each element from a to p:
Related
I'm working on a project that requires many dynamically sized 2D arrays that need to be accessible across functions.
The code I'm working on uses pointers like double** dynArray for this.
R = ...; // ROWS of the matrix, unknown prior to runtime
C = ...; // COLUMNS of the matrix, unknown prior to runtime
double** dynArray;
After checking the existing code I found that the arrays are currently always being initialized like this:
double** dynArray = new double*[R];
for(int r=0; r<R; r++){dynArray[r] = new double[C];}
In order to improve the readability I would like to write a method to do the above.
Here's what I came up with to allocate
void initialize2D(double*** data, int R, int C){
(*dynArray) = new double*[R];
for(int r=0; r<R; r++){
(*dynArray)[r] = new double[C];
for(int c=0; c<C; c++){
(*dynArray)[r][c] = 0;
}
}
}
and free memory respectively:
void free2D(double*** data, int R, int C){
for(int r=0; r<R; r++){
delete[] (*data)[r];
}
delete *data;
}
I intended to use these methods like this:
R = ...; // ROWS of the matrix, unknown prior to runtime
C = ...; // COLUMNS of the matrix, unknown prior to runtime
double** dynArray;
initialize2D(&dynArray, R, C);
/* do stuff*/
free2D(&dynArray,R,C);
After implementing these functions I ran Valgrind and found that this qualifies as a
definitely lost, sometimes
possibly lost.
What is the problem, and what would be the proper way to initialize through a function by reference?
Write the functions the following way
double ** initialize2D( int R, int C )
{
double **dynArray = new double *[R];
for ( int r = 0; r < R; r++ )
{
dynArray[r] = new double[C]();
}
return dynArray;
}
void free2D( double **data, int R )
{
for ( int r = 0; r < R; r++ ) delete [] data[r];
delete [] data;
}
And call the functions the following way
double** dynArray = initialize2D( R, C );
/* do stuff*/
free2D( dynArray, R );
dynArray = nullptr;
Take into account that you could use standard container std::vector<std::vector<double>> instead of dynamically allocate the arrays yourself.
Assuming it is necessary to pass the pointer to the function to initialise it ...
void initialize2D(double*** data, int R, int C)
{
*data = new double*[R];
for(int r=0; r<R; r++)
{
(*data)[r] = new double[C];
for(int c=0; c<C; c++)
{
(*data)[r][c] = 0;
}
}
}
void free2D( double ***data, int R )
{
for ( int r = 0; r < R; r++ ) delete [] (*data)[r];
delete [] (*data);
*data = nullptr;
}
Personally, however, I wouldn't directly use dynamic memory allocation at all. Instead I'd do;
#include <vector>
// and in your code
void some_function()
{
std::vector<std::vector<double> > dynArray(R, std::vector<double>(C));
// use dynArray as if it is a 2D array. All elements dynArray[i][j]
// will be initialised to zero, for i = 0 to R-1 and j = 0 to C-1
dynArray[3][4] = 42; // assuming R > 3 and C > 4
// ALL memory allocated for dynArray will be released here automatically as it passes out of scope
}
The advantage of this is that the standard vector class will happily manage all memory allocation and deallocation for you.
It is easy enough to pass such vectors around by reference.
An alltogether better way to code what you have above is:
#include <vector>
std::vector<std::vector<double>> initialise2D(int r, int c)
{
std::vector<std::vector<double>> result(r);
for(int i=0; i<r; ++i) result[i].reserve(c);
return result;
}
void free2D(std::vector<std::vector<double>> &v)
{
v.clear();
}
you can then
auto dynArray = initialise3D(20, 30);
You should also note that you do not actually need free2D any longer. I kept it here only for you to see how much easier things have became.
You will also note that you can use vector in the same way as you used array. That is why there was no problem for me to write result[i] using square brackets, as if it were an array.
I am trying to make a fast image threshold function. Currently what I do is:
void threshold(const cv::Mat &input, cv::Mat &output, uchar threshold) {
int rows = input.rows;
int cols = input.cols;
// cv::Mat for result
output.create(rows, cols, CV_8U);
if(input.isContinuous()) { //we have to make sure that we are dealing with a continues memory chunk
const uchar* p;
for (int r = 0; r < rows; ++r) {
p = input.ptr<uchar>(r);
for (int c = 0; c < cols; ++c) {
if(p[c] >= threshold)
//how to access output faster??
output.at<uchar>(r,c) = 255;
else
output.at<uchar>(r,c) = 0;
}
}
}
}
I know that the at() function is quite slow. How can I set the output faster, or in other words how to relate the pointer which I get from the input to the output?
You are thinking of at as the C++ standard library documents it for a few containers, performing a range check and throwing if out of bounds, however this is not the standard library but OpenCV.
According to the cv::Mat::at documentation:
The template methods return a reference to the specified array element. For the sake of higher performance, the index range checks are only performed in the Debug configuration.
So there's no range check as you may be thinking.
Comparing both cv::Mat::at and cv::Mat::ptr in the source code we can see they are almost identical.
So cv::Mat::ptr<>(row) is as expensive as
return (_Tp*)(data + step.p[0] * y);
While cv::Mat::at<>(row, column) is as expensive as:
return ((_Tp*)(data + step.p[0] * i0))[i1];
You might want to take cv::Mat::ptr directly instead of calling cv::Mat::at every column to avoid further repetition of the data + step.p[0] * i0 operation, doing [i1] by yourself.
So you would do:
/* output.create and stuff */
const uchar* p, o;
for (int r = 0; r < rows; ++r) {
p = input.ptr<uchar>(r);
o = output.ptr<uchar>(r); // <-----
for (int c = 0; c < cols; ++c) {
if(p[c] >= threshold)
o[c] = 255;
else
o[c] = 0;
}
}
As a side note you don't and shouldn't check for cv::Mat::isContinuous here, the gaps are from one row to another, you are taking pointers to a single row, so you don't need to deal with the matrix gaps.
How to make a 2d pointer like **check point a 2d array like
mycheck[][]?
How to convert a 1d like check[16], to 2d array like mycheck[4][4]?
My attempt
float (*mycheck)[4] = (float (*)[4]) check;
But if second time I want to use mycheck again for some other 1d array, how can I do? My attempt:
float (*mycheck)[4] = (float (*)[4]) other1darray;
this will definitely give a re-declaration error.
The answer to the first question is that you cannot do that. All you can do is allocate some memory and copy the data over.
The answer to the second question is very simple
mycheck = (float (*)[4]) other1darray;
You only have to declare variables once, after that just use the variable name.
Array a[] decays to a pointer to the first element when you drop the []. This does not happen recursively, in other words, it doesn't work for a[][].
Secondly, you can't assign arrays in C. You can ONLY initialize them. You will have to set each member yourself.
You can create a 2D array in C like this.
Use a typedef to make it easier.
typedef int **matrix;
matrix create2Darray(int row, int col)
{
int idx;
matrix m = malloc(row * sizeof(int*));
for (idx = 0; idx < row; ++idx)
{
m[idx] = malloc(col * sizeof(int));
}
return m;
}
And then call this in another function;
matrix check = create2Darray(2, 2);
To assign a 1D array to a 2D array you can assign the pointers to the right position in the array. An example below. It also show how to create a 2D array dynamically, but I commented it out, since it is not needed for the example.
#include <stdio.h>
#include <stdlib.h>
int main()
{
float **matrix;
float *array;
array = (float *) malloc(16 * sizeof(float));
for (size_t idx = 0; idx != 16; ++idx)
{
array[idx] = idx;
}
matrix = (float **) malloc(4 * sizeof(float *));
for (size_t idx = 0; idx != 4; ++idx)
{
// matrix[idx] = malloc(4 * sizeof(int));
matrix[idx] = &array[idx * 4];
}
for (size_t row = 0; row != 4; ++row)
{
for (size_t col = 0; col != 4; ++col)
{
printf("%.1f ", matrix[row][col]);
}
printf("\n");
}
}
Note: this makes the 1D array and 2D array point to the same memory. If you change something in the 1D it also changes in the 2D and vice-versa. If you don't want this, first copy the array.
I want to declare, populate, access a Multi-Dimensional Matrix in OpenCV (C++) which is compatible with namespace cv. I found no quick and easy to learn examples on them. Can you please help me out?
Here is a short example from the NAryMatIterator documentation; it shows how to create, populate, and process a multi-dimensional matrix in OpenCV:
void computeNormalizedColorHist(const Mat& image, Mat& hist, int N, double minProb)
{
const int histSize[] = {N, N, N};
// make sure that the histogram has a proper size and type
hist.create(3, histSize, CV_32F);
// and clear it
hist = Scalar(0);
// the loop below assumes that the image
// is a 8-bit 3-channel. check it.
CV_Assert(image.type() == CV_8UC3);
MatConstIterator_<Vec3b> it = image.begin<Vec3b>(),
it_end = image.end<Vec3b>();
for( ; it != it_end; ++it )
{
const Vec3b& pix = *it;
hist.at<float>(pix[0]*N/256, pix[1]*N/256, pix[2]*N/256) += 1.f;
}
minProb *= image.rows*image.cols;
Mat plane;
NAryMatIterator it(&hist, &plane, 1);
double s = 0;
// iterate through the matrix. on each iteration
// it.planes[*] (of type Mat) will be set to the current plane.
for(int p = 0; p < it.nplanes; p++, ++it)
{
threshold(it.planes[0], it.planes[0], minProb, 0, THRESH_TOZERO);
s += sum(it.planes[0])[0];
}
s = 1./s;
it = NAryMatIterator(&hist, &plane, 1);
for(int p = 0; p < it.nplanes; p++, ++it)
it.planes[0] *= s;
}
Also, check out the cv::compareHist function for another usage example of the NAryMatIterator here.
To create a multi-dimensional matrix that is of size 100x100x3, using floats, one channel, and with all elements initialized to 10 you write like this:
int size[3] = { 100, 100, 3 };
cv::Mat M(3, size, CV_32FC1, cv::Scalar(10));
To loop over and output the elements in the matrix you can do:
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
for (int k = 0; k < 3; k++)
std::cout << M.at<cv::Vec3f>(i,j)[k] << ", ";
However, beware of the troubles with using multi-dimensional matrices as documented here: How do i get the size of a multi-dimensional cv::Mat? (Mat, or MatND)
In C++ I'd like to do something like:
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
but of course this doesn't work. What is the best way to do something similar? I've seen some solutions to this but they seem pretty messy.
The manual dynamic way:
Let's say you want an array of width*height, the most efficient way is to just use a single dimensional array:
char *matrix = new char[width*height];
To delete it:
delete[] matrix;
To access it:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
To modify it:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
Boost Matrix:
Consider using boost::matrix if you can have the dependency.
You could then tie into the boost linear algebra libraries.
Here is some sample code of boost::matrix:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
On the stack for some compilers:
Some compilers actually allow you to create arrays on the stack with runtime determined sizes. g++ is an example of such a compiler. You cannot do this by default VC++ though.
So in g++ this is valid code:
int width = 10;
int height = 10;
int matrix[width][height];
Drew Hall mentioned that this C99 feature is called Variable Length Arrays (VLAs) and it can probably be turned on in any modern compiler.
I usually do something like this:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
You seem to be missing the whole point of C++ (C with classes) :-). This is the sort of use that's crying out for a class to implement it.
You could just use STL or other 3rd party class library which I'm sure would have the data structure you're looking for but, if you need to roll your own, just create a class with the following properties.
constructor which, given n, will just create a new n*n array of char (e.g., charray)..
member functions which get and set values based on x.y which simply refer to charray[x*n+y];
destructor which delete[]'s the array.
What about std::vector< std::vector<int> > array2d; ?
For a true two dimensional array:
int n = get_int_from_user();
char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new char[n];
}
// Operations on matrix.
for (int i = 0; i < n; i++) {
delete [] matrix[i];
}
delete matrix;
Just off the top of my head. Mistakes, no doubt. However, other people have posted a more elegant approach, I think.
I like the 1-d array approach (the selected answer by Brian R. Bondy) with the extension that you wrap the data members into a class so that you don't need to keep track of the width separately:
class Matrix
{
int width;
int height;
char* data;
public:
Matrix();
Matrix(int width, int height);
~Matrix();
char getArrayValue(int row, int col);
void setArrayValue(int row, int col, char val);
}
The implementation is an exercise for the reader. ;)
I think this would be a good one.
int n = get_int_from_user();
char **matrix=new (char*)[n];
for(int i=0;i<n;i++)
matrix[i]=new char[n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
for(int i=0;i<n;i++)
delete []matrix;
delete []matrix;
std::vector<int> m;
Then call m.resize() at runtime.
int* matrix = new int[w*h];
if you want to do something like Gaussian elimination your matrix should be
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(in Gaussian elimination we usually need to exchange one row with another so it's better to swap pointers to rows in constant time rather than swapping by copying in linear time).