Finding extreme points in contours with OpenCV C++ - c++

I have tried to implement this code, but I have a trouble when I want to determine the most extreme point of the contour follow this tutorial.
# determine the most extreme points along the contour
extLeft = tuple(c[c[:, :, 0].argmin()][0])
extRight = tuple(c[c[:, :, 0].argmax()][0])
extTop = tuple(c[c[:, :, 1].argmin()][0])
extBot = tuple(c[c[:, :, 1].argmax()][0])
Can anyone help me to solve this problem?

Starting from a std::vector<cv::Point>, you can use std::max_element and std::min_element with an appropriate comparator, that works on x coordinates to find left and right points, and works on y coordinates to find top and bottom points:
// Your points
vector<Point> pts;
...
Point extLeft = *min_element(pts.begin(), pts.end(),
[](const Point& lhs, const Point& rhs) {
return lhs.x < rhs.x;
});
Point extRight = *max_element(pts.begin(), pts.end(),
[](const Point& lhs, const Point& rhs) {
return lhs.x < rhs.x;
});
Point extTop = *min_element(pts.begin(), pts.end(),
[](const Point& lhs, const Point& rhs) {
return lhs.y < rhs.y;
});
Point extBot = *max_element(pts.begin(), pts.end(),
[](const Point& lhs, const Point& rhs) {
return lhs.y < rhs.y;
});

Related

Overloading operator *

I have a vector3 class which i need to implement different multiplication options ( so i overloaded the operator *) depending of the types that im multiplying.
The problem is that in the last one i get the error:
Description Resource Path Location Type
ambiguating new declaration of 'Pang::vector3 Pang::operator*(const Pang::vector3&, const Pang::vector3&)' vector3.h /PangGame/src line 130
C/C++ Problem
But i have only one operator overloaded that returns vector and muyltiplies two vectors.
Hope you can help ( just to clarify the class vector 3 has threee double numbers ) ex: vector3(double x, double y, double z); )
friend vector3 operator* (const double& number, const vector3& vector)
{
vector3 result;
result.x = number*vector.x;
result.y = number*vector.y;
result.z = number*vector.z;
return result;
}
friend vector3 operator* (const vector3& vector, const double& number)
{
vector3 result;
result.x = number*vector.x;
result.y = number*vector.y;
result.z = number*vector.z;
return result;
}
//Scalar product: If a = a1i + a2j + a3k and b = b1i + b2j + b3k then
// a · b = a1*b1 + a2*b2 + a3*b3
friend double operator* (const vector3& vector1, const vector3& vector2)
{
double result;
result= (vector1.x)*(vector2.x)+(vector1.y)*(vector2.y) + (vector1.z)*(vector2.z);
return result;
}
/* Product: Vector x Vector
* Example: The cross product of a = (2,3,4) and b = (5,6,7)
cx = aybz - azby = 3×7 - 4×6 = -3
cy = azbx - axbz = 4×5 - 2×7 = 6
cz = axby - aybx = 2×6 - 3×5 = -3
Answer: a × b = (-3,6,-3)*/
friend vector3 operator* (const vector3& vector,const vector3& vector2)
{
vector3 result;
result.x = (vector.y)*(vector2.z) - (vector.z)*(vector2.y);
result.y = (vector.z)*(vector2.x) - (vector.x)*(vector2.z);
result.z = (vector.x)*(vector2.y) - (vector.y)*(vector2.x);
return result;
}
The problem is that you are trying to overload operator* based on the return type:
double operator* (const vector3& vector1, const vector3& vector2)
vector3 operator* (const vector3& vector1, const vector3& vector2)
This is not allowed because overload resolution takes into account the function signature, which does not include the return type:
3.19 signature [defns.signature]
⟨function⟩ name, parameter-type-list, and enclosing namespace (if any)
One possible solution, if you do want your operator* to possibly yield either a double or another vector3, you can return a proxy type that is convertible to these types:
struct vector3_multiplication_proxy {
vector3 lhs, rhs;
operator double() { return 0; /* Your inner product calculation here */ }
operator vector3() { return {}; /* Your cross product calculation here */ }
};
vector3_multiplication_proxy operator* (const vector3& lhs, const vector3& rhs) {
return {lhs, rhs};
}
This does have lifetime pitfalls and may delay calculation depending on how you use it, so it may or may not be a good idea. In your particular case, it's probably a bad idea, because the inner and cross products are different things and should probably be denoted by different syntax.

C++ Member Function Cannot Change Private Field [duplicate]

This question already has an answer here:
About c++11 range for loops and iterators
(1 answer)
Closed 7 years ago.
OH! I found the problem. As I said at end, it was a simple problem.
In for loop, i iterated wiht copy of "Particle"s. I updated them but the operation does not affect the original values that stored in vector.
For requests about solution one can access the particle objects using 3 major ways.
lvalue-ref object way:
for (auto& p: particles)
...
Or by iterators:
for (auto it=particles.begin(); i<particles.end();++it)
...
Or by plain indexes:
for (size_t i=0; i<particles.size(); ++i)
...
For ones that curious about code, you may look below:
If I am not missing something very obvious, I encountered with a really strange problem.
To simplify the problem, I have a class named "Particle", which has a function called "update". Particle class has some private variables like position, velocity etc. And update function is supposed to make some calculations and add proper values to that private variables. But, that simply does not work.
Actually, I am sceptical about the type of that variables which is a class written by me, "Vector2".
To add values to variables, I've used the "+=" operator, and I think I implemented them correctly(?) in my Vector2 class.
To clarify situation, IMHO, it is better to give some code:
This is my Vector2.h :
namespace sim {
#include <ostream>
#include <cmath>
using namespace std;
struct Vector2 {
double x, y;
Vector2& operator+=(const Vector2& rhs) {
this->x += rhs.x;
this->y += rhs.y;
cout << "op+=" << endl;
return *this;
}
Vector2& operator*=(double k) {
x *= k;
y *= k;
cout << "op*=" << endl;
return *this;
}
friend ostream& operator<<(ostream& os, const Vector2& v2);
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 rhs);
};
ostream& operator<<(ostream& os, const Vector2& v2) {
os << "[ " << v2.x << "; " << v2.y << " ]";
return os;
}
Vector2 operator+(Vector2 lhs, const Vector2& rhs) {
lhs += rhs;
cout << "op+" << endl;
return lhs;
}
Vector2 operator*(Vector2 lhs, double k) {
lhs *= k;
cout << "op*" << endl;
return lhs;
}
(removed some unrelated parts like constructor)
And this is Particle class:
class Particle {
private:
Vector2 pos;
Vector2 vel;
Vector2 acc;
double rad;
SDL_Color clr;
public:
Particle(
Vector2 _p,
Vector2 _v,
Vector2 _a,
double _r = 10.0,
SDL_Color _c = { 255, 255, 255, 255 }) {
pos = _p;
vel = _v;
acc = _a;
rad = _r;
clr = _c;
}
Vector2& move_particle(Vector2 move_by) {
return (pos += move_by);
}
void update(double dt) {
this->vel += acc * dt;
this->pos += vel * dt;
cout << "update " << pos << vel << acc << endl;
}
void render(SDL_Renderer* renderer) {
// TODO: this was supposed to be a circle, but, who cares? ;)
SDL_Rect r = { int(pos.x), int(pos.y), int(rad), int(rad) };
SDL_RenderFillRect(renderer, &r);
cout << "render" << endl;
}
};
And the result: update does not update.
How do I know (guess) my overloads DOES work?
For 3 Vector2 objects, I can do any kind of operation I defined correctly.
And the results are just what they supposed to be. (Or, maybe not?)
But debugging update function roughly brings me to the point that actually += operator works for one time, and not again BUT this behaviour is showing itself only in update function.
And I know, this will be such a simple mistake that I possibly feel ashamed (just kidding).
Oh, and the main code of course:
int main() {
SDL_Init(SDL_INIT_EVERYTHING);
auto window = SDL_CreateWindow("My Very First Particle Simulation", -1, -1,
1024, 768, SDL_WINDOW_SHOWN);
auto renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
const Vector2 g(0.0, 9.8);
double dt = 0.1;
std::vector<Particle> particles;
bool quit = false;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
quit = true;
break;
case SDL_MOUSEBUTTONUP:
particles.emplace_back(Vector2(event.button.x, event.button.y), Vector2(1.0, 0.0), g);
break;
default:
break;
}
SDL_RenderClear(renderer);
for (auto p : particles) {
p.update(dt);
p.render(renderer);
}
SDL_RenderPresent(renderer);
}
}
}
Some comments on your code,
you can just change these to be member functions
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 lhs);
as in
Vector2 operator+(const Vector2& rhs);
Vector2 operator-(const Vector2& rhs);
Vector2 operator*(const double k);
friend Vector2 operator*(const double k, Vector2 lhs);
In them copy this to a new Vector2 and then update the value and return. The fourth function is kept as friend so that you can have something like double*Vector2 while the third one takes care of Vector2*double
Any operation that has Vector2 as the left operand can be done as a member function.
I can see that these two operators are taking their first args by value. Change them so the take their args by reference.
Vector2 operator+(Vector2 lhs, const Vector2& rhs) { // lhs should be a const reference
lhs += rhs;
cout << "op+" << endl;
return lhs;
}
Vector2 operator*(Vector2 lhs, double k) { // lhs should be a const reference
lhs *= k;
cout << "op*" << endl;
return lhs;
}
EDIT:
Also these functions should take their class args as const referenecs:
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 rhs);

What is the best way to search/find a point in a vector of points?

I tried to sort the points based on their x coordinates and do a binary search on the vector but I cannot find the points that I know they exist.
Thanks for your help.
struct PointSort {
bool operator() (cv::Point pt1, cv::Point pt2) { return (pt1.x < pt2.x);}
} mySort;
.
.
.
std::sort (temp.begin(), temp.end(), mySort);
if (std::binary_search(temp.begin(), temp.end(), somePoint, mySort)){
doSomething();
}
So something like:
struct point { int x, y; };
std::vector<point> pts { {1,2}, {4,5} };
auto comp_x=[](const point& p1, const point& p2) {
return p1.x < p2.x;
};
std::sort(begin(pts), end(pts), comp_x);
//using binary search
auto it=std::lower_bound(begin(pts), end(pts), some_point, comp_x);
//it now points to the point
The lower bound function uses a binary search to find the first element (upper_bound finds the last) and gives you an iterator to that element.
If you don't need it to be sorted, I would just use std::find.
auto it=std::find_if(begin(pts), end(pts), [&](const point& p) {
return p.x==some_point.x;
}
);
If you just want to find a Point that matches the one you are supplying:
std::vector<Point> points;
// points is filled somewhere
Point p { 1, 2 };
std::vector<Point>::iterator it = std::find(points.begin(), points.end(), p);
If you wanted to customize the comparison, you can use std::find_if:
Point pt { 1, 2 };
std::vector<Point>::iterator it = std::find_if(points.begin(), points.end(), [&](const Point& p)
{
return pt.x == p.x;
});
And for God's sake, ignore the "AAA" nonsense ...
Side note: your vector does not need to be sorted to use std::find (though it will speed it up if it is). And if you can use the C++11 standard, you do not need to create a functor:
std::sort(temp.begin(), temp.end(), [](const Point& p1, const Point& p2)
{
return p1.x < p2.x;
});
Additionally, if the elements of your Point class are floating point numbers, you will not want to use straight equality for comparisons. Instead, pick some small number as your lowest acceptable precision (epsilon), and compare the difference between 2 values to it:
float x = SOME_VALUE;
float y = SOME_OTHER_VALUE;
float EPSILON = 0.000000001;
bool are_equal = std::abs(x - y) < EPSILON;

Check if point is inside vector

I want to check if a given point with x and yvalue is inside a vector of points:
bool inside_vector(int x, int y, vector<Point2i>& points)
{
for(vector<Point2i>::const_iterator it = points.begin();
it != points.end();
++it)
{
if(it->x == y && it->y == y)
{
return true;
}
}
return false;
}
Are there other approaches without the for loop?
You can use std::find or std::find_if with suitable functor to avoid writing your own loop. But you don't gain in terms of complexity: it is still O(n). For example,
bool operator==(const Point2i& lhs, const Point2i& rhs)
{
return lhs.x == rhs.x && lhs.y == rhs.y;
}
Point2Di somePoint = Point2Di(x,y); // point to find
auto it = std::find(points.begin(), points.end(), somePoint);
or, without the equality operator,
auto it = std::find_if(points.begin(),
points.end(), [&somePoint](const Point2Di& p)
{return somePoint.x == p.x && somePoint.y == p.y;});
Assumming you have an operator== defined for your Point2i structure, you can use std::find(), like this:
std::vector<Point2i>::const_iterator findIt = std::find(
points.begin(),
points.end(),
Point2i(x, y));
I also assume you have a Point2i constructor that takes the two coordinates.

add a non-comparable object to a set

i have a class named Point (in an external library, i can't modify the code) that is used to represent a point in a 3d space:
int x = 0; int y = 0; int z = 0;
Point my_point p(x,y,z);
It overloads the == and != operators but not < or > ones. I need to store them in an efficient way (no double element, no repetition). I thought my data structure is set, but if i try to use, i get this error:
error: no match for ‘operator<’ in ‘__x < __y’
some advice?
Write a comparison operator, and instantiate the set with that:
struct ComparePoints
{
bool operator()( Point const& lhs, Point const& rhs ) const
{
if ( lhs.x != rhs.x ) {
return lhs.x < rhs.x;
} else if ( lhs.y != rhs.y ) {
return lhs.y < rhs.y;
} else {
return lhs.z < rhs.z;
}
}
};
std::set <Point, ComparePoints> mySet;
You can define a comparison functor and pass it as second template argument to std::set. See here, look at Compare. You can also define bool operator<(const Point& lhs, const Point& rhs), but if you cannot touch the class, this requires that the comparison can be implemented via the public interface of Point.
You can define operator < yourself. It doesn't have to be inside the Point class if x, y and z are available from Point's public interface.
bool operator<(const Point& lhs, const Point& rhs)
{
if( lhs.x != rhs.x ) return lhs.x < rhs.x;
if( lhs.y != rhs.y ) return lhs.y < rhs.y;
return lhs.z < rhs.z;
}