簡體   English   中英

如何用STL mimax算法替換我的'for'循環來找到min / max

[英]How to replace my 'for' loop to find min/max by STL mimax algorithm

我必須從a中找到最小值/最大值(min x,min y,max x,max 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被調用兩次,執行時間是兩次。 是否可以通過一次調用minmax算法來優化它?

minmax_elementPoint對象上運行比較並返回Point對象。

xy值是獨立的, 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)
}

不可以通過單次調用minmax_element來優化它,因為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方法與循環方法的范圍進行比較,我們可以考慮兩個方面:

  1. 可讀性。 accumulate方法略微更好地表達了從幾個點收集單個邊界框的意圖。 但它導致代碼略長。
  2. 性能。 對於這兩種方法,gcc(5.3和6)生成幾乎相同的代碼。 Clang 3.8可以矢量化循環范圍但不能用於accumulate 從C ++ 17開始,我們將使parallelizm TS標准化。 accumulate並行對應物將是reduce算法,因此accumulate/reduce方法將允許更多的靈活性。

結論:范圍和accumulate/reduce都有一些(dis)優勢。 但是可能一個完全不同的方法是最好的方法:如果OP中的cv::Point意味着你使用openCV庫,那么同一個庫就有了boundingRect函數,它正是你想要實現的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM