4

から最小/最大値(最小x、最小y、最大x、最大y)を見つける必要があります

vector<cv::Point>

ここに私のコード:

vector<cv::Point> contour;

...

Min = Point(640, 480) ;
Max = Point(0,0) ;
for (int j=0; j<(int)contour.size(); j++)
{
    if (contour[j].x < Min.x) Min.x = contour[j].x ;
    if (contour[j].y < Min.y) Min.y = contour[j].y ;
    if (contour[j].x > Max.x) Max.x = contour[j].x ;
    if (contour[j].y > Max.y) Max.y = contour[j].y ;
}

これはうまくいきます。mimmax STL を使用してバージョンを開発しました。

auto XminXmax = minmax_element(contour.begin(), contour.end(), [](Point p1,Point p2) {return p1.x < p2.x; });
auto YminYmax = minmax_element(contour.begin(), contour.end(), [](Point p1,Point p2) {return p1.y < p2.y; });
Point Min = Point((*XminXmax.first).x, (*YminYmax.first).y );
Point Max = Point((*XminXmax.second).x, (*YminYmax.second).y );

これも問題なく動作し、同じ結果が得られます。ただし、アルゴリズム minmax が 2 回呼び出されるため、実行時間は 2 倍になります。minmax algo への 1 回の呼び出しでこれを最適化することは可能ですか?

4

2 に答える 2

6

minmax_elementオブジェクトの比較を実行し、Pointオブジェクトを返しPointます。

xとのy値は独立しており、とが異なるオブジェクトに属する可能性がmin(x)あります。min(y)

for rangeこの特定のケースに使用します。

Min = Point(640, 480) ;
Max = Point(0,0) ;
for (auto &p : contour)
{
    Min.x = std::min(p.x, Min.x)
    Min.y = std::min(p.y, Min.y)
    Max.x = std::max(p.x, Max.x)
    Max.y = std::max(p.y, Max.y)
}
于 2016-03-11T11:21:51.257 に答える
1

いいえ、この問題の最適な解決策ではないminmax_elementため、 への 1 回の呼び出しでこれを最適化することはできません。minmax_element

いくつかの STL アルゴリズムを主張する場合は、次を使用しますaccumulate

std::accumulate(begin(contour), end(contour), Bound{}, [](Bound acc, Point p)
{
    return Bound{minpos(acc.bottomleft, p), maxpos(acc.topright, p)};
});

ただし、これにはいくつかの準備が必要です。

#include <numeric>

struct Point
{
    int x;
    int y;

    Point(int x, int y)
        : x(x), y(y) {}
};

Point minpos(Point a, Point b)
{
    return {std::min(a.x, b.x), std::min(a.y, b.y)};
}

Point maxpos(Point a, Point b)
{
    return {std::max(a.x, b.x), std::max(a.y, b.y)};
}

struct Bound
{
    Point bottomleft;
    Point topright;

    Bound(Point bl = {640, 480}, Point tr = {0, 0})
        : bottomleft(bl), topright(tr) {}
};

accumulateアプローチと範囲 for ループ アプローチを比較すると、次の 2 つの側面を考慮することができます。

  1. 読みやすさ。accumulateアプローチは、いくつかのポイントから単一のバウンディング ボックスを収集する意図をわずかにうまく表現しています。ただし、コードが少し長くなります。
  2. パフォーマンス。どちらのアプローチでも、gcc (5.3 および 6) はほぼ同じコードを生成します。Clang 3.8 は、 for ループの範囲をベクトル化できますが、 for はできませんaccumulate。C++17 から、parallelizm TS が標準化されます。の並列対応物はaccumulateアルゴリズムreduceになるため、accumulate/reduceアプローチにより柔軟性が向上します。

結論:どちらも範囲内でありaccumulate/reduce、いくつかの(欠点)利点があります。しかし、おそらく完全に異なるアプローチが最善の方法cv::Pointです.OPでopenCVライブラリを使用することを意味する場合、同じライブラリには、実装しようとしているものを正確に実行するboundingRect関数があります。

于 2016-03-13T13:45:52.087 に答える