Commit 4c2ef476 authored by Tobias Senst's avatar Tobias Senst Committed by Alexander Alekhin
Browse files

Merge pull request #2209 from tsenst:update_EdgeAwareInterpolator

Enhance EdgeAwareInterpolation no. matches limitation (#2209)

* sparse_match_interpolators EdgeAwareInterpolation - enhance limitation of the maximal number of matches to be interpolated from SHORT_MAX to INT_MAX by substituting short by int types

* sparse_match_interpolators EdgeAwareInterpolation - enhance limitation of the maximal number of matches to be interpolated from SHORT_MAX to INT_MAX by substituting short by int types

* fix wrong allocation of labels mats CV16S to CV_32S
parent e92f31c7
Loading
Loading
Loading
Loading
+49 −50
Original line number Diff line number Diff line
@@ -57,16 +57,16 @@ struct SparseMatch

bool operator<(const SparseMatch& lhs,const SparseMatch& rhs);

void weightedLeastSquaresAffineFit(short* labels, float* weights, int count, float lambda, SparseMatch* matches, Mat& dst);
void generateHypothesis(short* labels, int count, RNG& rng, unsigned char* is_used, SparseMatch* matches, Mat& dst);
void verifyHypothesis(short* labels, float* weights, int count, SparseMatch* matches, float eps, float lambda, Mat& hypothesis_transform, Mat& old_transform, float& old_weighted_num_inliers);
void weightedLeastSquaresAffineFit(int* labels, float* weights, int count, float lambda, SparseMatch* matches, Mat& dst);
void generateHypothesis(int* labels, int count, RNG& rng, unsigned char* is_used, SparseMatch* matches, Mat& dst);
void verifyHypothesis(int* labels, float* weights, int count, SparseMatch* matches, float eps, float lambda, Mat& hypothesis_transform, Mat& old_transform, float& old_weighted_num_inliers);

struct node
{
    float dist;
    short label;
    int label;
    node() {}
    node(short l,float d): dist(d), label(l) {}
    node(int l,float d): dist(d), label(l) {}
};

class EdgeAwareInterpolatorImpl CV_FINAL : public EdgeAwareInterpolator
@@ -78,7 +78,6 @@ public:
protected:
    int w,h;
    int match_num;

    //internal buffers:
    vector<node>* g;
    Mat labels;
@@ -186,9 +185,9 @@ void EdgeAwareInterpolatorImpl::interpolate(InputArray from_image, InputArray fr
    CV_Assert(match_num<SHRT_MAX);

    Mat src = from_image.getMat();
    labels = Mat(h,w,CV_16S);
    labels = Mat(h,w,CV_32S);
    labels = Scalar(-1);
    NNlabels = Mat(match_num,k,CV_16S);
    NNlabels = Mat(match_num,k,CV_32S);
    NNlabels = Scalar(-1);
    NNdistances = Mat(match_num,k,CV_32F);
    NNdistances = Scalar(0.0f);
@@ -218,7 +217,7 @@ void EdgeAwareInterpolatorImpl::preprocessData(Mat& src, vector<SparseMatch>& ma
        y = min((int)(matches[i].reference_image_pos.y+0.5f),h-1);

        distances.at<float>(y,x) = 0.0f;
        labels.at<short>(y,x) = (short)i;
        labels.at<int>(y,x) = (int)i;
    }

    computeGradientMagnitude(src,cost_map);
@@ -234,7 +233,7 @@ void EdgeAwareInterpolatorImpl::computeGradientMagnitude(Mat& src, Mat& dst)
    Mat dx,dy;
    Sobel(src, dx, CV_16S, 1, 0);
    Sobel(src, dy, CV_16S, 0, 1);
    float norm_coef = src.channels()*4.0f*255.0f;
    float norm_coef = src.channels()*4*255.0f;

    if(src.channels()==1)
    {
@@ -272,8 +271,8 @@ void EdgeAwareInterpolatorImpl::geodesicDistanceTransform(Mat& distances, Mat& c
    int i,j;
    float *dist_row,      *cost_row;
    float *dist_row_prev, *cost_row_prev;
    short *label_row;
    short *label_row_prev;
    int *label_row;
    int *label_row_prev;

#define CHECK(cur_dist,cur_label,cur_cost,prev_dist,prev_label,prev_cost,coef)\
{\
@@ -287,7 +286,7 @@ void EdgeAwareInterpolatorImpl::geodesicDistanceTransform(Mat& distances, Mat& c
    {
        //first pass (left-to-right, top-to-bottom):
        dist_row  = distances.ptr<float>(0);
        label_row = labels.ptr<short>(0);
        label_row = labels.ptr<int>(0);
        cost_row  = cost_map.ptr<float>(0);
        for(j=1;j<w;j++)
            CHECK(dist_row[j],label_row[j],cost_row[j],dist_row[j-1],label_row[j-1],cost_row[j-1],c1);
@@ -297,8 +296,8 @@ void EdgeAwareInterpolatorImpl::geodesicDistanceTransform(Mat& distances, Mat& c
            dist_row       = distances.ptr<float>(i);
            dist_row_prev  = distances.ptr<float>(i-1);

            label_row      = labels.ptr<short>(i);
            label_row_prev = labels.ptr<short>(i-1);
            label_row      = labels.ptr<int>(i);
            label_row_prev = labels.ptr<int>(i-1);

            cost_row      = cost_map.ptr<float>(i);
            cost_row_prev = cost_map.ptr<float>(i-1);
@@ -321,7 +320,7 @@ void EdgeAwareInterpolatorImpl::geodesicDistanceTransform(Mat& distances, Mat& c

        //second pass (right-to-left, bottom-to-top):
        dist_row  = distances.ptr<float>(h-1);
        label_row = labels.ptr<short>(h-1);
        label_row = labels.ptr<int>(h-1);
        cost_row  = cost_map.ptr<float>(h-1);
        for(j=w-2;j>=0;j--)
            CHECK(dist_row[j],label_row[j],cost_row[j],dist_row[j+1],label_row[j+1],cost_row[j+1],c1);
@@ -331,8 +330,8 @@ void EdgeAwareInterpolatorImpl::geodesicDistanceTransform(Mat& distances, Mat& c
            dist_row       = distances.ptr<float>(i);
            dist_row_prev  = distances.ptr<float>(i+1);

            label_row      = labels.ptr<short>(i);
            label_row_prev = labels.ptr<short>(i+1);
            label_row      = labels.ptr<int>(i);
            label_row_prev = labels.ptr<int>(i+1);

            cost_row      = cost_map.ptr<float>(i);
            cost_row_prev = cost_map.ptr<float>(i+1);
@@ -360,8 +359,8 @@ void EdgeAwareInterpolatorImpl::buildGraph(Mat& distances, Mat& cost_map)
{
    float *dist_row,      *cost_row;
    float *dist_row_prev, *cost_row_prev;
    short *label_row;
    short *label_row_prev;
    int *label_row;
    int *label_row_prev;
    int i,j;
    const float c1 = 1.0f/2.0f;
    const float c2 = sqrt(2.0f)/2.0f;
@@ -387,7 +386,7 @@ void EdgeAwareInterpolatorImpl::buildGraph(Mat& distances, Mat& cost_map)
    }

    dist_row  = distances.ptr<float>(0);
    label_row = labels.ptr<short>(0);
    label_row = labels.ptr<int>(0);
    cost_row  = cost_map.ptr<float>(0);
    for(j=1;j<w;j++)
        CHECK(dist_row[j],label_row[j],cost_row[j],dist_row[j-1],label_row[j-1],cost_row[j-1],c1);
@@ -397,8 +396,8 @@ void EdgeAwareInterpolatorImpl::buildGraph(Mat& distances, Mat& cost_map)
        dist_row       = distances.ptr<float>(i);
        dist_row_prev  = distances.ptr<float>(i-1);

        label_row      = labels.ptr<short>(i);
        label_row_prev = labels.ptr<short>(i-1);
        label_row      = labels.ptr<int>(i);
        label_row_prev = labels.ptr<int>(i-1);

        cost_row      = cost_map.ptr<float>(i);
        cost_row_prev = cost_map.ptr<float>(i-1);
@@ -442,7 +441,7 @@ void EdgeAwareInterpolatorImpl::buildGraph(Mat& distances, Mat& cost_map)
            }

            if(!found)
                g[neighbors[j].label].push_back(node((short)i,neighbors[j].dist));
                g[neighbors[j].label].push_back(node((int)i,neighbors[j].dist));
        }
    }
}
@@ -453,18 +452,18 @@ struct nodeHeap
    // children: 2*i, 2*i+1
    // parent: i>>1
    node* heap;
    short* heap_pos;
    int* heap_pos;
    node tmp_node;
    short size;
    short num_labels;
    int size;
    int num_labels;

    nodeHeap(short _num_labels)
    nodeHeap(int _num_labels)
    {
        num_labels = _num_labels;
        heap = new node[num_labels+1];
        heap[0] = node(-1,-1.0f);
        heap_pos = new short[num_labels];
        memset(heap_pos,0,sizeof(short)*num_labels);
        heap_pos = new int[num_labels];
        memset(heap_pos,0,sizeof(int)*num_labels);
        size=0;
    }

@@ -477,7 +476,7 @@ struct nodeHeap
    void clear()
    {
        size=0;
        memset(heap_pos,0,sizeof(short)*num_labels);
        memset(heap_pos,0,sizeof(int)*num_labels);
    }

    inline bool empty()
@@ -485,7 +484,7 @@ struct nodeHeap
        return (size==0);
    }

    inline void nodeSwap(short idx1, short idx2)
    inline void nodeSwap(int idx1, int idx2)
    {
        heap_pos[heap[idx1].label] = idx2;
        heap_pos[heap[idx2].label] = idx1;
@@ -500,8 +499,8 @@ struct nodeHeap
        size++;
        heap[size] = n;
        heap_pos[n.label] = size;
        short i = size;
        short parent_i = i>>1;
        int i = size;
        int parent_i = i>>1;
        while(heap[i].dist<heap[parent_i].dist)
        {
            nodeSwap(i,parent_i);
@@ -515,8 +514,8 @@ struct nodeHeap
        node res = heap[1];
        heap_pos[res.label] = 0;

        short i=1;
        short left,right;
        int i=1;
        int left,right;
        while( (left=i<<1) < size )
        {
            right = left+1;
@@ -543,7 +542,7 @@ struct nodeHeap
        heap[i] = heap[size];
        heap_pos[heap[i].label] = i;

        short parent_i = i>>1;
        int parent_i = i>>1;
        while(heap[i].dist<heap[parent_i].dist)
        {
            nodeSwap(i,parent_i);
@@ -562,9 +561,9 @@ struct nodeHeap
    {
        if(heap_pos[n.label])
        {
            short i = heap_pos[n.label];
            int i = heap_pos[n.label];
            heap[i].dist = min(heap[i].dist,n.dist);
            short parent_i = i>>1;
            int parent_i = i>>1;
            while(heap[i].dist<heap[parent_i].dist)
            {
                nodeSwap(i,parent_i);
@@ -587,7 +586,7 @@ void EdgeAwareInterpolatorImpl::GetKNNMatches_ParBody::operator() (const Range&
{
    int start = std::min(range.start * stripe_sz, inst->match_num);
    int end   = std::min(range.end   * stripe_sz, inst->match_num);
    nodeHeap q((short)inst->match_num);
    nodeHeap q((int)inst->match_num);
    int num_expanded_vertices;
    unsigned char* expanded_flag = new unsigned char[inst->match_num];
    node* neighbors;
@@ -600,8 +599,8 @@ void EdgeAwareInterpolatorImpl::GetKNNMatches_ParBody::operator() (const Range&
        num_expanded_vertices = 0;
        memset(expanded_flag,0,inst->match_num);
        q.clear();
        q.add(node((short)i,0.0f));
        short* NNlabels_row    = inst->NNlabels.ptr<short>(i);
        q.add(node((int)i,0.0f));
        int* NNlabels_row    = inst->NNlabels.ptr<int>(i);
        float* NNdistances_row = inst->NNdistances.ptr<float>(i);
        while(num_expanded_vertices<inst->k && !q.empty())
        {
@@ -625,7 +624,7 @@ void EdgeAwareInterpolatorImpl::GetKNNMatches_ParBody::operator() (const Range&
    delete[] expanded_flag;
}

void weightedLeastSquaresAffineFit(short* labels, float* weights, int count, float lambda, SparseMatch* matches, Mat& dst)
void weightedLeastSquaresAffineFit(int* labels, float* weights, int count, float lambda, SparseMatch* matches, Mat& dst)
{
    double sa[6][6]={{0.}}, sb[6]={0.};
    Mat A (6, 6, CV_64F, &sa[0][0]),
@@ -672,7 +671,7 @@ void weightedLeastSquaresAffineFit(short* labels, float* weights, int count, flo
    MM.reshape(2,3).convertTo(dst,CV_32F);
}

void generateHypothesis(short* labels, int count, RNG& rng, unsigned char* is_used, SparseMatch* matches, Mat& dst)
void generateHypothesis(int* labels, int count, RNG& rng, unsigned char* is_used, SparseMatch* matches, Mat& dst)
{
    int idx;
    Point2f src_points[3];
@@ -703,7 +702,7 @@ void generateHypothesis(short* labels, int count, RNG& rng, unsigned char* is_us
    getAffineTransform(src_points,dst_points).convertTo(dst,CV_32F);
}

void verifyHypothesis(short* labels, float* weights, int count, SparseMatch* matches, float eps, float lambda, Mat& hypothesis_transform, Mat& old_transform, float& old_weighted_num_inliers)
void verifyHypothesis(int* labels, float* weights, int count, SparseMatch* matches, float eps, float lambda, Mat& hypothesis_transform, Mat& old_transform, float& old_weighted_num_inliers)
{
    float* tr = hypothesis_transform.ptr<float>(0);
    Point2f a,b;
@@ -749,12 +748,12 @@ void EdgeAwareInterpolatorImpl::RansacInterpolation_ParBody::operator() (const R
        start = tmp-1;
    }

    short* KNNlabels;
    int* KNNlabels;
    float* KNNdistances;
    unsigned char* is_used = new unsigned char[inst->k];
    Mat hypothesis_transform;

    short* inlier_labels    = new short[inst->k];
    int* inlier_labels    = new int[inst->k];
    float* inlier_distances = new float[inst->k];
    float* tr;
    int num_inliers;
@@ -765,7 +764,7 @@ void EdgeAwareInterpolatorImpl::RansacInterpolation_ParBody::operator() (const R
        if(inst->g[i].empty())
            continue;

        KNNlabels    = inst->NNlabels.ptr<short>(i);
        KNNlabels    = inst->NNlabels.ptr<int>(i);
        KNNdistances = inst->NNdistances.ptr<float>(i);
        if(inc>0) //forward pass
        {
@@ -846,11 +845,11 @@ void EdgeAwareInterpolatorImpl::ransacInterpolation(vector<SparseMatch>& matches
    parallel_for_(Range(0,ransac_num_stripes),RansacInterpolation_ParBody(*this,transforms,weighted_inlier_nums,eps,&matches.front(),ransac_num_stripes,-1));

    //construct the final piecewise-affine interpolation:
    short* label_row;
    int* label_row;
    float* tr;
    for(int i=0;i<h;i++)
    {
        label_row = labels.ptr<short>(i);
        label_row = labels.ptr<int>(i);
        Point2f* dst_row = dst_dense_flow.ptr<Point2f>(i);
        for(int j=0;j<w;j++)
        {