Matrix manipulation on MATLAB to C++ or OpenCV - c++

I'm trying to do this operation in C++, but I cant wrap my head around it.
I tried looking in http://mathworks.com/help/matlab/ref/image.html but I still don't get it.
im is a matrix in Matlab. Width is 640
im(:,Width+(1:2),:) = im(:,1:2,:);
Is there anything similar to this operation in OpenCV Matrix or C++

Solution 1
You can use colRange function:
mat.colRange(0, 2).copyTo(mat.colRange(w, 2 + w));
Example:
//initilizes data
float data[2][4] = { { 1, 2, 3, 4}, { 5, 6, 7, 8 } };
Mat mat(2, 4, CV_32FC1, &data);
int w = 2; //w is equivelant to Width in your script, in this case I chose it to be 2
std::cout << "mat before: \n" << mat << std::endl;
mat.colRange(0, 2).copyTo(mat.colRange(w, 2 + w));
std::cout << "mat after: \n" << mat << std::endl;
Result:
mat before:
[1, 2, 3, 4;
5, 6, 7, 8]
mat after:
[1, 2, 1, 2;
5, 6, 5, 6]
Solution 2
Alternatively, use cv::Rect object, as follows:
cv::Mat roi = mat(cv::Rect(w, 0, 2, mat.rows));
mat(cv::Rect(0, 0, 2, mat.rows)).copyTo(roi);
There are several way to initialize a Rect, in my case I chose the following c-tor:
cv::Rect(int x, int y, int width, int height);
The result are the same as an in Solution 1.

Maybe you could also use Eigen that can serve the need. It has Block operations
Adapting the example provided under link you would need smth like:
Eigen::MatrixXf m(4, 4);
m << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16;
cout <<"original matrix \n" << m << endl;
m.block<2, 2>(1, 1) = m.block<2, 2>(2, 2);
cout <<"modified matrix \n" << m << endl;
Output:
original matrix
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
modified matrix
1 2 3 4
5 11 12 8
9 15 16 12
13 14 15 16

Related

OpenCV matrix element-wise division gives all-zero result

I use OpenCV by cocoapod on iOS C++ code. When running my app, I find it works abnormally. Finally, after digging down, I can give the following reproducible sample:
{
Mat a = (Mat_<uchar>({10, 20, 30, 40, 50, 60, 70, 80})).reshape(1, 1);
Mat b = (Mat_<uchar>({4, 5, 6, 7, 8, 9, 10, 11})).reshape(1, 1);
Mat c;
divide(a, b, c);
std::cout << "hello naive " << "a=" << a << endl << "b=" << b << endl << "a/b=" << (a / b) << "c=" << c << endl;
}
{
Mat a = (Mat_<uchar>({10, 20, 30, 40, 50, 60, 70})).reshape(1, 1);
Mat b = (Mat_<uchar>({4, 5, 6, 7, 8, 9, 10})).reshape(1, 1);
Mat c;
divide(a, b, c);
std::cout << "hello naive " << "a=" << a << endl << "b=" << b << endl << "a/b=" << (a / b) << "c=" << c << endl;
}
And the result:
im_sta[a]: {size=1 x 8, type=0, empty=0, min=10.000000, max=80.000000, miu=[45], sigma=[22.9]}
im_sta[b]: {size=1 x 8, type=0, empty=0, min=4.000000, max=11.000000, miu=[7.5], sigma=[2.29]}
im_sta[a / b]: {size=1 x 8, type=0, empty=0, min=0.000000, max=0.000000, miu=[0], sigma=[0]}
hello naive a=[ 10, 20, 30, 40, 50, 60, 70, 80]
b=[ 4, 5, 6, 7, 8, 9, 10, 11]
a/b=[ 0, 0, 0, 0, 0, 0, 0, 0]c=[ 0, 0, 0, 0, 0, 0, 0, 0]
im_sta[a]: {size=1 x 7, type=0, empty=0, min=10.000000, max=70.000000, miu=[40], sigma=[20]}
im_sta[b]: {size=1 x 7, type=0, empty=0, min=4.000000, max=10.000000, miu=[7], sigma=[2]}
im_sta[a / b]: {size=1 x 7, type=0, empty=0, min=2.000000, max=7.000000, miu=[5.29], sigma=[1.67]}
hello naive a=[ 10, 20, 30, 40, 50, 60, 70]
b=[ 4, 5, 6, 7, 8, 9, 10]
a/b=[ 2, 4, 5, 6, 6, 7, 7]c=[ 2, 4, 5, 6, 6, 7, 7]
(where im_sta is some extra statistics that I printed for more details, you can ignore it as well).
As you can see, in some cases (seems that when >=8 elements), that division results in ALL-ZERO!
How can I fix it? Thanks!
I find the answer later. Thus I post it here as a self-QA, in order to help people who have the same problem as me.
Solution: Upgrade OpenCV from 4.1 to 4.3! Then it is ok!
Actually, as you can see from the photo below, OpenCV >=4.2.0 is only available as cocoapod since 3 months ago (even if now it is 4.5.0 already)... So this is a quite new fix, if you do not want to compile opencv from source code by yourself... (When I started my project (of course before 3 months ago) there was only 4.1.0)

trouble debugging c++ code pointer in Visual studio

I will like to list each member of an array listed with its corresponding register address location. Here is my code
// PointerDeferenceTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int x=0, y=0;
int *px, *py;
int number[15] = {-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9};
while (x<14)
{
px = &x;
py = number+x;
cout << x+1 << ", " << px << ", " << *px << ", " << py << ", " << *py << ", " << py++ << ", " << *(py++) << ", " << *(++py) << " \n";
++x;
}
return 0;
}
Running at 64 bits getting the following unexpected result
1, 000000D7532FF874, 0, 000000D7532FF904, -1, 000000D7532FF900, -3, -1
2, 000000D7532FF874, 1, 000000D7532FF908, 0, 000000D7532FF904, -2, 0
3, 000000D7532FF874, 2, 000000D7532FF90C, 1, 000000D7532FF908, -1, 1
4, 000000D7532FF874, 3, 000000D7532FF910, 2, 000000D7532FF90C, 0, 2
5, 000000D7532FF874, 4, 000000D7532FF914, 3, 000000D7532FF910, 1, 3
6, 000000D7532FF874, 5, 000000D7532FF918, 4, 000000D7532FF914, 2, 4
7, 000000D7532FF874, 6, 000000D7532FF91C, 5, 000000D7532FF918, 3, 5
8, 000000D7532FF874, 7, 000000D7532FF920, 6, 000000D7532FF91C, 4, 6
9, 000000D7532FF874, 8, 000000D7532FF924, 7, 000000D7532FF920, 5, 7
10, 000000D7532FF874, 9, 000000D7532FF928, 8, 000000D7532FF924, 6, 8
11, 000000D7532FF874, 10, 000000D7532FF92C, 9, 000000D7532FF928, 7, 9
12, 000000D7532FF874, 11, 000000D7532FF930, 0, 000000D7532FF92C, 8, 0
13, 000000D7532FF874, 12, 000000D7532FF934, -858993460, 000000D7532FF930, 9, -858993460
14, 000000D7532FF874, 13, 000000D7532FF938, -858993460, 000000D7532FF934, 0, -858993460
I cannot figure out what I am doing wrong. The 4th column (py) is starting to list the 4th item in the array. But the code is set to read the first (number[0]).
I amusing W10 Visual studio community 2017 compile 64 bit
UPDATE 1: In response to PhoenixBlue comment. Amended the array sample to use different numbers.
UPDATE 2: This is my expected result
1, 000000D7532FF874, 0, 000000D7532FF904, -4, 000000D7532FF900, -3, -1
2, 000000D7532FF874, 1, 000000D7532FF908, -3, 000000D7532FF904, -2, 0
3, 000000D7532FF874, 2, 000000D7532FF90C, -2, 000000D7532FF908, -1, 1
4, 000000D7532FF874, 3, 000000D7532FF910, -1, 000000D7532FF90C, 0, 2
5, 000000D7532FF874, 4, 000000D7532FF914, 0, 000000D7532FF910, 1, 3
6, 000000D7532FF874, 5, 000000D7532FF918, 1, 000000D7532FF914, 2, 4
7, 000000D7532FF874, 6, 000000D7532FF91C, 2, 000000D7532FF918, 3, 5
8, 000000D7532FF874, 7, 000000D7532FF920, 3, 000000D7532FF91C, 4, 6
9, 000000D7532FF874, 8, 000000D7532FF924,4, 000000D7532FF920, 5, 7
10, 000000D7532FF874, 9, 000000D7532FF928, 5, 000000D7532FF924, 6, 8
11, 000000D7532FF874, 10, 000000D7532FF92C, 6, 000000D7532FF928, 7, 9
12, 000000D7532FF874, 11, 000000D7532FF930, 7, 000000D7532FF92C, 8, 0
13, 000000D7532FF874, 12, 000000D7532FF934, 8, 000000D7532FF930, 9, -858993460
14, 000000D7532FF874, 13, 000000D7532FF938, 9, 000000D7532FF934, 0, -858993460
This code is a problem py++ << ", " << *(py++) << ", " << *(++py).
In C++ you should not use multiple increments of the same variable in the same expression.
Rewrite your code like this
cout << x+1 << ", " << px << ", " << *px << ", " << py << ", " << *py << ", ";
cout << py++ << ", ";
cout << *(py++) << ", ";
cout << *(++py) << " \n";
That should fix some of the problems although as Msalters says you have other problems as well.
py overflows, when x==13, and so py=&number[13] before you increment it twice. That is Undefined Behavior, which may result in any outcome.
You probably will have more issues once you've fixed this, but Undefined Behavior is so severe that you cannot reason about minor bugs in the presence of UB. UB is so bad, it can appear to "travel back in time". You can't say "Foo happened before the UB, so it should be unaffected by it". Since UB can do anything, it can also change the past.

storing a 2D array into a 2D vector in c++

Suppose I have a following 2D matrix in the following format. First line indicates the dimension and the rest other lines contains the elements. In this case it's a 6*6 Matrix:
6
1 2 3 4 2 3
3 3 4 5 2 1
4 3 3 1 2 3
5 4 3 6 2 1
3 2 4 3 4 3
2 3 4 1 5 6
Normally we can store the matrix in a vector using this:
typedef std::vector<int32_t> vec_1d;
typedef std::vector<vec_1d> vec_2d;
vec_2d array{
{ 1, 2, 3, 4, 2, 3 }
, { 3, 3, 4, 5, 2, 1 }
, { 4, 3, 3, 1, 2, 3 }
, { 5, 4, 3, 6, 2, 1 }
, { 3, 2, 4, 3, 4, 3 }
, { 2, 3, 4, 1, 5, 6 }
};
But if I want to take this array in the format I have shown above from a text file into a 2d vector like the above one, how will I do this in c++ ?
This should work:
#include "fstream"
#include "vector"
using namespace std;
int main()
{
ifstream fin("file.txt");
int n;
fin >> n;
vector < vector <int> > matrix (n, vector <int>(n));
// or vec_2d matrix (n, vec_1d(n)); with your typedefs
for (auto &i: matrix)
for (auto &j: i)
fin >> j;
}

set_union issue while using arrays

I am trying to get union of 4 arrays using set_union. Here is the code I have so far:
int setA[5] = {2, 4, 5, 7, 8};
int setB[7] = {1, 2, 3, 4, 5, 6, 7};
int setC[5] = {2, 5, 8, 8, 15};
int setD[6] = {1, 4, 4, 6, 7, 12};
int AunionB[12];
int CunionD[11];
int finalUnion[23];
int *lastAunionB;
int *lastCunionD;
ostream_iterator<int> screen(cout, " ");
lastAunionB = set_union(setA, setA+5, setB, setB+7, AunionB);
cout << "AunionB = ";
copy(AunionB, lastAunionB, screen);
cout << endl;
lastCunionD = set_union(setC, setC+5, setD, setD+6, CunionD);
cout << "CunionD = ";
copy(CunionD, lastCunionD, screen);
cout << endl;
set_union(AunionB, AunionB+12, CunionD, CunionD+11, finalUnion);
cout << "Final Union = ";
copy(finalUnion, finalUnion+23, screen);
cout << endl;
When I ran the code, I got the following output:
AunionB = 1 2 3 4 5 6 7 8
CunionD = 1 2 4 4 5 6 7 8 8 12 15
Final Union = 1 2 3 4 5 6 7 2 4 4 5 6 7 8 8 12 15 52187240 1 1863041424 32767 0 0
Therefore, the unions of setA and setB works as intended as does the union of setC and setD. However, when I try to get the union of all for sets, it doesn't work! I'm guessing the last 5 values of finalUnion are the address fields but how do I remove them? Also, the union itself is incorrect and I can't understand why.
The size of the AunionB and Cuniond is not 12 and 11 because:
Elements from the second range that have an equivalent element in the first range are not copied to the resulting range.
Try this code:
int setA[5] = { 2, 4, 5, 7, 8 };
int setB[7] = { 1, 2, 3, 4, 5, 6, 7 };
int setC[5] = { 2, 5, 8, 8, 15 };
int setD[6] = { 1, 4, 4, 6, 7, 12 };
int AunionB[12];
int CunionD[11];
int finalUnion[23];
int *lastAunionB;
int *lastCunionD;
ostream_iterator<int> screen(cout, " ");
lastAunionB = set_union(setA, setA + 5, setB, setB + 7, AunionB);
cout << "AunionB = ";
copy(AunionB, lastAunionB, screen);
cout << endl;
lastCunionD = set_union(setC, setC + 5, setD, setD + 6, CunionD);
cout << "CunionD = ";
copy(CunionD, lastCunionD, screen);
cout << endl;
int *finalUnionEnd;
finalUnionEnd = set_union(AunionB, lastAunionB, CunionD, lastCunionD, finalUnion);
cout << "Final Union = ";
copy(finalUnion, finalUnionEnd, screen);
cout << endl;
And then you got the right result:
Final Union = 1 2 3 4 4 5 6 7 8 8 12 15
A Union operation removes values that the two sets have in common.
Note that AUnionB has 8 elements (not the 12 that your code predicts).
You need to adjust your union-of-union code to account for the actual size of the two initial unions. You have everything prepared to do it correctly:
int *lastFinalUnion = set_union(AunionB, lastAunionB, CunionD, lastCunionD, finalUnion);
Note that set C has two distinct occurrences of 8 and set D has two distinct occurrences of 4, which is why they appear duplicated in the intermediate result.
UPDATE
Also, I tried your code and i'm getting the answer as 1 2 3 4 5 6 7 2 4 4 5 6 7 8 8 12 15 . Shouldn't the answer be 1 2 3 4 4 5 6 7 8 8 12 15
I believe you are correct, but I'm not in front of a C++ compiler to step through and see what's doing on, or to verify your output. The actual code was edited in by another SO member, but it looks correct to me.
In the simplest case, set_union performs the "union" operation from set theory: the output range contains a copy of every element that is contained in [first1, last1), [first2, last2), or both. The general case is more complicated, because the input ranges may contain duplicate elements. The generalization is that if a value appears m times in [first1, last1) and n times in [first2, last2) (where m or n may be zero), then it appears max(m,n) times in the output range.
https://www.sgi.com/tech/stl/set_union.html

Extracting and sorting data in an array?

Here is my array:
int grid[gridsize+1] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3, 2, 2, 4, 1, 5, 3, 3, 6, 2, 6, 4, 5, 5, 5, 3, 6, 2, 6, 4, 4, 5, 5, 5, 6, 6, 6, 4, 7, 7, 8, 5, 8, 8, 8, 4, 7, 7, 8, 8, 8, 8, 8, 4, 7, 7, 7, 7, 8, 8, 8 };
Each number represents a colour, I would like to create multiple arrays for each unique number. The created arrays will store the locations of that number from the original array.
e.g
colour1[5]
[0]=0 //because the number 1 is stored in element 0.
[1]=1
[2]=8
[3]=9
The numbers in grid will change every time I run, so things need to be dynamic?
I can write inefficient code that accomplishes this, but it's just repetitive and I can't comprehend a way to turn this into something I can put in a function.
Here is what I have;
int target_number = 1
grid_size = 64;
int counter = -1;
int counter_2 = -1;
int colour_1;
while (counter < grid_size + 1){
counter = counter + 1;
if (grid[counter] == target)
counter_2 = counter_2 + 1;
colour_1[counter_2] = counter;
}
}
I have to do this for each colour, when I try to make a function, it cannot access the main array in main so is useless.
You can just use vector<vector<int>> to represent your counters. No maps or sorting are needed.
EDIT: added additional pass to determine maximum color, so no run-time resize is needed.
Here is the code:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int grid[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, /*...*/};
const size_t gridSize = std::end(grid) - std::begin(grid);
int maxColor = *std::max_element(std::begin(grid), std::end(grid));
std::vector<std::vector<int>> colorPos(maxColor);
for (size_t i = 0; i < gridSize; ++i)
colorPos[grid[i] - 1].push_back(i);
for (size_t i = 0; i < colorPos.size(); ++i) {
std::cout << (i + 1) << ": ";
for (int p : colorPos[i])
std::cout << p << ' ';
std::cout << std::endl;
}
return 0;
}
The output:
1: 0 1 8 9 10 17
2: 2 3 4 5 6 7 14 15 22 30
3: 11 12 13 19 20 28
4: 16 24 32 33 40 48 56
5: 18 25 26 27 34 35 36 44
6: 21 23 29 31 37 38 39
7: 41 42 49 50 57 58 59 60
8: 43 45 46 47 51 52 53 54 55 61 62 63
I think you'd be best off using a counting sort, which is a sorting algorithm that works very well for sorting large groups of simple types with many duplicate values in better than O(n log n) time. Here's some sample code, annotated for clarity:
// set up our grid
int grid_raw[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3, 2, 2, 4, 1, 5, 3, 3, 6, 2, 6, 4, 5, 5, 5, 3, 6, 2, 6, 4, 4, 5, 5, 5, 6, 6, 6, 4, 7, 7, 8, 5, 8, 8, 8, 4, 7, 7, 8, 8, 8, 8, 8, 4, 7, 7, 7, 7, 8, 8, 8};
// build a vector using our raw list of numbers. This calls the range constructor:
// (number 3) http://www.cplusplus.com/reference/vector/vector/vector/
// The trick to using sizeof is that I don't have to change anything if my grid's
// size changes (sizeof grid_raw gives the number of bytes in the whole array, and
// sizeof *grid_raw gives the number of bytes in one element, so dividing yields
// the number of elements.
std::vector<int> grid(grid_raw, grid_raw + sizeof grid_raw / sizeof *grid_raw);
// count the number of each color. std::map is an associative, key --> value
// container that's good for doing this even if you don't know how many colors
// you have, or what the possible values are. Think of the values in grid as being
// colors, not numbers, i.e. ++buckets[RED], ++buckets[GREEN], etc...
// if no bucket exists for a particular color yet, then it starts at zero (i.e,
// the first access of buckets[MAUVE] will be 0, but it remembers each increment)
std::map<int, int> buckets;
for (vector<int>::iterator i = grid.begin(); i != grid.end(); ++i)
++buckets[*i];
// build a new sorted vector from buckets, which now contains a count of the number
// of occurrences of each color. The list will be built in the order of elements
// in buckets, which will default to the numerical order of the colors (but can
// be customized if desired).
vector<int> sorted;
for (map<int, int>::iterator b = buckets.begin(); b != buckets.end(); ++b)
sorted.insert(sorted.end(), b->second, b->first);
// at this point, sorted = {1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, ...}
Read more about the Counting Sort (includes example python code)
Here's an ideone that demonstrates sorting your grid.
I'm not 100% sure this answers your question... but you included sorting in the title, even though you didn't say anything about it in the body of your question.
Maybe it would be better to use some associative container as for example std::unordered_map or std::multimap.
Here is a demonstrative program
#include <iostream>
#include <map>
int main()
{
int grid[] =
{
1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3, 2, 2,
4, 1, 5, 3, 3, 6, 2, 6, 4, 5, 5, 5, 3, 6, 2, 6,
4, 4, 5, 5, 5, 6, 6, 6, 4, 7, 7, 8, 5, 8, 8, 8,
4, 7, 7, 8, 8, 8, 8, 8, 4, 7, 7, 7, 7, 8, 8, 8
};
std::multimap<int, int> m;
int i = 0;
for ( int x : grid )
{
m.insert( { x, i++ } );
}
std::multimap<int, int>::size_type n = m.count( 1 );
std::cout << "There are " << n << " elements of color 1:";
auto p = m.equal_range( 1 );
for ( ; p.first != p.second ; ++p.first )
{
std::cout << ' ' << p.first->second;
}
std::cout << std::endl;
return 0;
}
The output
There are 6 elements of color 1: 0 1 8 9 10 17
Or
#include <iostream>
#include <map>
int main()
{
int grid[] =
{
1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 3, 3, 2, 2,
4, 1, 5, 3, 3, 6, 2, 6, 4, 5, 5, 5, 3, 6, 2, 6,
4, 4, 5, 5, 5, 6, 6, 6, 4, 7, 7, 8, 5, 8, 8, 8,
4, 7, 7, 8, 8, 8, 8, 8, 4, 7, 7, 7, 7, 8, 8, 8
};
std::multimap<int, int> m;
int i = 0;
for ( int x : grid )
{
m.insert( { x, i++ } );
}
for ( auto first = m.begin(); first != m.end(); )
{
auto n = m.count( first->first );
std::cout << "There are " << n
<< " elements of color " << first->first << ":";
auto p = m.equal_range( first->first );
for ( ; p.first != p.second ; ++p.first )
{
std::cout << ' ' << p.first->second;
}
std::cout << std::endl;
first = p.first;
}
return 0;
}
the output is
There are 6 elements of color 1: 0 1 8 9 10 17
There are 10 elements of color 2: 2 3 4 5 6 7 14 15 22 30
There are 6 elements of color 3: 11 12 13 19 20 28
There are 7 elements of color 4: 16 24 32 33 40 48 56
There are 8 elements of color 5: 18 25 26 27 34 35 36 44
There are 7 elements of color 6: 21 23 29 31 37 38 39
There are 8 elements of color 7: 41 42 49 50 57 58 59 60
There are 12 elements of color 8: 43 45 46 47 51 52 53 54 55 61 62 63
If you are not forced to use plain arrays, I can propose a map of colors to a vector of positions:
the map is an associative container, that for any color key returns a reference
the referenced used here will be a vector (a kind of dynamic array) containing all the positions.
Your input grid contains color codes:
typedef int colorcode; // For readability, to make diff between counts, offsets, and colorcodes
colorcode grid[] = { 1, 1, /* .....input data as above.... */ ,8 };
const size_t gridsize = sizeof(grid) / sizeof(int);
You would then define the color map:
map<colorcode, vector<int>> colormap;
// ^^^ key ^^^ value maintained for the key
With this approach, your color1[..] would then be replaced by a more dynamic corlormap[1][..]. And it's very easy to fill:
for (int i = 0; i < gridsize; i++)
colormap[grid[i]].push_back(i); // add the new position to the vector returned for the colormap of the color
To verify the result, you may iterate through the map, and for each existing value iterate through the positions:
for (auto x : colormap) { // for each color in the map
cout << "Color" << x.first << " : "; // display the color (key)
for (auto y : x.second) // and iterate through the vector of position
cout << y << " ";
cout << endl;
}
You don't know for sure how many different color codes you have, but you want to store for accodes