OpenCV reshape function does not work properly - c++

I am using OpenCV reshape function in order to reshape Mat of 25 rows and 1 column (so we have 25 data values) into Mat of 5 rows and 5 columns.
data = mu.reshape(5, 5);
When I look at my data variable in debugger, it has 5 rows but 1 column. If I print data at row(0) and col(0) it outputs all five values. So basically each row at col(0) contains 5 values.
My desired result is to get 5 rows and 5 columns where on each (row,col) will be one value.
Thank you in advance for your help.

You seem to have misinterpreted the meaning of arguments of the reshape() function.
According to the documentation the signature is
Mat Mat::reshape(int cn, int rows=0) const
With the following meaning of the arguments:
cn – New number of channels. If the parameter is 0, the number of channels remains the same.
rows – New number of rows. If the parameter is 0, the number of rows remains the same.
Note that the number of columns is implicit -- it's calculated from the existing matrix properties and the two parameters.
According to this, the code
data = mu.reshape(5, 5);
creates a 5-channel matrix of 5 rows and 1 column.
In order to reshape you matrix to a single channel 5x5 matrix, you have to do the following:
data = mu.reshape(1, 5);
Alternately, since the input matrix is already single channel, you can also use
data = mu.reshape(0, 5);

Related

efficiently updating inplace certain blocks of a large sparse matrix in Eigen?

Suppose that I have a large sparse matrix with the following pattern:
the number of nonzeros per column and their locations are fixed
only matrix block A and B will change and the rest of the matrix stays static; (blocks A and B themselves are also sparse with fixed nonzero locations)
As instructed in the document, i've initialized the above matrix by
reserving the exact number of nonzeros per column for the column major sparse matrix
inserting column by column
inserting from the smallest row index per column
In later part of the program, it's natural to reuse the matrix and only updates the A, B blocks inplace. Possible ways are:
accessing existing entries by coeffRef, would introduce binary search so not preferred here.
iterating over the outer and inner dimensions as documented here
However, it seems a bit unnecessary to iterate over all nonzero entries since most part of the sparse matrix stays the same.
Is it possible to update A, B inplace without iterating over all nonzeros in the matrix?
From what I can tell, the InnerIterator can be used used for this and runs in constant time.
Eigen::Index col = 1;
Eigen::Index offset_in_col = 1;
using SparseMatrixD = Eigen::SparseMatrix<double>;
SparseMatrixD mat = ...;
SparseMatrixD::InnerIterator i =
SparseMatrixD::InnerIterator(mat, col) + offset_in_col;
assert(i.row() == 1);
assert(i.col() == 1);
assert(i.value() == C);
This should access the value C. All you need to know is how many nonzero elements are per column (or inner dimension in general). You don't need to know how many nonzero columns (outer dimensions) are stored because that array (SparseMatrix.outerIndexPtr()) has one entry per column.

How to grab the last non empty row?

So here's the scenario. In this case i will start at row 2 as starting point. in Column B, i want to record row of the last non empty A column. For example : the first data in B column is 2 which is the very first row then in the next row it will keep that '2' as long as the A column is empty until i reach a value (1) in the A column. When it reach the next non empty row in A column (row 7), then value in B now will keep that value (7) and it will keep that value all the way down until it reach the next non empty row in A , which is row 15. etc. Hope i can explain it clearly.
for now i only use basic formula in B2 cell :
=if( A2<>1, min( row(A2), indirect( "b" & (row(A2) -1) ) ) , row( A2) )
and then copy it down to other cells in B column. It works. But i'm just want to convert this into arrayformula() and got no luck. Does anyone know how to make this works using arrayformula ?
use:
=INDEX(VLOOKUP(ROW(A2:A), {2; FILTER(ROW(A3:A), A3:A<>"")}, 1, 1))
Try this:
=ArrayFormula(vlookup(row(A2:A24),query({row();ArrayFormula(value(substitute(A3:A24,1,row(A3:A24))))},"select * where Col1>0"),1,true))
It has a few stages:
First it takes row number from the first cell using row(). Then it substitutes all 1 cells in column A into corresponding row numbers. Then using query I remove empty or 0 values. I got a small table of:
2
7
15
19
Next stage is to take each row number from a2:a24 and vlookup through my table.
Using vlookup with 'true' parameter it returns nearest value from the table that is smaller than row number tested. So 2 returns 2, 3 returns 2, 4 returns 2, etc.

compute sum of value in an rectangle area of array

I have a very big array of many value and store it in an row-major 1d array.
ex:
1 2 3
4 5 6
will be store in int* array = {1,2,3,4,5,6};
what I have to do is given the row1, row2, column1, column2, then print out the area's sum, and it will request to caulate different area for many times.
what I have think about it is first use nested loop to traverse the array and store each row's sum in sum_row and store each column's sum in sum_column and store the total element's sum im totalSum.
Then totalSum - the row and the columns that surrond it + the elemnts that has been minus twice.
But it seems fast enough, is there any algorithm that can do faster or some coding style tips that can make the factor little?
Thx in advance.
It seems to me that you have replaced one double iteration with another. The problem is in subtracting "the elemnts that has been minus twice"; unless I'm mistaken, this involves iterating over those elements to sum them.
Instead, just iterate over the rectangular area that you need to sum. I doubt it will be any slower.
A more efficient algorithm can be obtained by generating the matrix of summed upper-left matrices. (See the Wikipedia article on summed area table.) You can then compute any submatrix sum by looking up four area sums.

Matrix operations on SAS

I have a single line/multi column matrix, multiplied by a square matrix. SAS gives me a single line result. So far, from what I remember from college math, and asking people, okay.
But the line from SAS that does it is this one:
fieldA = matrix1`*matrix2[,1:fieldB]
while I understand "fieldA = matrix1`*matrix2", I have no idea what [,1:fieldB] does, and I can't seem to find any document that explains it.
matrix2[,1:fieldB] is subsetting matrix2. It includes all rows of matrix2, and only those columns that are included in the list 1:fieldB. Presumably fieldB identifies the number of columns in matrix1 (which become rows when transposed) so the * works [matrix1' rows must equal matrix2 columns for the operation to be legal].
For example, imagine matrix1 is the following matrix:
[1,3,5]
and matrix2 is the following matrix:
[1,2,3,4,
4,5,6,7,
8,9,10,11,
13,14,15,16]
Now,
matrix1`*matrix2
is illegal - matrix1` has 3 rows (transposed) and matrix2 has 4 columns. So:
matrix1`*matrix2[,1:3]
will now be legal, yielding the matrix product of matrix1` by the first 3 columns of matrix2.

Position of elements in vector

I have several elements in a vector type that are read from cin and then i perfrom some calculations on the vector and it's order of elements gets changed. The problem is that I need to print the positions of the vector elements after the calculations. I don't know how to explain this well that's why i'll give an example:
10 1 100 1000
and 10 is 1st element, 1 is 2nd, 100 is 3rd etc. After the calculations the vector changes in :
100 10 1 1000
so I should print
3 1 2 4
because 100 is the 3rd element of the input, 10 is the 1st etc. etc.
I tried with an array[1000] (because there aren't numbers larger than 1000 in the input), but it won't work because there can be multiple numbers with the same value, like:
10 10 10 100
and the output can be 1 2 3 4 or 2 3 1 4 or 3 1 2 4 etc. but here i need to output 1 2 3 4 because it's the 'smallest'.
I tried with array f[1001] and f[10] = 1, f[100] = 2, f[1] = 3 - if the numbers from the input are 10 100 1. But in case there are multiple numbers with the same value like 10 10 100, then my idea's not working. Please help me in any possible way.
Sounds like you need to store both the value and the initial position. You should be able to do this with an array of structs:
struct UserInput
{
unsigned int initialPosition;
int userInputValue;
};
int main()
{
userInput theUserInput[100];
// increment a counter, starting at 1, and place it in
// "initialPosition" in the struct as user input is read
}
I'll leave the rest up to you... as it is after all homework :) good luck.
Use an associative array if you know what it is.
Use linear search to determine the index if the number of input is limited.
Consider using log10 (or strlen) to transform the 1, 10, 100, 1000, etc. into 0, 1, 2, 3, etc.
From your description of such example:
10(3) 10(2) 10(1) 100(4)
What we have to output is 1 2 3 4, instead of 3 2 1 4.
So I don't think your requirement is just print the initial position directly. You've to make the position sequences as small as possible.
Following is my solution:
Use a direct-mapping hash table to store all the initial positions for specified element. All the initial positions for the same element is sorted. So if you want output the smallest position sequence, you only need to read the initial positions for this specified element from first to last.
The detailed implementation is left to you, since it's a homework.