Merge remote-tracking branch 'upstream/3.4' into merge-3.4
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 2 Oct 2020 15:58:45 +0000 (15:58 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 2 Oct 2020 15:58:45 +0000 (15:58 +0000)
1  2 
modules/calib3d/src/fundam.cpp
modules/dnn/src/layers/resize_layer.cpp
modules/dnn/src/onnx/onnx_importer.cpp
modules/highgui/src/window_w32.cpp
modules/imgproc/include/opencv2/imgproc/detail/gcgraph.hpp

Simple merge
Simple merge
index db2ea0f,0000000..f17c6e7
mode 100644,000000..100644
--- /dev/null
@@@ -1,393 -1,0 +1,395 @@@
 +/*M///////////////////////////////////////////////////////////////////////////////////////
 +//
 +//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 +//
 +//  By downloading, copying, installing or using the software you agree to this license.
 +//  If you do not agree to this license, do not download, install,
 +//  copy or use the software.
 +//
 +//
 +//                        Intel License Agreement
 +//                For Open Source Computer Vision Library
 +//
 +// Copyright (C) 2000, Intel Corporation, all rights reserved.
 +// Third party copyrights are property of their respective owners.
 +//
 +// Redistribution and use in source and binary forms, with or without modification,
 +// are permitted provided that the following conditions are met:
 +//
 +//   * Redistribution's of source code must retain the above copyright notice,
 +//     this list of conditions and the following disclaimer.
 +//
 +//   * Redistribution's in binary form must reproduce the above copyright notice,
 +//     this list of conditions and the following disclaimer in the documentation
 +//     and/or other materials provided with the distribution.
 +//
 +//   * The name of Intel Corporation may not be used to endorse or promote products
 +//     derived from this software without specific prior written permission.
 +//
 +// This software is provided by the copyright holders and contributors "as is" and
 +// any express or implied warranties, including, but not limited to, the implied
 +// warranties of merchantability and fitness for a particular purpose are disclaimed.
 +// In no event shall the Intel Corporation or contributors be liable for any direct,
 +// indirect, incidental, special, exemplary, or consequential damages
 +// (including, but not limited to, procurement of substitute goods or services;
 +// loss of use, data, or profits; or business interruption) however caused
 +// and on any theory of liability, whether in contract, strict liability,
 +// or tort (including negligence or otherwise) arising in any way out of
 +// the use of this software, even if advised of the possibility of such damage.
 +//
 +//M*/
 +
 +#ifndef OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP
 +#define OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP
 +
 +//! @cond IGNORED
 +
 +namespace cv { namespace detail {
 +template <class TWeight> class GCGraph
 +{
 +public:
 +    GCGraph();
 +    GCGraph( unsigned int vtxCount, unsigned int edgeCount );
 +    ~GCGraph();
 +    void create( unsigned int vtxCount, unsigned int edgeCount );
 +    int addVtx();
 +    void addEdges( int i, int j, TWeight w, TWeight revw );
 +    void addTermWeights( int i, TWeight sourceW, TWeight sinkW );
 +    TWeight maxFlow();
 +    bool inSourceSegment( int i );
 +private:
 +    class Vtx
 +    {
 +    public:
 +        Vtx *next; // initialized and used in maxFlow() only
 +        int parent;
 +        int first;
 +        int ts;
 +        int dist;
 +        TWeight weight;
 +        uchar t;
 +    };
 +    class Edge
 +    {
 +    public:
 +        int dst;
 +        int next;
 +        TWeight weight;
 +    };
 +
 +    std::vector<Vtx> vtcs;
 +    std::vector<Edge> edges;
 +    TWeight flow;
 +};
 +
 +template <class TWeight>
 +GCGraph<TWeight>::GCGraph()
 +{
 +    flow = 0;
 +}
 +template <class TWeight>
 +GCGraph<TWeight>::GCGraph( unsigned int vtxCount, unsigned int edgeCount )
 +{
 +    create( vtxCount, edgeCount );
 +}
 +template <class TWeight>
 +GCGraph<TWeight>::~GCGraph()
 +{
 +}
 +template <class TWeight>
 +void GCGraph<TWeight>::create( unsigned int vtxCount, unsigned int edgeCount )
 +{
 +    vtcs.reserve( vtxCount );
 +    edges.reserve( edgeCount + 2 );
 +    flow = 0;
 +}
 +
 +template <class TWeight>
 +int GCGraph<TWeight>::addVtx()
 +{
 +    Vtx v;
 +    memset( &v, 0, sizeof(Vtx));
 +    vtcs.push_back(v);
 +    return (int)vtcs.size() - 1;
 +}
 +
 +template <class TWeight>
 +void GCGraph<TWeight>::addEdges( int i, int j, TWeight w, TWeight revw )
 +{
 +    CV_Assert( i>=0 && i<(int)vtcs.size() );
 +    CV_Assert( j>=0 && j<(int)vtcs.size() );
 +    CV_Assert( w>=0 && revw>=0 );
 +    CV_Assert( i != j );
 +
 +    if( !edges.size() )
 +        edges.resize( 2 );
 +
 +    Edge fromI, toI;
 +    fromI.dst = j;
 +    fromI.next = vtcs[i].first;
 +    fromI.weight = w;
 +    vtcs[i].first = (int)edges.size();
 +    edges.push_back( fromI );
 +
 +    toI.dst = i;
 +    toI.next = vtcs[j].first;
 +    toI.weight = revw;
 +    vtcs[j].first = (int)edges.size();
 +    edges.push_back( toI );
 +}
 +
 +template <class TWeight>
 +void GCGraph<TWeight>::addTermWeights( int i, TWeight sourceW, TWeight sinkW )
 +{
 +    CV_Assert( i>=0 && i<(int)vtcs.size() );
 +
 +    TWeight dw = vtcs[i].weight;
 +    if( dw > 0 )
 +        sourceW += dw;
 +    else
 +        sinkW -= dw;
 +    flow += (sourceW < sinkW) ? sourceW : sinkW;
 +    vtcs[i].weight = sourceW - sinkW;
 +}
 +
 +template <class TWeight>
 +TWeight GCGraph<TWeight>::maxFlow()
 +{
++    CV_Assert(!vtcs.empty());
++    CV_Assert(!edges.empty());
 +    const int TERMINAL = -1, ORPHAN = -2;
 +    Vtx stub, *nilNode = &stub, *first = nilNode, *last = nilNode;
 +    int curr_ts = 0;
 +    stub.next = nilNode;
 +    Vtx *vtxPtr = &vtcs[0];
 +    Edge *edgePtr = &edges[0];
 +
 +    std::vector<Vtx*> orphans;
 +
 +    // initialize the active queue and the graph vertices
 +    for( int i = 0; i < (int)vtcs.size(); i++ )
 +    {
 +        Vtx* v = vtxPtr + i;
 +        v->ts = 0;
 +        if( v->weight != 0 )
 +        {
 +            last = last->next = v;
 +            v->dist = 1;
 +            v->parent = TERMINAL;
 +            v->t = v->weight < 0;
 +        }
 +        else
 +            v->parent = 0;
 +    }
 +    first = first->next;
 +    last->next = nilNode;
 +    nilNode->next = 0;
 +
 +    // run the search-path -> augment-graph -> restore-trees loop
 +    for(;;)
 +    {
 +        Vtx* v, *u;
 +        int e0 = -1, ei = 0, ej = 0;
 +        TWeight minWeight, weight;
 +        uchar vt;
 +
 +        // grow S & T search trees, find an edge connecting them
 +        while( first != nilNode )
 +        {
 +            v = first;
 +            if( v->parent )
 +            {
 +                vt = v->t;
 +                for( ei = v->first; ei != 0; ei = edgePtr[ei].next )
 +                {
 +                    if( edgePtr[ei^vt].weight == 0 )
 +                        continue;
 +                    u = vtxPtr+edgePtr[ei].dst;
 +                    if( !u->parent )
 +                    {
 +                        u->t = vt;
 +                        u->parent = ei ^ 1;
 +                        u->ts = v->ts;
 +                        u->dist = v->dist + 1;
 +                        if( !u->next )
 +                        {
 +                            u->next = nilNode;
 +                            last = last->next = u;
 +                        }
 +                        continue;
 +                    }
 +
 +                    if( u->t != vt )
 +                    {
 +                        e0 = ei ^ vt;
 +                        break;
 +                    }
 +
 +                    if( u->dist > v->dist+1 && u->ts <= v->ts )
 +                    {
 +                        // reassign the parent
 +                        u->parent = ei ^ 1;
 +                        u->ts = v->ts;
 +                        u->dist = v->dist + 1;
 +                    }
 +                }
 +                if( e0 > 0 )
 +                    break;
 +            }
 +            // exclude the vertex from the active list
 +            first = first->next;
 +            v->next = 0;
 +        }
 +
 +        if( e0 <= 0 )
 +            break;
 +
 +        // find the minimum edge weight along the path
 +        minWeight = edgePtr[e0].weight;
 +        CV_Assert( minWeight > 0 );
 +        // k = 1: source tree, k = 0: destination tree
 +        for( int k = 1; k >= 0; k-- )
 +        {
 +            for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
 +            {
 +                if( (ei = v->parent) < 0 )
 +                    break;
 +                weight = edgePtr[ei^k].weight;
 +                minWeight = MIN(minWeight, weight);
 +                CV_Assert( minWeight > 0 );
 +            }
 +            weight = fabs(v->weight);
 +            minWeight = MIN(minWeight, weight);
 +            CV_Assert( minWeight > 0 );
 +        }
 +
 +        // modify weights of the edges along the path and collect orphans
 +        edgePtr[e0].weight -= minWeight;
 +        edgePtr[e0^1].weight += minWeight;
 +        flow += minWeight;
 +
 +        // k = 1: source tree, k = 0: destination tree
 +        for( int k = 1; k >= 0; k-- )
 +        {
 +            for( v = vtxPtr+edgePtr[e0^k].dst;; v = vtxPtr+edgePtr[ei].dst )
 +            {
 +                if( (ei = v->parent) < 0 )
 +                    break;
 +                edgePtr[ei^(k^1)].weight += minWeight;
 +                if( (edgePtr[ei^k].weight -= minWeight) == 0 )
 +                {
 +                    orphans.push_back(v);
 +                    v->parent = ORPHAN;
 +                }
 +            }
 +
 +            v->weight = v->weight + minWeight*(1-k*2);
 +            if( v->weight == 0 )
 +            {
 +               orphans.push_back(v);
 +               v->parent = ORPHAN;
 +            }
 +        }
 +
 +        // restore the search trees by finding new parents for the orphans
 +        curr_ts++;
 +        while( !orphans.empty() )
 +        {
 +            Vtx* v2 = orphans.back();
 +            orphans.pop_back();
 +
 +            int d, minDist = INT_MAX;
 +            e0 = 0;
 +            vt = v2->t;
 +
 +            for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
 +            {
 +                if( edgePtr[ei^(vt^1)].weight == 0 )
 +                    continue;
 +                u = vtxPtr+edgePtr[ei].dst;
 +                if( u->t != vt || u->parent == 0 )
 +                    continue;
 +                // compute the distance to the tree root
 +                for( d = 0;; )
 +                {
 +                    if( u->ts == curr_ts )
 +                    {
 +                        d += u->dist;
 +                        break;
 +                    }
 +                    ej = u->parent;
 +                    d++;
 +                    if( ej < 0 )
 +                    {
 +                        if( ej == ORPHAN )
 +                            d = INT_MAX-1;
 +                        else
 +                        {
 +                            u->ts = curr_ts;
 +                            u->dist = 1;
 +                        }
 +                        break;
 +                    }
 +                    u = vtxPtr+edgePtr[ej].dst;
 +                }
 +
 +                // update the distance
 +                if( ++d < INT_MAX )
 +                {
 +                    if( d < minDist )
 +                    {
 +                        minDist = d;
 +                        e0 = ei;
 +                    }
 +                    for( u = vtxPtr+edgePtr[ei].dst; u->ts != curr_ts; u = vtxPtr+edgePtr[u->parent].dst )
 +                    {
 +                        u->ts = curr_ts;
 +                        u->dist = --d;
 +                    }
 +                }
 +            }
 +
 +            if( (v2->parent = e0) > 0 )
 +            {
 +                v2->ts = curr_ts;
 +                v2->dist = minDist;
 +                continue;
 +            }
 +
 +            /* no parent is found */
 +            v2->ts = 0;
 +            for( ei = v2->first; ei != 0; ei = edgePtr[ei].next )
 +            {
 +                u = vtxPtr+edgePtr[ei].dst;
 +                ej = u->parent;
 +                if( u->t != vt || !ej )
 +                    continue;
 +                if( edgePtr[ei^(vt^1)].weight && !u->next )
 +                {
 +                    u->next = nilNode;
 +                    last = last->next = u;
 +                }
 +                if( ej > 0 && vtxPtr+edgePtr[ej].dst == v2 )
 +                {
 +                    orphans.push_back(u);
 +                    u->parent = ORPHAN;
 +                }
 +            }
 +        }
 +    }
 +    return flow;
 +}
 +
 +template <class TWeight>
 +bool GCGraph<TWeight>::inSourceSegment( int i )
 +{
 +    CV_Assert( i>=0 && i<(int)vtcs.size() );
 +    return vtcs[i].t == 0;
 +}
 +
 +}} // namespace detail, cv
 +
 +
 +//! @endcond
 +
 +#endif  // OPENCV_IMGPROC_DETAIL_GCGRAPH_HPP