Convert Mat to <vector<vector>> C++ - c++

How to convert Mat in 2d vector (vector of vector) in C++?
I tried this, and got error in Mat.at function.
vector<vector<double>> dctm(300, vector<double>(300,0));
for (int i = 0; i < 300; i++) {
for (int j = 0; j < 300; j++) {
dctm[i][j] = img.at<double>(i, j);
}
}

You can fill the vector by iterating over values and pushing them one by one, but in general this is not considered a good practice. Much better solution is to use range functions provided to you by stl. This is true not only for vector but for any other stl structure.
Cleaner (from stl point view) and faster solution should be like this:
for(int i=0; i<300; i++)
{
Mat r = img.row(i);
dctm.push_back(vector<double>(r.begin<unsigned char>(), r.end<unsigned char>()));
}

Much faster way would be
vector<vector<double>> dctm(300, vector<double>(300,0));
for (int i = 0; i < 300; i++) {
uchar *rowPtr = img.ptr<uchar>(i);
for (int j = 0; j < 300; j++) {
dctm[i][j] = *rowPtr[j];
}
}
See How to scan images, lookup tables and time measurement with OpenCV

Related

how to use open dft in 2d vector

I would like to ask how to use the dft function in opencv to do Fourier transform with 2d vector.
I have error in my code ...
thank you all
//2d vector in here v1 and v2
//vector size is 1000*1000
//i have to do about 600 images in this process
for (int k = 0; k < 600; k++){
vector <vector <complex < double >>> v1(InputWidth, vector<complex < double >>(InputHeight));
vector <vector <complex < double >>> v2(InputWidth, vector<complex < double >>(InputHeight));
for (int i = 0; i < InputWidth; i++) {
int tempIndex = i*InputHeight;
for (int j = 0; j < InputHeight; j++)
{
int Correction_value = ProjectionImage[k]->data.s[tempIndex + j] * meshGrid[tempIndex + j];
ProjectionImage[k]->data.s[tempIndex + j] = Correction_value;
//v1 is an image
v1[i][j] = Correction_value;
}
}
//error happen in here
dft(v1, v2, DFT_COMPLEX_OUTPUT);
//do frequency filter
for (int i = 0; i < InputWidth; i++) {
for (int j = 0; j < InputHeight; j++)
{
v2[i][j] *= filter_2D[i][j];
}
}
//inverse fourier transform
idft(v2, v1, DFT_COMPLEX_OUTPUT);
}
error message
What is happening here is that you create a std::vector of pointers to other vectors. Those other vectors contain the pixel data. But those data are therefore not necessarily contiguous. Each row (or column) of your image is stored in its own memory segment. OpenCV expects all pixels to be in the same memory segment.
In short, simply copy your pixel data to a form supported by OpenCV, such as a cv::Mat.

Multiplying Matrices using 2d Vectors in C++

I'm trying to design a program that creates a matrix using vectors of vectors of integers, and then multiplyies it with another matrix. I know how to multiply matrices on paper, but when I try to implement it in my program, I'm not getting it to work. I know that both matrices are entered correctly and are passed correctly as I have the the output of those functions so that I can debug. The program works incorrectly when I try to multiply them. The answer and the number of elements are not right. I know I'm missing something but can't figure out what.
Matrix Matrix::operator*(Matrix m){
vector<int> mRow = m.getRow(0);
vector<int> mCol = m.getCol(0);
vector<int> newElem;
int product = 0;
//adds the contents of the 2nd matrix to the 2d vector
vector< vector<int> > m2(mRow.size(), vector<int>(mCol.size()));
for (int i = 0; i < mRow.size(); i++){
mRow.clear();
mRow = m.getRow(i);
for (int j = 0; j < mCol.size(); j++){
m2[j][i] = mRow[j];
}
}
//Multiplies the matrices using the 2d matrix**THIS IS WHERE IT GOES WRONG**
for (int i = 0; i < row; i++){
for (int j = 0; j < column; j++){
product += matrix[i][j]*m2[j][i];
}
newElem.insert(newElem.begin()+i,product);
product = 0;
}
//displays the products so that i can see if its working
for (int i = 0; i < newElem.size(); i++){
cout << " "<<newElem[i]<<endl;
}
//adds the new product vector to a new Matrix object and returns it
Matrix newM(row, mCol.size());
vector<int> temp;
for (int i = 0; i < row; i++){
for (int j = 0; j < mCol.size(); j++){
temp.insert(temp.begin()+j, newElem[0]);
newElem.erase(newElem.begin());
}
newM.setRow(temp,i);
temp.clear();
}
return newM;
}
Although I don't know whether this helps, I'm using this site as a reference for multiplying 2 matrices together.
Your matrix representation has nothing to do with your mistake. You need to have more nested iterations. Think of a result matrix and iterate through that to calculate it's every element. In a pseudocode:
for i in result column
for j in result row
res[i, j] = multiply(m1, m2, i, j)
where multiply function is the nested loop, something like this:
multiply(m1, m2, i, j)
{
val = 0;
for k in row
val += m1[i, k] * m2[k, j]
return val
}
Here is an implementation of the outer loops. Mind you, there are no error checking in the code.
vector<vector<int> > ml;
vector<vector<int> > mr;
// fill in ml and mr
...
// result matrix
vector<vector<int> > res;
// allocate the result matrix
res.resize(ml.size());
for( it = res.begin(); it != res.end(); ++it)
it->resize(ml[0].size());
// loop through the result matrix and fill it in
for( int i = 0; i < res.size(); ++i)
for( int j = 0; j < res[0].size(); ++j)
res[i][j] = multiply(ml, mr, i, j);
Leaving a proper implementation of multiply() function to you.

C++ create array with dynamic size

How can I create a array with dinamic size like this:
int sentLen = sentences.size();
double a[sentLen][sentLen];
for (int i = 0; i < sentLen; i++)
{
for (int j = 0; j < sentLen; j++)
{
a[i][j] = somefunction(i, j);
}
}
My research led me to malloc which isn't recommended or other too complicated methods. After I realised that size must be constant, I tried using unordered_map, and I have tried the following:
std::unordered_map <int, int, double> a;
for (int i = 0; i < sentLen; i++)
{
for (int j = 0; j < sentLen; j++)
{
a.insert({ i, j, somefunc(i, j) });
}
}
but still unsuccessful.
You don't really want to use arrays.
std::vector<std::vector<double>> a{
sentLen, std::vector<double>{ sentLen, 0.0 } };
for (int i = 0; i < sentLen; ++i)
{
for (int j = 0; j < sentLen; ++j)
{
a[i][j] = somefunc(i, j);
}
}
You're getting an error because you can't use variables as static array sizes. They must be known at compile time. You have to allocate dynamically or use a vector instead.

Manipulating specific x,y values of a cv::Mat?

What is the simplest way to modify a direct x,y location of a cv::Mat object? I have a cv::Mat called 'temp' which has an image in it, and what if I wanted to turn each pixel pink, one by one?
I tried something of the following:
for (int i = 0; i < temp.size().width; i++)
{
for (int j = 0; j < temp.size().height; j++)
{
temp.at(cv::Point(i, j)) = 255;
cv::waitKey();
}
}
but that won't even compile..
The way to use at in this case is temp.at<unsigned char>(i, j).
Here is an example :
Mat H(100, 100, CV_64F);
for(int i = 0; i < H.rows; i++)
for(int j = 0; j < H.cols; j++)
H.at<double>(i,j)=1./(i+j+1);
For the complete description look here: http://opencv.itseez.com/modules/core/doc/basic_structures.html#mat-at

optimize 2D array in C++

I'm dealing with a 2D array with the following characteristics:
const int cols = 500;
const int rows = 100;
int arr[rows][cols];
I access array arr in the following manner to do some work:
for(int k = 0; k < T; ++k) { // for each trainee
myscore[k] = 0;
for(int i = 0; i < cols; ++i) { // for each sample
for(int j = 0; j < rows; ++j) { // for each expert
myscore[k] += delta(i, anotherArray[k][i], arr[j][i]);
}
}
}
So I am worried about the array 'arr' and not the other one. I need to make this more cache-friendly and also boost the speed. I was thinking perhaps transposing the array but I wasn't sure how to do that. My implementation turns out to only work for square matrices. How would I make it work for non-square matrices?
Also, would mapping the 2D array into a 1D array boost the performance? If so, how would I do that? Finally, any other advice on how else I can optimize this... I've run out of ideas, but I know that arr[j][i] is the place where I need to make changes because I'm accessing columns by columns instead of rows by rows so that is not cache friendly at all.
Thanks,
Hristo
A general in-place matrix transposition is very difficult, but if you're okay with transposing it to another array, then it's pretty simple.
const int cols = 500;
const int rows = 100;
int arr[rows][cols];
// fill arr[][]
int arrT[cols][rows];
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
arrT[c][r] = arr[r][c];
}
}
Of course, depending on how you're getting arr[][], you can just fill arrT[][] directly instead.
However, there may be a simpler solution of simple swapping the order of the loops.
for(int k = 0; k < T; ++k) { // for each trainee
myscore[k] = 0;
for(int j = 0; j < rows; ++j) { // for each expert
for(int i = 0; i < cols; ++i) { // for each sample
myscore[k] += delta(i, anotherArray[k][i], arr[j][i]);
}
}
}
Yes, 1d should be faster than 2d. C and C++ arrays are always 1d (internally).
When you call something like
array[row][col]
the compiler actually calculates
col + row * maxcols
and uses that as the actual index of a 1d array. You might as well do that yourself. Cycling through an entire array will be way faster, and random access will be equally fast as in a 2d array.
for(int i = 0; i < N; ++i) { // for each sample
for(int j = 0; j < E[i]; ++j) { // for each expert
... arr[j][i] ... // each ++j causes a large stride => poor caching
}
}
transpose the loops:
for(int j = 0; j < E[i]; ++j) { // for each expert
for(int i = 0; i < N; ++i) { // for each sample
... arr[j][i] ... // each ++i looks to the next word in memory => good
}
}
Of course, without seeing everything else in the program, I can't say if that would cause a problem. If delta doesn't have side effects, you should be fine.
You want memory accesses to be adjacent. In your case simply swap I and j when accessing arr.