16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M///////////////////////////////////////////////////////////////////////////////////////
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  By downloading, copying, installing or using the software you agree to this license.
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  If you do not agree to this license, do not download, install,
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  copy or use the software.
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                        Intel License Agreement
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                For Open Source Computer Vision Library
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved.
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective icvers.
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification,
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met:
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's of source code must retain the above copyright notice,
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer.
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * Redistribution's in binary form must reproduce the above copyright notice,
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     this list of conditions and the following disclaimer in the documentation
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     and/or other materials provided with the distribution.
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//   * The name of Intel Corporation may not be used to endorse or promote products
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//     derived from this software without specific prior written permission.
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed.
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct,
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services;
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability,
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage.
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* ////////////////////////////////////////////////////////////////////
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//  Geometrical transforms on images and matrices: rotation, zoom etc.
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// */
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h"
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#undef CV_MAT_ELEM_PTR_FAST
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size )  \
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn     ((mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col))
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renninline float
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennmin4( float a, float b, float c, float d )
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    a = MIN(a,b);
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    c = MIN(c,d);
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return MIN(a,c);
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CV_MAT_3COLOR_ELEM(img,type,y,x,c) CV_MAT_ELEM(img,type,y,(x)*3+(c))
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define KNOWN  0  //known outside narrow band
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define BAND   1  //narrow band (known)
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define INSIDE 2  //unknown
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define CHANGE 3  //servise
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvHeapElem
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    float T;
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int i,j;
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct CvHeapElem* prev;
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    struct CvHeapElem* next;
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvHeapElem;
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennclass CvPriorityQueueFloat
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennprotected:
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvHeapElem *mem,*empty,*head,*tail;
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int num,in;
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennpublic:
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool Init( const CvMat* f )
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i,j;
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for( i = num = 0; i < f->rows; i++ )
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for( j = 0; j < f->cols; j++ )
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                num += CV_MAT_ELEM(*f,uchar,i,j)!=0;
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (num<=0) return false;
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mem = (CvHeapElem*)cvAlloc((num+2)*sizeof(CvHeapElem));
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (mem==NULL) return false;
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        head       = mem;
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        head->i    = head->j = -1;
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        head->prev = NULL;
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        head->next = mem+1;
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        head->T    = -FLT_MAX;
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        empty      = mem+1;
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for (i=1; i<=num; i++) {
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            mem[i].prev   = mem+i-1;
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            mem[i].next   = mem+i+1;
1061691b57dbad9cfc15b9a8b72f8b376733b934ffeDoug Kwan            mem[i].i      = -1;
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            mem[i].T      = FLT_MAX;
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tail       = mem+i;
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tail->i    = tail->j = -1;
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tail->prev = mem+i-1;
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tail->next = NULL;
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tail->T    = FLT_MAX;
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return true;
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool Add(const CvMat* f) {
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        int i,j;
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        for (i=0; i<f->rows; i++) {
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for (j=0; j<f->cols; j++) {
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if (CV_MAT_ELEM(*f,uchar,i,j)!=0) {
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if (!Push(i,j,0)) return false;
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return true;
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool Push(int i, int j, float T) {
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvHeapElem *tmp=empty,*add=empty;
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (empty==tail) return false;
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        while (tmp->prev->T>T) tmp = tmp->prev;
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (tmp!=empty) {
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            add->prev->next = add->next;
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            add->next->prev = add->prev;
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            empty = add->next;
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            add->prev = tmp->prev;
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            add->next = tmp;
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            add->prev->next = add;
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            add->next->prev = add;
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        } else {
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            empty = empty->next;
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        add->i = i;
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        add->j = j;
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        add->T = T;
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        in++;
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //      printf("push i %3d  j %3d  T %12.4e  in %4d\n",i,j,T,in);
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return true;
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool Pop(int *i, int *j) {
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvHeapElem *tmp=head->next;
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (empty==tmp) return false;
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *i = tmp->i;
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *j = tmp->j;
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->prev->next = tmp->next;
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->next->prev = tmp->prev;
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->prev = empty->prev;
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->next = empty;
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->prev->next = tmp;
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->next->prev = tmp;
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        empty = tmp;
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        in--;
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //      printf("pop  i %3d  j %3d  T %12.4e  in %4d\n",tmp->i,tmp->j,tmp->T,in);
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return true;
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool Pop(int *i, int *j, float *T) {
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CvHeapElem *tmp=head->next;
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (empty==tmp) return false;
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *i = tmp->i;
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *j = tmp->j;
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        *T = tmp->T;
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->prev->next = tmp->next;
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->next->prev = tmp->prev;
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->prev = empty->prev;
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->next = empty;
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->prev->next = tmp;
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        tmp->next->prev = tmp;
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        empty = tmp;
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        in--;
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        //      printf("pop  i %3d  j %3d  T %12.4e  in %4d\n",tmp->i,tmp->j,tmp->T,in);
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return true;
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPriorityQueueFloat(void) {
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        num=in=0;
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        mem=empty=head=tail=NULL;
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ~CvPriorityQueueFloat(void)
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvFree( &mem );
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renninline float VectorScalMult(CvPoint2D32f v1,CvPoint2D32f v2) {
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   return v1.x*v2.x+v1.y*v2.y;
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renninline float VectorLength(CvPoint2D32f v1) {
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   return v1.x*v1.x+v1.y*v1.y;
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn///////////////////////////////////////////////////////////////////////////////////////////
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//HEAP::iterator Heap_Iterator;
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//HEAP Heap;
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennfloat FastMarching_solve(int i1,int j1,int i2,int j2, const CvMat* f, const CvMat* t)
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    double sol, a11, a22, m12;
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    a11=CV_MAT_ELEM(*t,float,i1,j1);
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    a22=CV_MAT_ELEM(*t,float,i2,j2);
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m12=MIN(a11,a22);
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_ELEM(*f,uchar,i1,j1) != INSIDE )
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if( fabs(a11-a22) >= 1.0 )
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sol = 1+m12;
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                sol = (a11+a22+sqrt((double)(2-(a11-a22)*(a11-a22))))*0.5;
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            sol = 1+a11;
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sol = 1+a22;
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        sol = 1+m12;
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return (float)sol;
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////////////////////////////////////////////////////////////////////
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) {
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   int i, j, ii = 0, jj = 0, q;
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   float dist;
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   while (Heap->Pop(&ii,&jj)) {
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      unsigned known=(negate)?CHANGE:KNOWN;
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      CV_MAT_ELEM(*f,uchar,ii,jj) = (uchar)known;
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for (q=0; q<4; q++) {
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         i=0; j=0;
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         if     (q==0) {i=ii-1; j=jj;}
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         else if(q==1) {i=ii;   j=jj-1;}
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         else if(q==2) {i=ii+1; j=jj;}
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         else {i=ii;   j=jj+1;}
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         if ((i<=0)||(j<=0)||(i>f->rows)||(j>f->cols)) continue;
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        FastMarching_solve(i+1,j,i,j-1,f,t),
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        FastMarching_solve(i-1,j,i,j+1,f,t),
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        FastMarching_solve(i+1,j,i,j+1,f,t));
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_MAT_ELEM(*t,float,i,j) = dist;
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            CV_MAT_ELEM(*f,uchar,i,j) = BAND;
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            Heap->Push(i,j,dist);
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         }
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   }
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   if (negate) {
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for (i=0; i<f->rows; i++) {
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         for(j=0; j<f->cols; j++) {
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (CV_MAT_ELEM(*f,uchar,i,j) == CHANGE) {
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*f,uchar,i,j) = KNOWN;
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*t,float,i,j) = -CV_MAT_ELEM(*t,float,i,j);
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         }
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   }
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap ) {
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   float dist;
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   if (CV_MAT_CN(out->type)==3) {
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      while (Heap->Pop(&ii,&jj)) {
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         for(q=0; q<4; q++) {
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if     (q==0) {i=ii-1; j=jj;}
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==1) {i=ii;   j=jj-1;}
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==2) {i=ii+1; j=jj;}
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==3) {i=ii;   j=jj+1;}
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j-1,f,t),
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i-1,j,i,j+1,f,t),
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j+1,f,t));
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*t,float,i,j) = dist;
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               for (color=0; color<=2; color++) {
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CvPoint2D32f gradI,gradT,r;
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  float Ia=0,Jx=0,Jy=0,s=1.0e-20f,w,dst,lev,dir,sat;
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) {
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f;
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j)));
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  } else {
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1)));
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=0;
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) {
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f;
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j)));
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  } else {
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j)));
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=0;
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  for (k=i-range; k<=i+range; k++) {
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     for (l=j-range; l<=j+range; l++) {
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.y     = (float)(i-k);
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.x     = (float)(j-l);
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dst = (float)(1./(VectorLength(r)*sqrt((double)VectorLength(r))));
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j))));
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dir=VectorScalMult(r,gradT);
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (fabs(dir)<=0.01) dir=0.000001f;
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              w = (float)fabs(dst*lev*dir);
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)))*2.0f;
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)));
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)));
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=0;
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)))*2.0f;
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)));
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)));
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=0;
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Ia += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color));
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Jx -= (float)w * (float)(gradI.x*r.x);
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Jy -= (float)w * (float)(gradI.y*r.y);
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              s  += w;
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           }
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  sat = (float)((Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)+0.5f));
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  {
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int isat = cvRound(sat);
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = CV_CAST_8U(isat);
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               }
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*f,uchar,i,j) = BAND;
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               Heap->Push(i,j,dist);
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         }
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   } else if (CV_MAT_CN(out->type)==1) {
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      while (Heap->Pop(&ii,&jj)) {
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         for(q=0; q<4; q++) {
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if     (q==0) {i=ii-1; j=jj;}
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==1) {i=ii;   j=jj-1;}
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==2) {i=ii+1; j=jj;}
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==3) {i=ii;   j=jj+1;}
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j-1,f,t),
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i-1,j,i,j+1,f,t),
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j+1,f,t));
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*t,float,i,j) = dist;
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               for (color=0; color<=0; color++) {
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CvPoint2D32f gradI,gradT,r;
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  float Ia=0,Jx=0,Jy=0,s=1.0e-20f,w,dst,lev,dir,sat;
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) {
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f;
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j)));
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  } else {
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1)));
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.x=0;
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) {
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f;
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j)));
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  } else {
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j)));
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     } else {
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        gradT.y=0;
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  for (k=i-range; k<=i+range; k++) {
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     for (l=j-range; l<=j+range; l++) {
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.y     = (float)(i-k);
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.x     = (float)(j-l);
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dst = (float)(1./(VectorLength(r)*sqrt(VectorLength(r))));
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j))));
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dir=VectorScalMult(r,gradT);
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (fabs(dir)<=0.01) dir=0.000001f;
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              w = (float)fabs(dst*lev*dir);
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm-1)))*2.0f;
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm)));
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp)-CV_MAT_ELEM(*out,uchar,km,lm-1)));
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=0;
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)))*2.0f;
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,km,lm)));
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)));
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=0;
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Ia += (float)w * (float)(CV_MAT_ELEM(*out,uchar,km,lm));
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Jx -= (float)w * (float)(gradI.x*r.x);
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Jy -= (float)w * (float)(gradI.y*r.y);
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              s  += w;
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           }
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  sat = (float)((Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)+0.5f));
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  {
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int isat = cvRound(sat);
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CV_MAT_ELEM(*out,uchar,i-1,j-1) = CV_CAST_8U(isat);
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               }
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*f,uchar,i,j) = BAND;
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               Heap->Push(i,j,dist);
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         }
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   }
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap) {
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   float dist;
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   if (CV_MAT_CN(out->type)==3) {
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      while (Heap->Pop(&ii,&jj)) {
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         for(q=0; q<4; q++) {
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if     (q==0) {i=ii-1; j=jj;}
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==1) {i=ii;   j=jj-1;}
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==2) {i=ii+1; j=jj;}
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==3) {i=ii;   j=jj+1;}
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j-1,f,t),
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i-1,j,i,j+1,f,t),
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j+1,f,t));
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*t,float,i,j) = dist;
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               for (color=0; color<=2; color++) {
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CvPoint2D32f gradI,r;
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  float Ia=0,s=1.0e-20f,w,dst,dir;
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  for (k=i-range; k<=i+range; k++) {
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     int km=k-1+(k==1),kp=k-1-(k==f->rows-2);
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     for (l=j-range; l<=j+range; l++) {
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int lm=l-1+(l==1),lp=l-1-(l==f->cols-2);
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if (k>0&&l>0&&k<f->rows-1&&l<f->cols-1) {
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.y=(float)(k-i);
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.x=(float)(l-j);
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dst = 1/(VectorLength(r)*VectorLength(r)+1);
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color))+
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                    abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)));
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)))*2.0f;
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)))*2.0f;
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=0;
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color))+
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                    abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)));
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)))*2.0f;
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)))*2.0f;
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=0;
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              gradI.x=-gradI.x;
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dir=VectorScalMult(r,gradI);
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (fabs(dir)<=0.01) {
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 dir=0.000001f;
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI)));
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              w = dst*dir;
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Ia += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color));
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              s  += w;
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           }
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  {
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int out_val = cvRound((double)Ia/s);
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = CV_CAST_8U(out_val);
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               }
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*f,uchar,i,j) = BAND;
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               Heap->Push(i,j,dist);
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         }
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   } else if (CV_MAT_CN(out->type)==1) {
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      while (Heap->Pop(&ii,&jj)) {
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         for(q=0; q<4; q++) {
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if     (q==0) {i=ii-1; j=jj;}
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==1) {i=ii;   j=jj-1;}
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==2) {i=ii+1; j=jj;}
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else if(q==3) {i=ii;   j=jj+1;}
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j-1,f,t),
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i-1,j,i,j+1,f,t),
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           FastMarching_solve(i+1,j,i,j+1,f,t));
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*t,float,i,j) = dist;
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               {
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CvPoint2D32f gradI,r;
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  float Ia=0,s=1.0e-20f,w,dst,dir;
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  for (k=i-range; k<=i+range; k++) {
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     for (l=j-range; l<=j+range; l++) {
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                               ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.y=(float)(i-k);
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              r.x=(float)(j-l);
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dst = 1/(VectorLength(r)*VectorLength(r)+1);
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,kp,lm))+
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                    abs(CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)));
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,kp,lm)))*2.0f;
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)))*2.0f;
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.x=0;
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm))+
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                    abs(CV_MAT_ELEM(*out,uchar,km,lm)-CV_MAT_ELEM(*out,uchar,km,lm-1)));
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm)))*2.0f;
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lm)-CV_MAT_ELEM(*out,uchar,km,lm-1)))*2.0f;
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 } else {
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                    gradI.y=0;
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 }
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              gradI.x=-gradI.x;
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              dir=VectorScalMult(r,gradI);
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              if (fabs(dir)<=0.01) {
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 dir=0.000001f;
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              } else {
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                 dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI)));
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              }
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              w = dst*dir;
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              Ia += (float)w * (float)(CV_MAT_ELEM(*out,uchar,km,lm));
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                              s  += w;
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                           }
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        }
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                     }
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  {
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  int out_val = cvRound((double)Ia/s);
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  CV_MAT_ELEM(*out,uchar,i-1,j-1) = CV_CAST_8U(out_val);
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                  }
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               }
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*f,uchar,i,j) = BAND;
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               Heap->Push(i,j,dist);
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         }
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   }
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define SET_BORDER1_C1(image,type,value) {\
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      int i,j;\
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for(j=0; j<image->cols; j++) {\
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         CV_MAT_ELEM(*image,type,0,j) = value;\
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }\
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for (i=1; i<image->rows-1; i++) {\
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         CV_MAT_ELEM(*image,type,i,0) = CV_MAT_ELEM(*image,type,i,image->cols-1) = value;\
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }\
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for(j=0; j<image->cols; j++) {\
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         CV_MAT_ELEM(*image,type,erows-1,j) = value;\
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }\
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   }
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define COPY_MASK_BORDER1_C1(src,dst,type) {\
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      int i,j;\
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      for (i=0; i<src->rows; i++) {\
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         for(j=0; j<src->cols; j++) {\
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (CV_MAT_ELEM(*src,type,i,j)!=0)\
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn               CV_MAT_ELEM(*dst,type,i+1,j+1) = INSIDE;\
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn         }\
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn      }\
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn   }
7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void
7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_img,
7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn           double inpaintRange, int flags )
7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat *mask = 0, *band = 0, *f = 0, *t = 0, *out = 0;
7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvPriorityQueueFloat *Heap = 0, *Out = 0;
7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    IplConvKernel *el_cross = 0, *el_range = 0;
7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_FUNCNAME( "cvInpaint" );
7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __BEGIN__;
7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat input_hdr, mask_hdr, output_hdr;
7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CvMat* input_img, *inpaint_mask, *output_img;
7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int range=cvRound(inpaintRange);
7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int erows, ecols;
7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( input_img = cvGetMat( _input_img, &input_hdr ));
7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( inpaint_mask = cvGetMat( _inpaint_mask, &mask_hdr ));
7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( output_img = cvGetMat( _output_img, &output_hdr ));
7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask))
7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnmatchedSizes, "All the input and output images must have the same size" );
7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( (CV_MAT_TYPE(input_img->type) != CV_8UC1 &&
7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_MAT_TYPE(input_img->type) != CV_8UC3) ||
7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        !CV_ARE_TYPES_EQ(input_img,output_img) )
7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat,
7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        "Only 8-bit 1-channel and 3-channel input/output images are supported" );
7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 )
7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_ERROR( CV_StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" );
7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    range = MAX(range,1);
7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    range = MIN(range,100);
7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ecols = input_img->cols + 2;
7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    erows = input_img->rows + 2;
7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( f = cvCreateMat(erows, ecols, CV_8UC1));
7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( t = cvCreateMat(erows, ecols, CV_32FC1));
7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( band = cvCreateMat(erows, ecols, CV_8UC1));
7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( mask = cvCreateMat(erows, ecols, CV_8UC1));
7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    CV_CALL( el_cross = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL));
7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvCopy( input_img, output_img );
7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSet(mask,cvScalar(KNOWN,0,0,0));
7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    COPY_MASK_BORDER1_C1(inpaint_mask,mask,uchar);
7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    SET_BORDER1_C1(mask,uchar,0);
7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSet(f,cvScalar(KNOWN,0,0,0));
7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSet(t,cvScalar(1.0e6f,0,0,0));
7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvDilate(mask,band,el_cross,1);   // image with narrow band
7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Heap=new CvPriorityQueueFloat;
7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (!Heap->Init(band))
7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSub(band,mask,band,NULL);
7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    SET_BORDER1_C1(band,uchar,0);
7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (!Heap->Add(band))
7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        EXIT;
7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSet(f,cvScalar(BAND,0,0,0),band);
7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSet(f,cvScalar(INSIDE,0,0,0),mask);
7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvSet(t,cvScalar(0,0,0,0),band);
7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if( flags == CV_INPAINT_TELEA )
7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( out = cvCreateMat(erows, ecols, CV_8UC1));
7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        CV_CALL( el_range = cvCreateStructuringElementEx(2*range+1,2*range+1,
7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            range,range,CV_SHAPE_RECT,NULL));
7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvDilate(mask,out,el_range,1);
7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSub(out,mask,out,NULL);
7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Out=new CvPriorityQueueFloat;
7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (!Out->Init(out))
7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (!Out->Add(band))
8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            EXIT;
8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        cvSub(out,band,out,NULL);
8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        SET_BORDER1_C1(out,uchar,0);
8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvCalcFMM(out,t,Out,true);
8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvTeleaInpaintFMM(mask,t,output_img,range,Heap);
8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        icvNSInpaintFMM(mask,t,output_img,range,Heap);
8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    __END__;
8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete Out;
8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    delete Heap;
8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseStructuringElement(&el_cross);
8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseStructuringElement(&el_range);
8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&out);
8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&mask);
8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&band);
8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&t);
8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    cvReleaseMat(&f);
8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
822