Make a function take a cv::Point2x

Hi, I have this function (just an example) :

void TranslateSimpleContour(std::vector<cv::Point> &contour, const int &shiftHorizontal, const int &shiftVertical) // translate simple contour along vertical and/or horizontal axis
{
    cv::Point t(shiftHorizontal, shiftVertical);
    for (int nb = 0; nb < int(contour.size()); nb++)
        contour[nb] += t;
}

How to make it take any cv::Point format like cv::Point2i, cv::Point2f or cv::Point2d in the std::vector ? A “universal” cv::Point2x version of this function…

do not declare a parameter to be a reference if you don’t intend to change it.

const references are a contradiction in terms.

you need to learn about templates then.

I thought maybe there was a universal cv::Point type I could use, but couldn’t find.
OK I’ll use a template.

Use the cv::Point_<T> template. Note the trailing underscore after Point, this is part of the name of that class template.

Link to documentation: OpenCV: cv::Point_< _Tp > Class Template Reference

re my remarks on “const references”: I should have qualified that w.r.t. those int parameters. in other contexts, const references do make sense, not there.

1 Like

you can define a temporary cv::Mat variable and add or subtract shifting values
take a look

#include <iostream>
#include <opencv2/core.hpp>

void TranslateSimpleContour(cv::Mat &contour, const int &shiftHorizontal, const int &shiftVertical) // translate simple contour along vertical and/or horizontal axis
{
    cv::Scalar t(shiftHorizontal, shiftVertical);
    contour = contour + t;
}

// generated by ChatGPT
template <typename PointType>
void TranslateSimpleContour(std::vector<PointType>& contour, typename PointType::value_type shiftHorizontal, typename PointType::value_type shiftVertical)
{
    PointType translation(shiftHorizontal, shiftVertical);
    for (auto& point : contour)
    {
        point += translation;
    }
}

int main(int , const char** )
{
    std::vector<cv::Point> contour2i = { {168, 212}, {92, 192}, {131, 109}, {213, 100} };
    std::vector<cv::Point2f> contour2f = { {16.8f, 21.2f}, {9.2f, 19.2f}, {13.1f, 10.9f}, {21.3f, 10.0f} };
    std::vector<cv::Point2d> contour2d = { {16.8, 2.12}, {9.2, 1.92}, {1.31, 1.09}, {2.13, 10.0} };

    std::cout << contour2i << std::endl;
    cv::Mat tmp = cv::Mat(contour2i);
    TranslateSimpleContour(tmp, 1, 2);
    std::cout << contour2i<< std::endl;

    std::cout << contour2f << std::endl;
    tmp = cv::Mat(contour2f);
    TranslateSimpleContour(tmp, 1, 2);
    std::cout << contour2f<< std::endl;
    std::cout << "---------------------------------" << std::endl;
    //-------------------------------------------
    std::cout << contour2i << std::endl;
    TranslateSimpleContour(contour2i, 1, 2);
    std::cout << contour2i<< std::endl;

    std::cout << contour2f << std::endl;
    TranslateSimpleContour(contour2f, 1, 2);
    std::cout << contour2f<< std::endl;

    std::cout << "---------------------------------" << std::endl;
    //-------------------------------------------
    std::cout << contour2f << std::endl;
    tmp = cv::Mat(contour2f);
    tmp = tmp + cv::Scalar(1.6, 2.6);
    std::cout << contour2f<< std::endl;

    std::cout << contour2d << std::endl;
    tmp = cv::Mat(contour2d);
    tmp = tmp + cv::Scalar(1.6, 2.6);
    std::cout << contour2d<< std::endl;
    return 0;
}

The aim is not to multiply the functions or putting “ifs” in them to care about each type of value. cv::Point_<T> can’t be used for variables in functions, I think it was the first thing I tried.

That looks nice, but it requires a copy of the data each time, not very optimized. I could work with cv::Mats instead of vectors of points though. I’ll try it!

sure you can. “template function”. please look it up.

I think, in addition to learning C++ templates as others have suggested, it would be beneficial if you learn how to read the compiled machine code. By doing so, you will understand that, in C++, each type of Point_ (e.g. Point2i, Point2f, etc) requires different machine code to handle.

Thanks to you all for all these insights.

Since I asked this question I have successfully learned about templates, applied the concept to what I wanted to do, with success. I had a hard time finding the right way to declare in the functions body the other associated variables corresponding to the type of the template (cv::Rect for example), etc.

I’m a fast learner, it’s just that the docs of OpenCV and C++ are difficult to read and understand if you are not accustomed to that kind of litterature. And OpenCV’s doc is sometimes too “light”.

Ah, one last thing : how do I indicate my question was solved ?

but it requires a copy of the data each time

no. Mat uses existing data without copying.

before closing it will be better sharing your final choice (solution).

Here is the code of the final solution :

template <typename Point2x>
void TranslateSimpleContour(std::vector<Point2x> &contour, const typename Point2x::value_type &shiftHorizontal, const typename Point2x::value_type &shiftVertical)
{
    static_assert(std::is_base_of<cv::Point_<typename Point2x::value_type>, Point2x>::value, "Point2x must be a cv::Point_ type");

    Point2x t(shiftHorizontal, shiftVertical);
    for (size_t nb = 0; nb < contour.size(); nb++)
        contour[nb] += t;
}

So I do I close this question ?

that is not a thing on this forum. this is different from Stack Overflow.