OpenCV Add columns to a matrix - c++

in OpenCV 2 and later there is method Mat::resize that let's you add any number of rows with the default value to your matrix is there any equivalent method for the column. and if not what is the most efficient way to do this.
Thanks

Use cv::hconcat:
Mat mat;
Mat cols;
cv::hconcat(mat, cols, mat);

Worst case scenario: rotate the image by 90 degrees and use Mat::resize(), making columns become rows.

Since OpenCV, stores elements of matrix rows sequentially one after another there is no direct method to increase column size but I bring up myself two solutions for the above matter,
First using the following method (the order of copying elements is less than other methods), also you could use a similar method if you want to insert some rows or columns not specifically at the end of matrices.
void resizeCol(Mat& m, size_t sz, const Scalar& s)
{
Mat tm(m.rows, m.cols + sz, m.type());
tm.setTo(s);
m.copyTo(tm(Rect(Point(0, 0), m.size())));
m = tm;
}
And the other one if you are insisting not to include even copying data order into your algorithms then it is better to create your matrix with the big number of rows and columns and start the algorithm with the smaller submatrix then increase your matrix size by Mat::adjustROI method.

Related

Armadillo: efficient RAM sparse batch insertion

I know that Sparse matrix in armadillo is still in preliminary support.
I'm using armadillo lib in my quantum systems research and I have problem to construct sparse mat in effective RAM way.
So far I was using my own implementation of sparse matrixes, but I want to have an optimized matrix class.
I'm filling elements in batch mode:
umat loc(2,size);
cx_vec val(size);
// calculate loc and val
...
//
sp_cx_mat Hamiltonian(loc, val);
This kind of action copy values from loc,val to constructor of Hamiltonian and for some few seconds require 2x RAM. I calculate huge matrix (size is about 2**L, where L=22, 24, ...) so I wish I had well optimised code in memory.
For comparison, matrix size: 705432x705432 - RAM and "filling time":
my implementation (COO format): time 7.95s, memory 317668kB
armadillo (CSC format): time 5.32s, memory 715000kB
Is it possible to deallocate fragments of vectors: loc, val on the fly to save memory, element by element?
The answer here will be to use the other sparse matrix constructor that takes the CSC format, so you will need to modify your // calculate loc and val code, instead filling the following three arrays:
values (length equal to number of points)
row_indices (length equal to number of points)
col_ptrs (length equal to number of columns plus one)
The points should be arranged in column-major ordering in the values and row_indices vectors, and the col_ptrs vector contains the number of nonzero elements before the beginning of the column. That is, col_ptrs[0] will always contain 0, col_ptrs[1] will contain the number of nonzero elements in the first column, col_ptrs[2] will contain the number of nonzero elements in the first and second columns, and col_ptrs[n_cols + 1] will contain the number of nonzero elements in the matrix.
For more documentation on this constructor, see the "Batch constructors" section of http://arma.sourceforge.net/docs.html#SpMat ; this is the fourth entry in that list.
If you cannot easily modify your calculation code to adhere to that format, then you might be better off trying to specify sort_locations = false to the constructor you are using, if you are not already doing that.

Reordering of matrix in c++

I have a matrix in C++, A(n,n) and a vector P(n) which looks something like this:
P = [ 3 6 1 13 12 16 ... ]
it contains numbers 1:n but not in an ascending order but scrambled.
My aim is to change the rows and columns of matrix A to the same order. For example since P[0] = 3 I want the 3rd row and 3rd column to move to the 1st row and column in matrix A.
But because the matrix could be potentially really large, I can't use another matrix of size same as A because that would be wasteful.
In matlab this can be done simply by using the command:
A(P,P);
Any ideas on how to do the same thing in c++?
I will suggest using a level of indirection, to locate each matrix in a cell.
Let's say your matrix object is called M. Instead of using
M[R][C]
to refer to the cell in row R, column C (assuming row-major matrix ordering), you will have an associated pair of vectors, let's call them y and x, so the value of the cell in row R column C is:
M[y[R]][x[C]]
Initially, both y and x vectors map each "logical" row or column to the corresponding physical row and column, that is both y and x contain [0..max_row] and [0..max_col].
Then, to effect the swapping in your question, you simply copy your P vector to the y and x vectors.
You should implement your matrix not directly, as a two-dimensional std::vector, but as a standalone class:
class Matrix {
public:
// ...
auto operator()(size_t R, size_t C) const;
auto &operator()(size_t R, size_t C);
// ...
};
and implement the indirect mapping of rows and columns as part of the class implementation.
Easiest way is probably to just brute-force it. The best idea is probably to do it row by row. You'll need a helper array of length N which keeps track of the original row index, and one temporary row. Then, starting at row R=0, check if row R is in the right position. If not, copy it to the temporary row, copy the right row to row R (permuting it on the go), and copy the temporary row to the spot that was just freed. If a row happens to be in the right spot, copy it to the temporary row, and permute it when copying back.

Insufficient memory opencv

I am beginner to OpenCV and C++.
I am trying to write PCA code for face recognition using 3 different faces. For this, each image(of size d=mxn) is reshaped to a column vector of d elements.
typedef vector<Mat> Row;
Row img1v(36000,img1);
Row img2v(36000,img2);
Row img3v(36000,img3);
I calculate the vector of mean of the images as follows:
Row meanImg;
for(int i=0;i<img1v.size();++i)
{
meanImg.push_back((img1v[i]+img2v[i]+img3v[i])/3);
}
cout<<meanImg.size()<<endl;
Here I get an error:
OpenCV Error: Insufficient memory (Failed to allocate 144004 bytes) in OutOfMemoryError
My image size is 180x200. I don't know what to do? Also how can I form a row vector in opencv using C++? (For calculating covariance I need to multiply difference vector with its traspose).
I don't know OpenCV and its types. But your typedef looks suspicious.
My guess is that the error occurs while creating the imgXv instances of Row. For each call of Row imgXv(36000,img1); a vector is created that consists of 36000 instances of Mat that are all copies of the imgX instances. See constructor 2) of std::vector::vector in cppreference.com:
vector( size_type count, const T& value, const Allocator& alloc = Allocator()); (2)
2) Constructs the container with count copies of elements with value value.
So you`re trying to keep 108003 images in memory. Each of your images consists of 36000 pixels. If each pixel is represented by at least 1 byte, this would occupy a minimum of 3.6 GB of memory.
From what I get of your approach you don't want that, but rather a typedef vector<float> Row; and Row imgXv(36000);

How to get values of a Matrix which are non zero

I am translating some matlab code to c++ using opencv. I want to get the values of a Matrix which satisfies a condition. I created a mask for this and when I apply it to the original Matrix I get the same size of the original matrix but with 0 values which are not there in the mask. But my question is how can I get only the values that are non-zero in the matrix and assign it to a different matrix.
My matlab code is:
for i= 1:size(no,1)
mask= labels==i;
op = orig(mask, :); //op only contains the values from the orig matrix which are in the mask. So orig size and op size is not the same
.....
end
The c++ translation that I have now is:
for (int i=0; i<n.rows; i++)
{
Mat mask;
compare(labels,i,mask,CMP_EQ);
Mat op;
orig.copyTo(op,mask); //Here the orig size and the op size is always same but values which are not in the mask are 0
}
So, how can I create a matrix which only has the values that the mask satisfies???
You might try to make use of cv::SparseMat (http://docs.opencv.org/modules/core/doc/basic_structures.html#sparsemat), which only keeps non-zero values in a hash.
When you assign a regular cv::Mat to a cv::SparseMat, it automatically captures the non-zero values. From that point, you can iterate through the non-zero values and manipulate them as you'd like.
Hope I got question correctly and it helps!
OpenCv does support Matrix Expresions like A > B or A <= Band so on.
This is stated in the Documentation off cv::Mat
If you're simply wanting to store values, the Mat object is probably not the best way, since it has been made for the purpose of containing images.
In that case, use an std::vector object instead of the cv::Mat object, and you can use the .push_back handle whenever you find an element that is non-zero, which will dynamically resize the vector.
If you're trying to create a new image, then you have to be specific about what kind of image you want to see, because if you don't know how many nonzero elements there are, how can you set the width and height? Also you might end up with an odd number of elements.

Best sparse matrix representation for column and row swaping

I am looking for sparse matrix representation that allow for efficient row and column swaping. The classic representation (by compressed row,compressed column or triplets) seems to only allow to perform one or the other but never booth.
Any one know a good data structure for this ?
--Edit--
To clarify , i want to be able to swap rows, like swap row 5 and row 7, and also swap column like swap column 6 and column 8.
You may just want to just add another level of indirection to handle swapping whichever is not efficient. For example, if you have a sparse representation that can efficiently swap rows but not columns, then have an array that maps from the true columns to the effective columns. When you access an element, use the array to find the proper underlying element.
class SparseMatrix {
public:
Element& operator()(Index row,Index col)
{
return matrix(row,col_map[col]);
}
void swapRows(Index row1,Index row2)
{
matrix.swapRows(row1,row2);
}
void swapCols(Index col1,Index col2)
{
swap(col_map[col1],col_map[col2]);
}
private:
FastRowSwapSparseMatrix matrix;
vector<Index> col_map;
};
My suggestion is
Eigen: Very fast and efficient for Linear algebra operations
http://eigen.tuxfamily.org/
or
Mapped Matrix in boost --> more flexible, but slower for linear algebra operations
http://www.boost.org/doc/libs/1_39_0/libs/numeric/ublas/doc/matrix_sparse.htm
For your case, both libraries allow you to manipulate rows and columns efficiently