How To Use Vector Points in C++ OpenCv? - c++

Could you guys Please help me in providing good notes or links ?
For Ex : I need to create a vector and dump these x,y values in Vector ..
Data { X , Y } = {1,1} , {1,2} , {1,3}, {2,1},{2,2},{2,3},{3,1},{3,2},{3,3}

A vector of point in OpenCV is just a standard C++ STL vector containing OpenCV Point objects :
std::vector<Point> data;
data.push_back(Point(1,1));
data.push_back(Point(1,2));
data.push_back(Point(1,3));
data.push_back(Point(2,1));
...
Alternatively, if you're using C++11 or later you can use a list initialization:
std::vector<Point> data = {Point(1,1), Point(1,2), Point(1,3), Point(2,1)};
Take a look at the C++ reference for STL Vector

So... you want to use a vector to store data... wherein each element is a pair of ints? Well, if you don't want to create your own type, use a tuple or pair:
#include <vector>
#include <utility>
// ...
std::vector<std::pair<int, int> v;
// ...
v.push_back(std::make_pair(1, 1));
// ...
auto p = c[offset];
int x = p.first;
int y = p.second;

Related

Is there a way to slice the structure vector in c++?

I have an data named faces which definition is like this:
struct ivec3 {
unsigned int v0;
unsigned int v1;
unsigned int v2;
};
std::vector<ivec3> faces;
I got the faces with 100 elements(faces.size()=100).
Now I want to get all v0 of faces. If I use the Python, I can do it like this
all_v0 = faces[:, 0]
So, how can I use the slicing operation in C++ like above code of Python?
Thanks very much!
You can do this with the help of std::transform:
std::vector<int> all_v0;
all_v0.reserve(faces.size());
std::transform(faces.begin(), faces.end(),
std::back_inserter(all_v0),
[] (const ivec3& i) { return i.v0; });
There is no "slicing operation" for vectors in C++.
But this can be done with a simple loop. Or, without writing the loop yourself by using a standard algorithm such as std::transform.
Consider whether you actually need a new container that has the "slices", or whether you would perhaps be content with having a range that can access those elements. This is analogous to using generator objects instead of creating the list in Python. Example:
auto get_v0 = [](const auto& v) -> auto {
return v.v0;
};
auto v0_range = std::ranges::transform_view(
faces,
get_v0
);
// access the objects:
for (auto v0 : v0_range) {
// use v0
}
// or if you do need a container:
std::vector v0s(begin(v0_range), end(v0_range));
Instead of the function, you can also use a member pointer as demonstrated in 康桓瑋's answer
You can pass in the corresponding member object pointer to C++20 views::transform to do this.
#include <ranges>
#include <vector>
struct ivec3 {
unsigned int v0;
unsigned int v1;
unsigned int v2;
};
int main() {
std::vector<ivec3> faces;
auto v0s = faces | std::views::transform(&ivec3::v0);
auto v1s = faces | std::views::transform(&ivec3::v1);
auto v2s = faces | std::views::transform(&ivec3::v2);
}

How to Sort Vector of Points Based on a Y-Axis?

I have a group of coordinates for example :
10,40; 9,27; 5,68; 7,55; 8,15;
How do I sort those coordinates without losing the correct X-Axis of the sorted Y-Axis.
From the example above I want to sort the coordinates so the correct output will be:
8,15; 9,27; 10,40; 7,55; 5,68.
Any suggestion will be greatly appreciated.
Thank you.
Documentation for std::sort
#include "opencv2/core/core.hpp"
#include <algorithm> // std::sort
// This defines a binary predicate that,
// taking two values of the same type of those
// contained in the list, returns true if the first
// argument goes before the second argument
struct myclass {
bool operator() (cv::Point pt1, cv::Point pt2) { return (pt1.y < pt2.y);}
} myobject;
int main () {
// input data
std::vector<cv::Point> pts(5);
pts[0] = Point(10,40);
pts[1] = Point(9,27);
pts[2] = Point(5,68);
pts[3] = Point(7,55);
pts[4] = Point(8,15);
// sort vector using myobject as comparator
std::sort(pts.begin(), pts.end(), myobject);
}
You need to specify how exactly you are storing your group of coordinates.
The easiest way is to store them as a new struct you create and apply a basic bubble sort algorithm over the top of it, using the Y value as your sort parameter. Then when you "swap" the position of the structs, the X & Y stay together.
struct Vector {
float x;
float y;
};
You could create a class that maps a coordinate, and if you are using STL as your Vector, you can use the sort method to sort your whole vector based on the Y coordinate.
Here and here are similar questions from stack.

C++ array inserting to a double vector

If I declare
vector< vector <double > > V;
how can I insert (3.0, 4.0) as the first element?
You can use std::make_pair to insert a pair of doubles into your vector:
std::vector<std::pair<double, double>> V;
V.push_back(std::make_pair(3.0, 4.0));
You cant add 2 values to that 2d vector, that 2d vector only store one value of type double in M x N positions.
what you can do is create a struct for example:
struct SPoint
{
double X;
double Y;
};
and then add the points like this:
vector< vector <SPoint > > v;
SPoint point = {3.0, 3.4};
v.push_back ( std::vector<SPoint >()
v[0].push_back(point);
hope it helps.
In C++03:
vector<vector<double>> V;
V.push_back(std::vector<double>(2));
V[0][0] = 3.0;
V[0][1] = 4.0;
In C++11:
vector<vector<double>> V;
V.emplace_back({3.0, 4.0});
If instead, it makes more sense to use a std::vector of std::pairs, you can do it like so:
std::vector<std::pair<double, double>> V;
V.push_back({3.0, 4.0});
Accessing an element of the pair will look like either V[0].first or V[1].second.
It isn't clear whether you want to insert an element into a pre-existing vector, or into a new, empty one. In either case, you can use the std::vector std::initializer_list constructor to initialize or assign as appropriate:
#include <vector>
int main()
{
std::vector<std::vector<double>> v1;
v1.push_back({3.0,4.0}); // push first element using initializer_list
std::vector<std::vector<double>> v2(10);
v2[0] = {3.0, 4.0}; // assign value to pre-existing vector
}

C++ Access an element of pair inside vector

I have a vector with each element being a pair. I am confused with the syntax. Can someone please tell me how to iterate over each vector and in turn each element of pair to access the class.
std::vector<std::pair<MyClass *, MyClass *>> VectorOfPairs;
Also, please note, I will be passing the values in between the function, hence VectorOfPairs with be passed by pointer that is *VectorOfPairs in some places of my code.
Appreciate your help. Thanks
This should work (assuming you have a C++11 compatible compiler)
for ( auto it = VectorOfPairs.begin(); it != VectorOfPairs.end(); it++ )
{
// To get hold of the class pointers:
auto pClass1 = it->first;
auto pClass2 = it->second;
}
If you don't have auto you'll have to use std::vector<std::pair<MyClass *, MyClass *>>::iterator instead.
Here is a sample. Note I'm using a typedef to alias that long, ugly typename:
typedef std::vector<std::pair<MyClass*, MyClass*> > MyClassPairs;
for( MyClassPairs::iterator it = VectorOfPairs.begin(); it != VectorOfPairs.end(); ++it )
{
MyClass* p_a = it->first;
MyClass* p_b = it->second;
}
Yet another option if you have a C++11 compliant compiler is using range based for loops
for( auto const& v : VectorOfPairs ) {
// v is a reference to a vector element
v.first->foo();
v.second->bar();
}
You can access the elements of pairs inside vector in C++17 in a following style by combining range-based for loop and structured bindings. Example:
for (auto& [x, y] : pts) {
cin >> x >> y;
}
where pts is a vector of pairs. & is used to make formal "uniquely-named variable" e of structured binding a reference so that x and y referring to subobjects of e refer to original pair inside pts, which can be modified this way (e.g. cin can be used to input to it). Without &, e would be a copy (to subobjects of which x and y again refer). Example using your VectorOfPairs:
for (auto [pFirst, pSecond] : VectorOfPairs ) {
// ...
}
Also you can make e a reference to const when modification through structured binding is not needed and you want to avoid potentially expensive copy of a pair (though this should not be a problem in your case since pair object consisting of 2 pointers is pretty small and cheap to copy). Example:
for (const auto& [pFirst, pSecond] : VectorOfPairs ) {
// ...
}

Is there an equivalent function in C/C++ to GNU-R which()?

Let me explain what the 'which' function does:
From GNU-R help:
which indices are TRUE?
Give the ‘TRUE’ indices of a logical object, allowing for array indices.
or showing some code: (GNU-R starts counting indices with 1)
> x <- c(1,2,3,1,3,5);
> which(x == 1);
[1] 1 4
> which(x == 3);
[1] 3 5
> ll <- c(TRUE,FALSE,TRUE,NA,FALSE,FALSE,TRUE);
> which(ll);
[1] 1 3 7
Does anyone know a similar function in C/C++?
Thanks for your help
rinni
You have to understand that R is vectorised, whereas C first and foremost works on individual atomistic data pieces: a single int, double, ...
With C++, you can look into STL algorithms with which you approach this.
Lastly, at the R and C++ intersection, our Rcpp package has some vectorized operations in C++ which mimic some operations; see the Rcpp-sugar pdf vignette for more (and/or some of our talks on Rcpp).
Create a functor object that you can initialize with the match value, and iterator over your list using std::for_each. So for example:
vector<int> values;
//fill your vector with values;
struct match_functor
{
vector<int> value_array;
int match_value;
match_functor(int value): match_value(value) {}
void operator() (int input_value)
{
if(match_value == input_value)
value_array.push_back(input_value);
}
};
match_functor matches(1);
std::for_each(values.begin(), values.end(), matches);
Now your result value array can be accessed using matches.value_array[INDEX].
As an alternative, if you simply want to have the indicies of the original vector, rather than the actual values, then you can do something like this for your functor object:
struct match_functor
{
vector<int> index_array;
int match_value;
int index;
match_functor(int value): match_value(value), index(0) {}
void operator() (int input_value)
{
if(match_value == input_value)
index_array.push_back(index);
index++;
}
};
match_functor matches(1);
matches = std::for_each(values.begin(), values.end(), matches);
Now matches.index_array[INDEX] will hold the indicies of the orignal vector that match the value 1, and not the actual values from the original vector.
the algorithm std::find_if should do the trick - in conjunction with a loop I should add.