DepthInpainter.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. #include "DepthInpainter.hpp"
  2. #include <stdint.h>
  3. #include <opencv2/opencv.hpp>
  4. #ifndef CV_VERSION_EPOCH
  5. #if defined (CV_MAJOR_VERSION) && (CV_VERSION_MAJOR == 4)
  6. #include <opencv2/imgproc/types_c.h>
  7. #include <opencv2/imgproc/imgproc_c.h>
  8. #include <opencv2/photo/legacy/constants_c.h>
  9. #include <opencv2/imgcodecs/legacy/constants_c.h>
  10. #endif
  11. #endif
  12. using namespace cv;
  13. #undef CV_MAT_ELEM_PTR_FAST
  14. #define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size ) \
  15. ((mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col))
  16. inline float
  17. min4( float a, float b, float c, float d )
  18. {
  19. a = MIN(a,b);
  20. c = MIN(c,d);
  21. return MIN(a,c);
  22. }
  23. #define CV_MAT_3COLOR_ELEM(img,type,y,x,c) CV_MAT_ELEM(img,type,y,(x)*3+(c))
  24. #define KNOWN 0 //known outside narrow band
  25. #define BAND 1 //narrow band (known)
  26. #define INSIDE 2 //unknown
  27. #define CHANGE 3 //servise
  28. typedef struct CvHeapElem
  29. {
  30. float T;
  31. int i,j;
  32. struct CvHeapElem* prev;
  33. struct CvHeapElem* next;
  34. }
  35. CvHeapElem;
  36. class CvPriorityQueueFloat
  37. {
  38. protected:
  39. CvHeapElem *mem,*empty,*head,*tail;
  40. int num,in;
  41. public:
  42. bool Init( const CvMat* f )
  43. {
  44. int i,j;
  45. for( i = num = 0; i < f->rows; i++ )
  46. {
  47. for( j = 0; j < f->cols; j++ )
  48. num += CV_MAT_ELEM(*f,uchar,i,j)!=0;
  49. }
  50. if (num<=0) return false;
  51. mem = (CvHeapElem*)cvAlloc((num+2)*sizeof(CvHeapElem));
  52. if (mem==NULL) return false;
  53. head = mem;
  54. head->i = head->j = -1;
  55. head->prev = NULL;
  56. head->next = mem+1;
  57. head->T = -FLT_MAX;
  58. empty = mem+1;
  59. for (i=1; i<=num; i++) {
  60. mem[i].prev = mem+i-1;
  61. mem[i].next = mem+i+1;
  62. mem[i].i = -1;
  63. mem[i].T = FLT_MAX;
  64. }
  65. tail = mem+i;
  66. tail->i = tail->j = -1;
  67. tail->prev = mem+i-1;
  68. tail->next = NULL;
  69. tail->T = FLT_MAX;
  70. return true;
  71. }
  72. bool Add(const CvMat* f) {
  73. int i,j;
  74. for (i=0; i<f->rows; i++) {
  75. for (j=0; j<f->cols; j++) {
  76. if (CV_MAT_ELEM(*f,uchar,i,j)!=0) {
  77. if (!Push(i,j,0)) return false;
  78. }
  79. }
  80. }
  81. return true;
  82. }
  83. bool Push(int i, int j, float T) {
  84. CvHeapElem *tmp=empty,*add=empty;
  85. if (empty==tail) return false;
  86. while (tmp->prev->T>T) tmp = tmp->prev;
  87. if (tmp!=empty) {
  88. add->prev->next = add->next;
  89. add->next->prev = add->prev;
  90. empty = add->next;
  91. add->prev = tmp->prev;
  92. add->next = tmp;
  93. add->prev->next = add;
  94. add->next->prev = add;
  95. } else {
  96. empty = empty->next;
  97. }
  98. add->i = i;
  99. add->j = j;
  100. add->T = T;
  101. in++;
  102. // printf("push i %3d j %3d T %12.4e in %4d\n",i,j,T,in);
  103. return true;
  104. }
  105. bool Pop(int *i, int *j) {
  106. CvHeapElem *tmp=head->next;
  107. if (empty==tmp) return false;
  108. *i = tmp->i;
  109. *j = tmp->j;
  110. tmp->prev->next = tmp->next;
  111. tmp->next->prev = tmp->prev;
  112. tmp->prev = empty->prev;
  113. tmp->next = empty;
  114. tmp->prev->next = tmp;
  115. tmp->next->prev = tmp;
  116. empty = tmp;
  117. in--;
  118. // printf("pop i %3d j %3d T %12.4e in %4d\n",tmp->i,tmp->j,tmp->T,in);
  119. return true;
  120. }
  121. bool Pop(int *i, int *j, float *T) {
  122. CvHeapElem *tmp=head->next;
  123. if (empty==tmp) return false;
  124. *i = tmp->i;
  125. *j = tmp->j;
  126. *T = tmp->T;
  127. tmp->prev->next = tmp->next;
  128. tmp->next->prev = tmp->prev;
  129. tmp->prev = empty->prev;
  130. tmp->next = empty;
  131. tmp->prev->next = tmp;
  132. tmp->next->prev = tmp;
  133. empty = tmp;
  134. in--;
  135. // printf("pop i %3d j %3d T %12.4e in %4d\n",tmp->i,tmp->j,tmp->T,in);
  136. return true;
  137. }
  138. CvPriorityQueueFloat(void) {
  139. num=in=0;
  140. mem=empty=head=tail=NULL;
  141. }
  142. ~CvPriorityQueueFloat(void)
  143. {
  144. cvFree( &mem );
  145. }
  146. };
  147. inline float VectorScalMult(CvPoint2D32f v1,CvPoint2D32f v2) {
  148. return v1.x*v2.x+v1.y*v2.y;
  149. }
  150. inline float VectorLength(CvPoint2D32f v1) {
  151. return v1.x*v1.x+v1.y*v1.y;
  152. }
  153. ///////////////////////////////////////////////////////////////////////////////////////////
  154. //HEAP::iterator Heap_Iterator;
  155. //HEAP Heap;
  156. static float FastMarching_solve(int i1,int j1,int i2,int j2, const CvMat* f, const CvMat* t)
  157. {
  158. double sol, a11, a22, m12;
  159. a11=CV_MAT_ELEM(*t,float,i1,j1);
  160. a22=CV_MAT_ELEM(*t,float,i2,j2);
  161. m12=MIN(a11,a22);
  162. if( CV_MAT_ELEM(*f,uchar,i1,j1) != INSIDE )
  163. if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
  164. if( fabs(a11-a22) >= 1.0 )
  165. sol = 1+m12;
  166. else
  167. sol = (a11+a22+sqrt((double)(2-(a11-a22)*(a11-a22))))*0.5;
  168. else
  169. sol = 1+a11;
  170. else if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
  171. sol = 1+a22;
  172. else
  173. sol = 1+m12;
  174. return (float)sol;
  175. }
  176. /////////////////////////////////////////////////////////////////////////////////////
  177. static void
  178. icvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) {
  179. int i, j, ii = 0, jj = 0, q;
  180. float dist;
  181. while (Heap->Pop(&ii,&jj)) {
  182. unsigned known=(negate)?CHANGE:KNOWN;
  183. CV_MAT_ELEM(*f,uchar,ii,jj) = (uchar)known;
  184. for (q=0; q<4; q++) {
  185. i=0; j=0;
  186. if (q==0) {i=ii-1; j=jj;}
  187. else if(q==1) {i=ii; j=jj-1;}
  188. else if(q==2) {i=ii+1; j=jj;}
  189. else {i=ii; j=jj+1;}
  190. if ((i<=0)||(j<=0)||(i>f->rows)||(j>f->cols)) continue;
  191. if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
  192. dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
  193. FastMarching_solve(i+1,j,i,j-1,f,t),
  194. FastMarching_solve(i-1,j,i,j+1,f,t),
  195. FastMarching_solve(i+1,j,i,j+1,f,t));
  196. CV_MAT_ELEM(*t,float,i,j) = dist;
  197. CV_MAT_ELEM(*f,uchar,i,j) = BAND;
  198. Heap->Push(i,j,dist);
  199. }
  200. }
  201. }
  202. if (negate) {
  203. for (i=0; i<f->rows; i++) {
  204. for(j=0; j<f->cols; j++) {
  205. if (CV_MAT_ELEM(*f,uchar,i,j) == CHANGE) {
  206. CV_MAT_ELEM(*f,uchar,i,j) = KNOWN;
  207. CV_MAT_ELEM(*t,float,i,j) = -CV_MAT_ELEM(*t,float,i,j);
  208. }
  209. }
  210. }
  211. }
  212. }
  213. static void
  214. icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap ) {
  215. int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
  216. float dist;
  217. if (CV_MAT_CN(out->type)==1) {
  218. while (Heap->Pop(&ii,&jj)) {
  219. CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
  220. for(q=0; q<4; q++) {
  221. if (q==0) {i=ii-1; j=jj;}
  222. else if(q==1) {i=ii; j=jj-1;}
  223. else if(q==2) {i=ii+1; j=jj;}
  224. else if(q==3) {i=ii; j=jj+1;}
  225. if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
  226. if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
  227. dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
  228. FastMarching_solve(i+1,j,i,j-1,f,t),
  229. FastMarching_solve(i-1,j,i,j+1,f,t),
  230. FastMarching_solve(i+1,j,i,j+1,f,t));
  231. CV_MAT_ELEM(*t,float,i,j) = dist;
  232. for (color=0; color<=0; color++) {
  233. CvPoint2D32f gradI,gradT,r;
  234. float Ia=0,Jx=0,Jy=0,s=1.0e-20f,w,dst,lev,dir,sat;
  235. if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) {
  236. if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
  237. gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f;
  238. } else {
  239. gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j)));
  240. }
  241. } else {
  242. if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
  243. gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1)));
  244. } else {
  245. gradT.x=0;
  246. }
  247. }
  248. if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) {
  249. if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
  250. gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f;
  251. } else {
  252. gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j)));
  253. }
  254. } else {
  255. if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
  256. gradT.y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j)));
  257. } else {
  258. gradT.y=0;
  259. }
  260. }
  261. for (k=i-range; k<=i+range; k++) {
  262. int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
  263. for (l=j-range; l<=j+range; l++) {
  264. int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
  265. if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
  266. if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
  267. ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
  268. r.y = (float)(i-k);
  269. r.x = (float)(j-l);
  270. dst = (float)(1./(VectorLength(r)*sqrt(VectorLength(r))));
  271. lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j))));
  272. dir=VectorScalMult(r,gradT);
  273. if (fabs(dir)<=0.01) dir=0.000001f;
  274. w = (float)fabs(dst*lev*dir);
  275. if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
  276. if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
  277. // gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm-1)))*2.0f;
  278. gradI.x=(float)((CV_MAT_ELEM(*out,uint16_t,km,lp+1)-CV_MAT_ELEM(*out,uint16_t,km,lm-1)))*2.0f;
  279. } else {
  280. // gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm)));
  281. gradI.x=(float)((CV_MAT_ELEM(*out,uint16_t,km,lp+1)-CV_MAT_ELEM(*out,uint16_t,km,lm)));
  282. }
  283. } else {
  284. if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
  285. // gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp)-CV_MAT_ELEM(*out,uchar,km,lm-1)));
  286. gradI.x=(float)((CV_MAT_ELEM(*out,uint16_t,km,lp)-CV_MAT_ELEM(*out,uint16_t,km,lm-1)));
  287. } else {
  288. gradI.x=0;
  289. }
  290. }
  291. if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
  292. if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
  293. // gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)))*2.0f;
  294. gradI.y=(float)((CV_MAT_ELEM(*out,uint16_t,kp+1,lm)-CV_MAT_ELEM(*out,uint16_t,km-1,lm)))*2.0f;
  295. } else {
  296. // gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,km,lm)));
  297. gradI.y=(float)((CV_MAT_ELEM(*out,uint16_t,kp+1,lm)-CV_MAT_ELEM(*out,uint16_t,km,lm)));
  298. }
  299. } else {
  300. if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
  301. // gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)));
  302. gradI.y=(float)((CV_MAT_ELEM(*out,uint16_t,kp,lm)-CV_MAT_ELEM(*out,uint16_t,km-1,lm)));
  303. } else {
  304. gradI.y=0;
  305. }
  306. }
  307. // Ia += (float)w * (float)(CV_MAT_ELEM(*out,uchar,km,lm));
  308. Ia += (float)w * (float)(CV_MAT_ELEM(*out,uint16_t,km,lm));
  309. Jx -= (float)w * (float)(gradI.x*r.x);
  310. Jy -= (float)w * (float)(gradI.y*r.y);
  311. s += w;
  312. }
  313. }
  314. }
  315. }
  316. sat = (float)((Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)+0.5f));
  317. {
  318. // CV_MAT_ELEM(*out,uchar,i-1,j-1) = cv::saturate_cast<uchar>(sat);
  319. CV_MAT_ELEM(*out,uint16_t,i-1,j-1) = cv::saturate_cast<uint16_t>(sat);
  320. }
  321. }
  322. CV_MAT_ELEM(*f,uchar,i,j) = BAND;
  323. Heap->Push(i,j,dist);
  324. }
  325. }
  326. }
  327. }
  328. }
  329. static void
  330. icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap) {
  331. int i = 0, j = 0, ii = 0, jj = 0, k, l, q;
  332. float dist;
  333. if (CV_MAT_CN(out->type)==1) {
  334. while (Heap->Pop(&ii,&jj)) {
  335. CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
  336. for(q=0; q<4; q++) {
  337. if (q==0) {i=ii-1; j=jj;}
  338. else if(q==1) {i=ii; j=jj-1;}
  339. else if(q==2) {i=ii+1; j=jj;}
  340. else if(q==3) {i=ii; j=jj+1;}
  341. if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
  342. if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
  343. dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
  344. FastMarching_solve(i+1,j,i,j-1,f,t),
  345. FastMarching_solve(i-1,j,i,j+1,f,t),
  346. FastMarching_solve(i+1,j,i,j+1,f,t));
  347. CV_MAT_ELEM(*t,float,i,j) = dist;
  348. {
  349. CvPoint2D32f gradI,r;
  350. float Ia=0,s=1.0e-20f,w,dst,dir;
  351. for (k=i-range; k<=i+range; k++) {
  352. int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
  353. for (l=j-range; l<=j+range; l++) {
  354. int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
  355. if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
  356. if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
  357. ((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
  358. r.y=(float)(i-k);
  359. r.x=(float)(j-l);
  360. dst = 1/(VectorLength(r)*VectorLength(r)+1);
  361. if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
  362. if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
  363. // gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,kp,lm))+
  364. // abs(CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)));
  365. gradI.x=(float)(abs(CV_MAT_ELEM(*out,uint16_t,kp+1,lm)-CV_MAT_ELEM(*out,uint16_t,kp,lm))+
  366. abs(CV_MAT_ELEM(*out,uint16_t,kp,lm)-CV_MAT_ELEM(*out,uint16_t,km-1,lm)));
  367. } else {
  368. // gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,kp,lm)))*2.0f;
  369. gradI.x=(float)(abs(CV_MAT_ELEM(*out,uint16_t,kp+1,lm)-CV_MAT_ELEM(*out,uint16_t,kp,lm)))*2.0f;
  370. }
  371. } else {
  372. if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
  373. // gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)))*2.0f;
  374. gradI.x=(float)(abs(CV_MAT_ELEM(*out,uint16_t,kp,lm)-CV_MAT_ELEM(*out,uint16_t,km-1,lm)))*2.0f;
  375. } else {
  376. gradI.x=0;
  377. }
  378. }
  379. if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
  380. if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
  381. // gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm))+
  382. // abs(CV_MAT_ELEM(*out,uchar,km,lm)-CV_MAT_ELEM(*out,uchar,km,lm-1)));
  383. gradI.y=(float)(abs(CV_MAT_ELEM(*out,uint16_t,km,lp+1)-CV_MAT_ELEM(*out,uint16_t,km,lm))+
  384. abs(CV_MAT_ELEM(*out,uint16_t,km,lm)-CV_MAT_ELEM(*out,uint16_t,km,lm-1)));
  385. } else {
  386. // gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm)))*2.0f;
  387. gradI.y=(float)(abs(CV_MAT_ELEM(*out,uint16_t,km,lp+1)-CV_MAT_ELEM(*out,uint16_t,km,lm)))*2.0f;
  388. }
  389. } else {
  390. if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
  391. // gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lm)-CV_MAT_ELEM(*out,uchar,km,lm-1)))*2.0f;
  392. gradI.y=(float)(abs(CV_MAT_ELEM(*out,uint16_t,km,lm)-CV_MAT_ELEM(*out,uint16_t,km,lm-1)))*2.0f;
  393. } else {
  394. gradI.y=0;
  395. }
  396. }
  397. gradI.x=-gradI.x;
  398. dir=VectorScalMult(r,gradI);
  399. if (fabs(dir)<=0.01) {
  400. dir=0.000001f;
  401. } else {
  402. dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI)));
  403. }
  404. w = dst*dir;
  405. // Ia += (float)w * (float)(CV_MAT_ELEM(*out,uchar,km,lm));
  406. Ia += (float)w * (float)(CV_MAT_ELEM(*out,uint16_t,km,lm));
  407. s += w;
  408. }
  409. }
  410. }
  411. }
  412. // CV_MAT_ELEM(*out,uchar,i-1,j-1) = cv::saturate_cast<uchar>((double)Ia/s);
  413. CV_MAT_ELEM(*out,uint16_t,i-1,j-1) = cv::saturate_cast<uint16_t>((double)Ia/s);
  414. }
  415. CV_MAT_ELEM(*f,uchar,i,j) = BAND;
  416. Heap->Push(i,j,dist);
  417. }
  418. }
  419. }
  420. }
  421. }
  422. #define SET_BORDER1_C1(image,type,value) {\
  423. int i,j;\
  424. for(j=0; j<image->cols; j++) {\
  425. CV_MAT_ELEM(*image,type,0,j) = value;\
  426. }\
  427. for (i=1; i<image->rows-1; i++) {\
  428. CV_MAT_ELEM(*image,type,i,0) = CV_MAT_ELEM(*image,type,i,image->cols-1) = value;\
  429. }\
  430. for(j=0; j<image->cols; j++) {\
  431. CV_MAT_ELEM(*image,type,erows-1,j) = value;\
  432. }\
  433. }
  434. #define COPY_MASK_BORDER1_C1(src,dst,type) {\
  435. int i,j;\
  436. for (i=0; i<src->rows; i++) {\
  437. for(j=0; j<src->cols; j++) {\
  438. if (CV_MAT_ELEM(*src,type,i,j)!=0)\
  439. CV_MAT_ELEM(*dst,type,i+1,j+1) = INSIDE;\
  440. }\
  441. }\
  442. }
  443. void
  444. _cvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_img,
  445. double inpaintRange, int flags )
  446. {
  447. cv::Ptr<CvMat> mask, band, f, t, out;
  448. cv::Ptr<CvPriorityQueueFloat> Heap, Out;
  449. IplConvKernel *el_cross, *el_range;
  450. CvMat input_hdr, mask_hdr, output_hdr;
  451. CvMat* input_img, *inpaint_mask, *output_img;
  452. int range=cvRound(inpaintRange);
  453. int erows, ecols;
  454. input_img = cvGetMat( _input_img, &input_hdr );
  455. inpaint_mask = cvGetMat( _inpaint_mask, &mask_hdr );
  456. output_img = cvGetMat( _output_img, &output_hdr );
  457. if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask))
  458. CV_Error( CV_StsUnmatchedSizes, "All the input and output images must have the same size" );
  459. if( (CV_MAT_TYPE(input_img->type) != CV_16UC1) ||
  460. !CV_ARE_TYPES_EQ(input_img,output_img) )
  461. CV_Error( CV_StsUnsupportedFormat,
  462. "Only 8-bit 1-channel and 3-channel input/output images are supported" );
  463. if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 )
  464. CV_Error( CV_StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" );
  465. range = MAX(range,1);
  466. range = MIN(range,100);
  467. ecols = input_img->cols + 2;
  468. erows = input_img->rows + 2;
  469. f = cvCreateMat(erows, ecols, CV_8UC1);
  470. t = cvCreateMat(erows, ecols, CV_32FC1);
  471. band = cvCreateMat(erows, ecols, CV_8UC1);
  472. mask = cvCreateMat(erows, ecols, CV_8UC1);
  473. el_cross = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL);
  474. cvCopy( input_img, output_img );
  475. cvSet(mask,cvScalar(KNOWN,0,0,0));
  476. COPY_MASK_BORDER1_C1(inpaint_mask,mask,uchar);
  477. SET_BORDER1_C1(mask,uchar,0);
  478. cvSet(f,cvScalar(KNOWN,0,0,0));
  479. cvSet(t,cvScalar(1.0e6f,0,0,0));
  480. cvDilate(mask,band,el_cross,1); // image with narrow band
  481. cvReleaseStructuringElement(&el_cross);
  482. Heap=new CvPriorityQueueFloat;
  483. if (!Heap->Init(band))
  484. return;
  485. cvSub(band,mask,band,NULL);
  486. SET_BORDER1_C1(band,uchar,0);
  487. if (!Heap->Add(band))
  488. return;
  489. cvSet(f,cvScalar(BAND,0,0,0),band);
  490. cvSet(f,cvScalar(INSIDE,0,0,0),mask);
  491. cvSet(t,cvScalar(0,0,0,0),band);
  492. if( flags == CV_INPAINT_TELEA )
  493. {
  494. out = cvCreateMat(erows, ecols, CV_8UC1);
  495. el_range = cvCreateStructuringElementEx(2*range+1,2*range+1,
  496. range,range,CV_SHAPE_RECT,NULL);
  497. cvDilate(mask,out,el_range,1);
  498. cvReleaseStructuringElement(&el_range);
  499. cvSub(out,mask,out,NULL);
  500. Out=new CvPriorityQueueFloat;
  501. if (!Out->Init(out))
  502. return;
  503. if (!Out->Add(band))
  504. return;
  505. cvSub(out,band,out,NULL);
  506. SET_BORDER1_C1(out,uchar,0);
  507. icvCalcFMM(out,t,Out,true);
  508. icvTeleaInpaintFMM(mask,t,output_img,range,Heap);
  509. }
  510. else if (flags == CV_INPAINT_NS) {
  511. icvNSInpaintFMM(mask,t,output_img,range,Heap);
  512. } else {
  513. CV_Error( CV_StsBadArg, "The flags argument must be one of CV_INPAINT_TELEA or CV_INPAINT_NS" );
  514. }
  515. }
  516. CvMat ToCvMat(const cv::Mat& m)
  517. {
  518. CV_DbgAssert(m.dims <= 2);
  519. CvMat dst = cvMat(m.rows, m.dims == 1 ? 1 : m.cols, m.type(), m.data);
  520. dst.step = (int)m.step[0];
  521. dst.type = (dst.type & ~cv::Mat::CONTINUOUS_FLAG) | (m.flags & cv::Mat::CONTINUOUS_FLAG);
  522. return dst;
  523. }
  524. void _inpaint( InputArray _src, InputArray _mask, OutputArray _dst,
  525. double inpaintRange, int flags )
  526. {
  527. Mat src = _src.getMat(), mask = _mask.getMat();
  528. _dst.create( src.size(), src.type() );
  529. CvMat c_src = ToCvMat(src), c_mask = ToCvMat(mask), c_dst = ToCvMat(_dst.getMat());
  530. _cvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags );
  531. }
  532. //////////////////////////////////////////////////////////////////////////////////////
  533. cv::Mat DepthInpainter::genValidMask(const cv::Mat& depth)
  534. {
  535. cv::Mat orgMask = (depth == 0);
  536. // cv::Mat mask = orgMask.clone();
  537. cv::Mat mask = orgMask;
  538. cv::Mat kernel = cv::Mat::zeros(_kernelSize, _kernelSize, CV_8U);
  539. cv::circle(kernel, cv::Point(kernel.cols/2, kernel.rows/2), kernel.rows/2, cv::Scalar(255), -1);
  540. cv::erode(orgMask, mask, kernel);
  541. cv::dilate(mask, mask, kernel);
  542. gSpeckleFilter.Compute(mask, 0, _maxInternalHoleToBeFilled, 1);
  543. // revert mask
  544. mask = mask == 0;
  545. return mask;
  546. }
  547. void DepthInpainter::inpaint(const cv::Mat& depth, cv::Mat& out, const cv::Mat& mask)
  548. {
  549. cv::Mat newDepth;
  550. cv::Mat _mask = mask.empty() ? (depth == 0) : mask;
  551. if(depth.type() == CV_8U || depth.type() == CV_8UC3){
  552. cv::inpaint(depth, _mask, newDepth, _inpaintRadius, cv::INPAINT_TELEA);
  553. } else if(depth.type() == CV_16U){
  554. _inpaint(depth, _mask, newDepth, _inpaintRadius, cv::INPAINT_TELEA);
  555. }
  556. if(mask.empty() && !_fillAll){
  557. // gen masked image
  558. cv::Mat mask = genValidMask(depth);
  559. out = cv::Mat::zeros(depth.size(), CV_16U);
  560. newDepth.copyTo(out, mask);
  561. } else {
  562. out = newDepth;
  563. }
  564. }