OpenCV: append different vectors as one row - c++

I have a cv::Mat1f vector which size is kxd. How can I fill it by appending k different 1xd vectors?
I want to do something like:
int k = 3, d = 3;
cv::Mat1f testMat(1,k*d);
for(int i=0; i<k;i++){
cv::Mat1f partial(1,d,i);
testMat.push_back(partial);
}
Notice that the example above is much simpler that my real case.

I found a solution, but I don't know if it's the best one
int k = 3, d = 3;
cv::Mat1f testMat(1,k*d);
for(int i=0; i<k;i++){
cv::Mat1f partial(1,d,i);
testMat.push_back(partial);
}
testMat = testMat.reshape(1,1);

Related

Create 2d array from a division of two 1d-arrays in arrayfire

I have two 1d-arrays in arrayfire, x and y. I would like to divide them through each other, and create a 2d-array from the result, i.e. as shown in the following code:
#include <arrayfire>
int main(void){
const size_t x_len = 1024, y_len = 2048;
af::array x(x_len, f64), y(y_len, f64);
//Fill x, y with y \neq 0
//Now either
af::array xy(x_len, y_len, f64); //Gives a 2d-array
for(size_t i = 0; i < x.dims(0); ++i)
for(size_t j = 0; j < y.dims(0); ++j)
xy(i, j) = x(i) / y(j);
//or
af::array xy = x / y; //Gives a 1d-array
return 0;
}
The former approach gives me the targeted 2d-array, the latter approach does not (and will result in a crash if x_len != y_len. I could use the approach written above, but I assume that it will be significantly slower than specialized commands.
Therefore, are there such commands available in arrayfire, or do I have to use loops?
af::array xy = matmulNT(x, 1/y);

Access 2D array with 1D iteration

If I define an array as follows:
int rows = 10;
int cols = 10;
double **mat;
mat = new double*[rows];
mat[0] = new double[rows*cols];
for(int r=1; r<10; r++)
mat[r] = &(mat[0][r*cols]);
How do I iterate over this array via 1-dimension?
E.g. I'd like to do the following:
mat[10] = 1;
to achieve the same thing as
mat[1][0] = 1;
Is there a way to dereference the double** array to do this?
With your definition of mat, you can do this:
double* v = mat[0]; 'use v a uni-dimensional vector
for(int i =0; i< rows* cols; i++) v[i] = 1;
Alternatively,if what you wanted was to define mat itself as a uni-dimensional vector and use it as bi-dimensional in a tricky way:
double mat[rows * cols];
#define MAT(i, j) mat[i*cols + j]
MAT(1, 0) = 1;
<=>
mat[10] = 1
now you have the options to span the matrix in one-dimension using mat or bi-dimension using the MAT macro
mat[row * cols + column]
where row is the row you want to access and column is the column you want to access.
Of course an iteration over the array would just involve some kind of loop (best suited would be for) and just applying the pattern every time.

Opencv: How to I get and then change values of "Mat vector"

I want to do an operation like this however I cannot get the values of the vector Mat and change them. table is a 1 dimensional array by the way. Thanks.
vector<Mat> orjchannel;
vector<Mat> refchannel;
// There are some functions here
for (int i = 0; i < 512; i++){
for (int j = 0; j < 512; j++){
double value = refchannel[i][j]; // This part does not work
orjchannel[i][j] = tables[value];
With OpenCV, you typically access the values of a Mat with the at<DATATYPE>(r,c) command. For example...
// Mat constructor
Mat data(4, 1, CV_64FC1);
// Set Value
data.at<double>(0,0) = 4;
// Get Value
double value = data.at<double>(0,0);

Multi-Dimensional data in a Matrix in OpenCV with C++

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)

Convert Mat to **float

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: