From 807170d5c9e9c1b6c90fb7067a7311538ed12639 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Tue, 1 Oct 2024 20:02:03 +0300 Subject: [PATCH] C-API cleanup: inpaint algorithms in photo --- modules/photo/src/inpaint.cpp | 397 +++++++++++++++++----------------- 1 file changed, 196 insertions(+), 201 deletions(-) diff --git a/modules/photo/src/inpaint.cpp b/modules/photo/src/inpaint.cpp index d9a7dbc58b..2f2f368fa1 100644 --- a/modules/photo/src/inpaint.cpp +++ b/modules/photo/src/inpaint.cpp @@ -49,8 +49,8 @@ #include #include "precomp.hpp" -#include "opencv2/imgproc/imgproc_c.h" -#include "opencv2/photo/legacy/constants_c.h" + +using namespace cv; #undef CV_MAT_ELEM_PTR_FAST #define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size ) \ @@ -74,7 +74,6 @@ min4( float a, float b, float c, float d ) return MIN(a,c); } -#define CV_MAT_3COLOR_ELEM(img,type,y,x,c) CV_MAT_ELEM(img,type,y,(x)*3+(c)) #define KNOWN 0 //known outside narrow band #define BAND 1 //narrow band (known) #define INSIDE 2 //unknown @@ -109,11 +108,11 @@ protected: int next_order; public: - bool Add(const CvMat* f) { + bool Add(const Mat &f) { int i,j; - for (i=0; irows; i++) { - for (j=0; jcols; j++) { - if (CV_MAT_ELEM(*f,uchar,i,j)!=0) { + for (i=0; i(i, j)!=0) { if (!Push(i,j,0)) return false; } } @@ -166,22 +165,22 @@ static inline float VectorLength(const cv::Point2f& v1) //HEAP::iterator Heap_Iterator; //HEAP Heap; -static float FastMarching_solve(int i1,int j1,int i2,int j2, const CvMat* f, const CvMat* t) +static float FastMarching_solve(int i1,int j1,int i2,int j2, const Mat &f, const Mat &t) { double sol, a11, a22, m12; - a11=CV_MAT_ELEM(*t,float,i1,j1); - a22=CV_MAT_ELEM(*t,float,i2,j2); + a11=t.at(i1,j1); + a22=t.at(i2,j2); m12=MIN(a11,a22); - if( CV_MAT_ELEM(*f,uchar,i1,j1) != INSIDE ) - if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE ) + if( f.at(i1,j1) != INSIDE ) + if( f.at(i2,j2) != INSIDE ) if( fabs(a11-a22) >= 1.0 ) sol = 1+m12; else sol = (a11+a22+sqrt((double)(2-(a11-a22)*(a11-a22))))*0.5; else sol = 1+a11; - else if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE ) + else if( f.at(i2,j2) != INSIDE ) sol = 1+a22; else sol = 1+m12; @@ -193,14 +192,14 @@ static float FastMarching_solve(int i1,int j1,int i2,int j2, const CvMat* f, con static void -icvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) { +icvCalcFMM(Mat &f, Mat &t, CvPriorityQueueFloat *Heap, bool negate) { int i, j, ii = 0, jj = 0, q; float dist; while (Heap->Pop(&ii,&jj)) { unsigned known=(negate)?CHANGE:KNOWN; - CV_MAT_ELEM(*f,uchar,ii,jj) = (uchar)known; + f.at(ii,jj) = (uchar)known; for (q=0; q<4; q++) { i=0; j=0; @@ -208,26 +207,26 @@ icvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) { else if(q==1) {i=ii; j=jj-1;} else if(q==2) {i=ii+1; j=jj;} else {i=ii; j=jj+1;} - if ((i<=0)||(j<=0)||(i>f->rows)||(j>f->cols)) continue; + if ((i<=0)||(j<=0)||(i>f.rows)||(j>f.cols)) continue; - if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) { + if (f.at(i,j)==INSIDE) { dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t), FastMarching_solve(i+1,j,i,j-1,f,t), FastMarching_solve(i-1,j,i,j+1,f,t), FastMarching_solve(i+1,j,i,j+1,f,t)); - CV_MAT_ELEM(*t,float,i,j) = dist; - CV_MAT_ELEM(*f,uchar,i,j) = BAND; + t.at(i,j) = dist; + f.at(i,j) = BAND; Heap->Push(i,j,dist); } } } if (negate) { - for (i=0; irows; i++) { - for(j=0; jcols; j++) { - if (CV_MAT_ELEM(*f,uchar,i,j) == CHANGE) { - CV_MAT_ELEM(*f,uchar,i,j) = KNOWN; - CV_MAT_ELEM(*t,float,i,j) = -CV_MAT_ELEM(*t,float,i,j); + for (i=0; i(i,j) == CHANGE) { + f.at(i,j) = KNOWN; + t.at(i,j) = -t.at(i,j); } } } @@ -236,53 +235,54 @@ icvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) { template static void -icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap ) { +icvTeleaInpaintFMM(Mat &f, Mat &t, Mat &out, int range, CvPriorityQueueFloat *Heap ) { int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0; float dist; - if (CV_MAT_CN(out->type)==3) { + if (out.channels()==3) { + typedef Vec PixelT; while (Heap->Pop(&ii,&jj)) { - CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN; + f.at(ii,jj) = KNOWN; for(q=0; q<4; q++) { if (q==0) {i=ii-1; j=jj;} else if(q==1) {i=ii; j=jj-1;} else if(q==2) {i=ii+1; j=jj;} else if(q==3) {i=ii; j=jj+1;} - if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue; + if ((i<=0)||(j<=0)||(i>t.rows-1)||(j>t.cols-1)) continue; - if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) { + if (f.at(i,j)==INSIDE) { dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t), FastMarching_solve(i+1,j,i,j-1,f,t), FastMarching_solve(i-1,j,i,j+1,f,t), FastMarching_solve(i+1,j,i,j+1,f,t)); - CV_MAT_ELEM(*t,float,i,j) = dist; + t.at(i,j) = dist; cv::Point2f gradT[3]; for (color=0; color<=2; color++) { - if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) { - gradT[color].x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f; + if (f.at(i,j+1)!=INSIDE) { + if (f.at(i,j-1)!=INSIDE) { + gradT[color].x=(float)((t.at(i,j+1)-t.at(i,j-1)))*0.5f; } else { - gradT[color].x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j))); + gradT[color].x=(float)((t.at(i,j+1)-t.at(i,j))); } } else { - if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) { - gradT[color].x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1))); + if (f.at(i,j-1)!=INSIDE) { + gradT[color].x=(float)((t.at(i,j)-t.at(i,j-1))); } else { gradT[color].x=0; } } - if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) { - gradT[color].y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f; + if (f.at(i+1,j)!=INSIDE) { + if (f.at(i-1,j)!=INSIDE) { + gradT[color].y=(float)((t.at(i+1,j)-t.at(i-1,j)))*0.5f; } else { - gradT[color].y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j))); + gradT[color].y=(float)((t.at(i+1,j)-t.at(i,j))); } } else { - if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) { - gradT[color].y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j))); + if (f.at(i-1,j)!=INSIDE) { + gradT[color].y=(float)((t.at(i,j)-t.at(i-1,j))); } else { gradT[color].y=0; } @@ -297,50 +297,50 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu float w,dst,lev,dir,sat; for (k=i-range; k<=i+range; k++) { - int km=k-1+(k==1),kp=k-1-(k==t->rows-2); + int km=k-1+(k==1),kp=k-1-(k==t.rows-2); for (l=j-range; l<=j+range; l++) { - int lm=l-1+(l==1),lp=l-1-(l==t->cols-2); - if (k>0&&l>0&&krows-1&&lcols-1) { - if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&& + int lm=l-1+(l==1),lp=l-1-(l==t.cols-2); + if (k>0&&l>0&&k(k,l)!=INSIDE)&& ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) { for (color=0; color<=2; color++) { r.y = (float)(i-k); r.x = (float)(j-l); dst = (float)(1./(VectorLength(r)*sqrt((double)VectorLength(r)))); - lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j)))); + lev = (float)(1./(1+fabs(t.at(k,l)-t.at(i,j)))); dir=VectorScalMult(r,gradT[color]); if (fabs(dir)<=0.01) dir=0.000001f; w = (float)fabs(dst*lev*dir); - if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - 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; + if (f.at(k,l+1)!=INSIDE) { + if (f.at(k,l-1)!=INSIDE) { + gradI.x=(float)((out.at(km,lp+1)[color]-out.at(km,lm-1)[color]))*2.0f; } else { - gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color))); + gradI.x=(float)((out.at(km,lp+1)[color]-out.at(km,lm)[color])); } } else { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color))); + if (f.at(k,l-1)!=INSIDE) { + gradI.x=(float)((out.at(km,lp)[color]-out.at(km,lm-1)[color])); } else { gradI.x=0; } } - if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - 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; + if (f.at(k+1,l)!=INSIDE) { + if (f.at(k-1,l)!=INSIDE) { + gradI.y=(float)((out.at(kp+1,lm)[color]-out.at(km-1,lm)[color]))*2.0f; } else { - gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color))); + gradI.y=(float)((out.at(kp+1,lm)[color]-out.at(km,lm)[color])); } } else { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color))); + if (f.at(k-1,l)!=INSIDE) { + gradI.y=(float)((out.at(kp,lm)[color]-out.at(km-1,lm)[color])); } else { gradI.y=0; } } - Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,k-1,l-1,color)); + Ia[color] += (float)w * (float)(out.at(k-1,l-1)[color]); Jx[color] -= (float)w * (float)(gradI.x*r.x); Jy[color] -= (float)w * (float)(gradI.y*r.y); s[color] += w; @@ -351,108 +351,108 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu } for (color=0; color<=2; color++) { sat = (float)(Ia[color]/s[color]+(Jx[color]+Jy[color])/(sqrt(Jx[color]*Jx[color]+Jy[color]*Jy[color])+1.0e-20f)); - CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = round_cast(sat); + out.at(i-1,j-1)[color] = round_cast(sat); } - CV_MAT_ELEM(*f,uchar,i,j) = BAND; + f.at(i,j) = BAND; Heap->Push(i,j,dist); } } } - } else if (CV_MAT_CN(out->type)==1) { + } else if (out.channels()==1) { while (Heap->Pop(&ii,&jj)) { - CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN; + f.at(ii,jj) = KNOWN; for(q=0; q<4; q++) { if (q==0) {i=ii-1; j=jj;} else if(q==1) {i=ii; j=jj-1;} else if(q==2) {i=ii+1; j=jj;} else if(q==3) {i=ii; j=jj+1;} - if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue; + if ((i<=0)||(j<=0)||(i>t.rows-1)||(j>t.cols-1)) continue; - if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) { + if (f.at(i,j)==INSIDE) { dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t), FastMarching_solve(i+1,j,i,j-1,f,t), FastMarching_solve(i-1,j,i,j+1,f,t), FastMarching_solve(i+1,j,i,j+1,f,t)); - CV_MAT_ELEM(*t,float,i,j) = dist; + t.at(i,j) = dist; for (color=0; color<=0; color++) { cv::Point2f gradI,gradT,r; float Ia=0,Jx=0,Jy=0,s=1.0e-20f,w,dst,lev,dir,sat; - if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) { - gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f; + if (f.at(i,j+1)!=INSIDE) { + if (f.at(i,j-1)!=INSIDE) { + gradT.x=(float)((t.at(i,j+1)-t.at(i,j-1)))*0.5f; } else { - gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j))); + gradT.x=(float)((t.at(i,j+1)-t.at(i,j))); } } else { - if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) { - gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1))); + if (f.at(i,j-1)!=INSIDE) { + gradT.x=(float)((t.at(i,j)-t.at(i,j-1))); } else { gradT.x=0; } } - if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) { - gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f; + if (f.at(i+1,j)!=INSIDE) { + if (f.at(i-1,j)!=INSIDE) { + gradT.y=(float)((t.at(i+1,j)-t.at(i-1,j)))*0.5f; } else { - gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j))); + gradT.y=(float)((t.at(i+1,j)-t.at(i,j))); } } else { - if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) { - gradT.y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j))); + if (f.at(i-1,j)!=INSIDE) { + gradT.y=(float)((t.at(i,j)-t.at(i-1,j))); } else { gradT.y=0; } } for (k=i-range; k<=i+range; k++) { - int km=k-1+(k==1),kp=k-1-(k==t->rows-2); + int km=k-1+(k==1),kp=k-1-(k==t.rows-2); for (l=j-range; l<=j+range; l++) { - int lm=l-1+(l==1),lp=l-1-(l==t->cols-2); - if (k>0&&l>0&&krows-1&&lcols-1) { - if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&& + int lm=l-1+(l==1),lp=l-1-(l==t.cols-2); + if (k>0&&l>0&&k(k,l)!=INSIDE)&& ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) { r.y = (float)(i-k); r.x = (float)(j-l); dst = (float)(1./(VectorLength(r)*sqrt(VectorLength(r)))); - lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j)))); + lev = (float)(1./(1+fabs(t.at(k,l)-t.at(i,j)))); dir=VectorScalMult(r,gradT); if (fabs(dir)<=0.01) dir=0.000001f; w = (float)fabs(dst*lev*dir); - if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - gradI.x=(float)((CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm-1)))*2.0f; + if (f.at(k,l+1)!=INSIDE) { + if (f.at(k,l-1)!=INSIDE) { + gradI.x=(float)((out.at(km,lp+1)-out.at(km,lm-1)))*2.0f; } else { - gradI.x=(float)((CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm))); + gradI.x=(float)((out.at(km,lp+1)-out.at(km,lm))); } } else { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - gradI.x=(float)((CV_MAT_ELEM(*out,data_type,km,lp)-CV_MAT_ELEM(*out,data_type,km,lm-1))); + if (f.at(k,l-1)!=INSIDE) { + gradI.x=(float)((out.at(km,lp)-out.at(km,lm-1))); } else { gradI.x=0; } } - if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - gradI.y=(float)((CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)))*2.0f; + if (f.at(k+1,l)!=INSIDE) { + if (f.at(k-1,l)!=INSIDE) { + gradI.y=(float)((out.at(kp+1,lm)-out.at(km-1,lm)))*2.0f; } else { - gradI.y=(float)((CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,km,lm))); + gradI.y=(float)((out.at(kp+1,lm)-out.at(km,lm))); } } else { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - gradI.y=(float)((CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm))); + if (f.at(k-1,l)!=INSIDE) { + gradI.y=(float)((out.at(kp,lm)-out.at(km-1,lm))); } else { gradI.y=0; } } - Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,k-1,l-1)); + Ia += (float)w * (float)(out.at(k-1,l-1)); Jx -= (float)w * (float)(gradI.x*r.x); Jy -= (float)w * (float)(gradI.y*r.y); s += w; @@ -462,11 +462,11 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu } sat = (float)(Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)); { - CV_MAT_ELEM(*out,data_type,i-1,j-1) = round_cast(sat); + out.at(i-1,j-1) = round_cast(sat); } } - CV_MAT_ELEM(*f,uchar,i,j) = BAND; + f.at(i,j) = BAND; Heap->Push(i,j,dist); } } @@ -476,28 +476,29 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu template static void -icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap) { +icvNSInpaintFMM(Mat &f, Mat &t, Mat &out, int range, CvPriorityQueueFloat *Heap) { int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0; float dist; - if (CV_MAT_CN(out->type)==3) { + if (out.channels()==3) { + typedef Vec PixelT; while (Heap->Pop(&ii,&jj)) { - CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN; + f.at(ii,jj) = KNOWN; for(q=0; q<4; q++) { if (q==0) {i=ii-1; j=jj;} else if(q==1) {i=ii; j=jj-1;} else if(q==2) {i=ii+1; j=jj;} else if(q==3) {i=ii; j=jj+1;} - if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue; + if ((i<=0)||(j<=0)||(i>t.rows-1)||(j>t.cols-1)) continue; - if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) { + if (f.at(i,j)==INSIDE) { dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t), FastMarching_solve(i+1,j,i,j-1,f,t), FastMarching_solve(i-1,j,i,j+1,f,t), FastMarching_solve(i+1,j,i,j+1,f,t)); - CV_MAT_ELEM(*t,float,i,j) = dist; + t.at(i,j) = dist; cv::Point2f gradI,r; float Ia[3]={0,0,0}; @@ -505,11 +506,11 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue float w,dst,dir; for (k=i-range; k<=i+range; k++) { - int km=k-1+(k==1),kp=k-1-(k==f->rows-2); + int km=k-1+(k==1),kp=k-1-(k==f.rows-2); for (l=j-range; l<=j+range; l++) { - int lm=l-1+(l==1),lp=l-1-(l==f->cols-2); - if (k>0&&l>0&&krows-1&&lcols-1) { - if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&& + int lm=l-1+(l==1),lp=l-1-(l==f.cols-2); + if (k>0&&l>0&&k(k,l)!=INSIDE)&& ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) { for (color=0; color<=2; color++) { r.y=(float)(k-i); @@ -517,30 +518,30 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue dst = 1/(VectorLength(r)*VectorLength(r)+1); - if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color))+ - abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color))); + if (f.at(k+1,l)!=INSIDE) { + if (f.at(k-1,l)!=INSIDE) { + gradI.x=(float)(abs(out.at(kp+1,lm)[color]-out.at(kp,lm)[color])+ + abs(out.at(kp,lm)[color]-out.at(km-1,lm)[color])); } else { - 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; + gradI.x=(float)(abs(out.at(kp+1,lm)[color]-out.at(kp,lm)[color]))*2.0f; } } else { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - 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; + if (f.at(k-1,l)!=INSIDE) { + gradI.x=(float)(abs(out.at(kp,lm)[color]-out.at(km-1,lm)[color]))*2.0f; } else { gradI.x=0; } } - if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color))+ - abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color))); + if (f.at(k,l+1)!=INSIDE) { + if (f.at(k,l-1)!=INSIDE) { + gradI.y=(float)(abs(out.at(km,lp+1)[color]-out.at(km,lm)[color])+ + abs(out.at(km,lm)[color]-out.at(km,lm-1)[color])); } else { - 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; + gradI.y=(float)(abs(out.at(km,lp+1)[color]-out.at(km,lm)[color]))*2.0f; } } else { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - 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; + if (f.at(k,l-1)!=INSIDE) { + gradI.y=(float)(abs(out.at(km,lm)[color]-out.at(km,lm-1)[color]))*2.0f; } else { gradI.y=0; } @@ -555,7 +556,7 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI))); } w = dst*dir; - Ia[color] += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,k-1,l-1,color)); + Ia[color] += (float)w * (float)(out.at(k-1,l-1)[color]); s[color] += w; } } @@ -563,74 +564,74 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue } } for (color=0; color<=2; color++) { - CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = cv::saturate_cast((double)Ia[color]/s[color]); + out.at(i-1,j-1)[color] = cv::saturate_cast((double)Ia[color]/s[color]); } - CV_MAT_ELEM(*f,uchar,i,j) = BAND; + f.at(i,j) = BAND; Heap->Push(i,j,dist); } } } - } else if (CV_MAT_CN(out->type)==1) { + } else if (out.channels()==1) { while (Heap->Pop(&ii,&jj)) { - CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN; + f.at(ii,jj) = KNOWN; for(q=0; q<4; q++) { if (q==0) {i=ii-1; j=jj;} else if(q==1) {i=ii; j=jj-1;} else if(q==2) {i=ii+1; j=jj;} else if(q==3) {i=ii; j=jj+1;} - if ((i<=0)||(j<=0)||(i>t->rows-1)||(j>t->cols-1)) continue; + if ((i<=0)||(j<=0)||(i>t.rows-1)||(j>t.cols-1)) continue; - if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) { + if (f.at(i,j)==INSIDE) { dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t), FastMarching_solve(i+1,j,i,j-1,f,t), FastMarching_solve(i-1,j,i,j+1,f,t), FastMarching_solve(i+1,j,i,j+1,f,t)); - CV_MAT_ELEM(*t,float,i,j) = dist; + t.at(i,j) = dist; { cv::Point2f gradI,r; float Ia=0,s=1.0e-20f,w,dst,dir; for (k=i-range; k<=i+range; k++) { - int km=k-1+(k==1),kp=k-1-(k==t->rows-2); + int km=k-1+(k==1),kp=k-1-(k==t.rows-2); for (l=j-range; l<=j+range; l++) { - int lm=l-1+(l==1),lp=l-1-(l==t->cols-2); - if (k>0&&l>0&&krows-1&&lcols-1) { - if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&& + int lm=l-1+(l==1),lp=l-1-(l==t.cols-2); + if (k>0&&l>0&&k(k,l)!=INSIDE)&& ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) { r.y=(float)(i-k); r.x=(float)(j-l); dst = 1/(VectorLength(r)*VectorLength(r)+1); - if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm))+ - std::abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm))); + if (f.at(k+1,l)!=INSIDE) { + if (f.at(k-1,l)!=INSIDE) { + gradI.x=(float)(std::abs(out.at(kp+1,lm)-out.at(kp,lm))+ + std::abs(out.at(kp,lm)-out.at(km-1,lm))); } else { - gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp+1,lm)-CV_MAT_ELEM(*out,data_type,kp,lm)))*2.0f; + gradI.x=(float)(std::abs(out.at(kp+1,lm)-out.at(kp,lm)))*2.0f; } } else { - if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) { - gradI.x=(float)(std::abs(CV_MAT_ELEM(*out,data_type,kp,lm)-CV_MAT_ELEM(*out,data_type,km-1,lm)))*2.0f; + if (f.at(k-1,l)!=INSIDE) { + gradI.x=(float)(std::abs(out.at(kp,lm)-out.at(km-1,lm)))*2.0f; } else { gradI.x=0; } } - if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm))+ - std::abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1))); + if (f.at(k,l+1)!=INSIDE) { + if (f.at(k,l-1)!=INSIDE) { + gradI.y=(float)(std::abs(out.at(km,lp+1)-out.at(km,lm))+ + std::abs(out.at(km,lm)-out.at(km,lm-1))); } else { - gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lp+1)-CV_MAT_ELEM(*out,data_type,km,lm)))*2.0f; + gradI.y=(float)(std::abs(out.at(km,lp+1)-out.at(km,lm)))*2.0f; } } else { - if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) { - gradI.y=(float)(std::abs(CV_MAT_ELEM(*out,data_type,km,lm)-CV_MAT_ELEM(*out,data_type,km,lm-1)))*2.0f; + if (f.at(k,l-1)!=INSIDE) { + gradI.y=(float)(std::abs(out.at(km,lm)-out.at(km,lm-1)))*2.0f; } else { gradI.y=0; } @@ -645,16 +646,16 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI))); } w = dst*dir; - Ia += (float)w * (float)(CV_MAT_ELEM(*out,data_type,k-1,l-1)); + Ia += (float)w * (float)(out.at(k-1,l-1)); s += w; } } } } - CV_MAT_ELEM(*out,data_type,i-1,j-1) = cv::saturate_cast((double)Ia/s); + out.at(i-1,j-1) = cv::saturate_cast((double)Ia/s); } - CV_MAT_ELEM(*f,uchar,i,j) = BAND; + f.at(i,j) = BAND; Heap->Push(i,j,dist); } } @@ -665,99 +666,94 @@ icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueue #define SET_BORDER1_C1(image,type,value) {\ int i,j;\ - for(j=0; jcols; j++) {\ - CV_MAT_ELEM(*image,type,0,j) = value;\ + for(j=0; j(0,j) = value;\ }\ - for (i=1; irows-1; i++) {\ - CV_MAT_ELEM(*image,type,i,0) = CV_MAT_ELEM(*image,type,i,image->cols-1) = value;\ + for (i=1; i(i,0) = image.at(i,image.cols-1) = value;\ }\ - for(j=0; jcols; j++) {\ - CV_MAT_ELEM(*image,type,erows-1,j) = value;\ + for(j=0; j(erows-1,j) = value;\ }\ } #define COPY_MASK_BORDER1_C1(src,dst,type) {\ int i,j;\ - for (i=0; irows; i++) {\ - for(j=0; jcols; j++) {\ - if (CV_MAT_ELEM(*src,type,i,j)!=0)\ - CV_MAT_ELEM(*dst,type,i+1,j+1) = INSIDE;\ + for (i=0; i(i,j)!=0)\ + dst.at(i+1,j+1) = INSIDE;\ }\ }\ } static void -icvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_img, +icvInpaint( const Mat &input_img, const Mat &inpaint_mask, Mat &output_img, double inpaintRange, int flags ) { - cv::Ptr mask, band, f, t, out; + cv::Mat mask, band, f, t, out; cv::Ptr Heap, Out; cv::Mat el_range, el_cross; // structuring elements for dilate - CvMat input_hdr, mask_hdr, output_hdr; - CvMat* input_img, *inpaint_mask, *output_img; int range=cvRound(inpaintRange); int erows, ecols; - input_img = cvGetMat( _input_img, &input_hdr ); - inpaint_mask = cvGetMat( _inpaint_mask, &mask_hdr ); - output_img = cvGetMat( _output_img, &output_hdr ); - - if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask)) + if((input_img.size() != output_img.size()) || (input_img.size() != inpaint_mask.size())) CV_Error( cv::Error::StsUnmatchedSizes, "All the input and output images must have the same size" ); - if( (CV_MAT_TYPE(input_img->type) != CV_8U && - CV_MAT_TYPE(input_img->type) != CV_16U && - CV_MAT_TYPE(input_img->type) != CV_32F && - CV_MAT_TYPE(input_img->type) != CV_8UC3) || - !CV_ARE_TYPES_EQ(input_img,output_img) ) + if( (input_img.type() != CV_8U && + input_img.type() != CV_16U && + input_img.type() != CV_32F && + input_img.type() != CV_8UC3) || + (input_img.type() != output_img.type()) ) CV_Error( cv::Error::StsUnsupportedFormat, "8-bit, 16-bit unsigned or 32-bit float 1-channel and 8-bit 3-channel input/output images are supported" ); - if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 ) + if( inpaint_mask.type() != CV_8UC1 ) CV_Error( cv::Error::StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" ); range = MAX(range,1); range = MIN(range,100); - ecols = input_img->cols + 2; - erows = input_img->rows + 2; + ecols = input_img.cols + 2; + erows = input_img.rows + 2; - f.reset(cvCreateMat(erows, ecols, CV_8UC1)); - t.reset(cvCreateMat(erows, ecols, CV_32FC1)); - band.reset(cvCreateMat(erows, ecols, CV_8UC1)); - mask.reset(cvCreateMat(erows, ecols, CV_8UC1)); + f.create(erows, ecols, CV_8UC1); + t.create(erows, ecols, CV_32FC1); + band.create(erows, ecols, CV_8UC1); + mask.create(erows, ecols, CV_8UC1); el_cross = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3, 3), cv::Point(1, 1)); - cvCopy( input_img, output_img ); - cvSet(mask,cvScalar(KNOWN,0,0,0)); + input_img.copyTo( output_img ); + mask.setTo(Scalar(KNOWN,0,0,0)); COPY_MASK_BORDER1_C1(inpaint_mask,mask,uchar); SET_BORDER1_C1(mask,uchar,0); - cvSet(f,cvScalar(KNOWN,0,0,0)); - cvSet(t,cvScalar(1.0e6f,0,0,0)); - cv::dilate(cv::cvarrToMat(mask), cv::cvarrToMat(band), el_cross, cv::Point(1, 1)); + f.setTo(Scalar(KNOWN,0,0,0)); + t.setTo(Scalar(1.0e6f,0,0,0)); + cv::dilate(mask, band, el_cross, cv::Point(1, 1)); Heap=cv::makePtr(); - cvSub(band,mask,band,NULL); + subtract(band, mask, band); SET_BORDER1_C1(band,uchar,0); if (!Heap->Add(band)) return; - cvSet(f,cvScalar(BAND,0,0,0),band); - cvSet(f,cvScalar(INSIDE,0,0,0),mask); - cvSet(t,cvScalar(0,0,0,0),band); + + f.setTo(Scalar(BAND,0,0,0),band); + f.setTo(Scalar(INSIDE,0,0,0),mask); + t.setTo(Scalar(0,0,0,0),band); if( flags == cv::INPAINT_TELEA ) { - out.reset(cvCreateMat(erows, ecols, CV_8UC1)); + out.create(erows, ecols, CV_8UC1); el_range = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2 * range + 1, 2 * range + 1)); - cv::dilate(cv::cvarrToMat(mask), cv::cvarrToMat(out), el_range); - cvSub(out,mask,out,NULL); + cv::dilate(mask, out, el_range); + subtract(out, mask, out); Out=cv::makePtr(); if (!Out->Add(band)) return; - cvSub(out,band,out,NULL); + subtract(out, band, out); SET_BORDER1_C1(out,uchar,0); icvCalcFMM(out,t,Out,true); - switch(CV_MAT_DEPTH(output_img->type)) + switch(output_img.depth()) { case CV_8U: icvTeleaInpaintFMM(mask,t,output_img,range,Heap); @@ -773,7 +769,7 @@ icvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_ } } else if (flags == cv::INPAINT_NS) { - switch(CV_MAT_DEPTH(output_img->type)) + switch(output_img.depth()) { case CV_8U: icvNSInpaintFMM(mask,t,output_img,range,Heap); @@ -788,7 +784,7 @@ icvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_ CV_Error( cv::Error::StsBadArg, "Unsupported format of the input image" ); } } else { - CV_Error( cv::Error::StsBadArg, "The flags argument must be one of CV_INPAINT_TELEA or CV_INPAINT_NS" ); + CV_Error( cv::Error::StsBadArg, "The flags argument must be one of INPAINT_TELEA or INPAINT_NS" ); } } @@ -800,6 +796,5 @@ void cv::inpaint( InputArray _src, InputArray _mask, OutputArray _dst, Mat src = _src.getMat(), mask = _mask.getMat(); _dst.create( src.size(), src.type() ); Mat dst = _dst.getMat(); - CvMat c_src = cvMat(src), c_mask = cvMat(mask), c_dst = cvMat(dst); - icvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags ); + icvInpaint( src, mask, dst, inpaintRange, flags ); }