1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2012, Willow Garage Inc., all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The names of the copyright holders may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
42 /*******************************************************************************************
44 The LogPolar Blind Spot Model code has been contributed by Fabio Solari and Manuela Chessa.
46 More details can be found in:
48 M. Chessa, S. P. Sabatini, F. Solari and F. Tatti (2011)
49 A Quantitative Comparison of Speed and Reliability for Log-Polar Mapping Techniques,
50 Computer Vision Systems - 8th International Conference,
51 ICVS 2011, Sophia Antipolis, France, September 20-22, 2011
52 (http://dx.doi.org/10.1007/978-3-642-23968-7_5)
54 ********************************************************************************************/
56 #include "precomp.hpp"
64 //------------------------------------interp-------------------------------------------
65 LogPolar_Interp::LogPolar_Interp(int w, int h, Point2i center, int _R, double _ro0, int _interp, int full, int _s, int sp)
67 if ( (center.x!=w/2 || center.y!=h/2) && full==0) full=1;
69 if (center.x<0) center.x=0;
70 if (center.y<0) center.y=0;
71 if (center.x>=w) center.x=w-1;
72 if (center.y>=h) center.y=h-1;
77 if (center.x<=w/2 && center.y>=h/2)
78 rtmp=(int)std::sqrt((float)center.y*center.y + (float)(w-center.x)*(w-center.x));
79 else if (center.x>=w/2 && center.y>=h/2)
80 rtmp=(int)std::sqrt((float)center.y*center.y + (float)center.x*center.x);
81 else if (center.x>=w/2 && center.y<=h/2)
82 rtmp=(int)std::sqrt((float)(h-center.y)*(h-center.y) + (float)center.x*center.x);
83 else //if (center.x<=w/2 && center.y<=h/2)
84 rtmp=(int)std::sqrt((float)(h-center.y)*(h-center.y) + (float)(w-center.x)*(w-center.x));
89 bottom = M/2 - (h-center.y);
90 left = M/2 - center.x;
91 right = M/2 - (w - center.x);
94 top=bottom=left=right=0;
99 int jc=M/2-1, ic=N/2-1;
100 int _romax=std::min(ic, jc);
101 double _a=std::exp(std::log((double)(_romax/2-1)/(double)ro0)/(double)R);
102 S=(int) floor(2*CV_PI/(_a-1)+0.5);
107 create_map(M, N, _R, _s, _ro0);
110 void LogPolar_Interp::create_map(int _M, int _n, int _R, int _s, double _ro0)
118 int jc=N/2-1, ic=M/2-1;
119 romax=std::min(ic, jc);
120 a=std::exp(std::log((double)romax/(double)ro0)/(double)R);
121 q=((double)S)/(2*CV_PI);
123 Rsri = Mat::zeros(S,R,CV_32FC1);
124 Csri = Mat::zeros(S,R,CV_32FC1);
125 ETAyx = Mat::zeros(N,M,CV_32FC1);
126 CSIyx = Mat::zeros(N,M,CV_32FC1);
128 for(int v=0; v<S; v++)
130 for(int u=0; u<R; u++)
132 Rsri.at<float>(v,u)=(float)(ro0*std::pow(a,u)*sin(v/q)+jc);
133 Csri.at<float>(v,u)=(float)(ro0*std::pow(a,u)*cos(v/q)+ic);
137 for(int j=0; j<N; j++)
139 for(int i=0; i<M; i++)
143 theta=atan((double)(j-jc)/(double)(i-ic));
145 theta=atan((double)(j-jc)/(double)(i-ic))+CV_PI;
150 ETAyx.at<float>(j,i)=(float)(q*theta);
152 double ro2=(j-jc)*(j-jc)+(i-ic)*(i-ic);
153 CSIyx.at<float>(j,i)=(float)(0.5*std::log(ro2/(ro0*ro0))/std::log(a));
158 const Mat LogPolar_Interp::to_cortical(const Mat &source)
160 Mat out(S,R,CV_8UC1,Scalar(0));
163 copyMakeBorder(source,source_border,top,bottom,left,right,BORDER_CONSTANT,Scalar(0));
165 remap(source_border,out,Csri,Rsri,interp);
171 const Mat LogPolar_Interp::to_cartesian(const Mat &source)
173 Mat out(N,M,CV_8UC1,Scalar(0));
177 if (interp==INTER_NEAREST || interp==INTER_LINEAR){
178 copyMakeBorder(source,source_border,0,1,0,0,BORDER_CONSTANT,Scalar(0));
179 Mat rowS0 = source_border.row(S);
180 source_border.row(0).copyTo(rowS0);
181 } else if (interp==INTER_CUBIC){
182 copyMakeBorder(source,source_border,0,2,0,0,BORDER_CONSTANT,Scalar(0));
183 Mat rowS0 = source_border.row(S);
184 Mat rowS1 = source_border.row(S+1);
185 source_border.row(0).copyTo(rowS0);
186 source_border.row(1).copyTo(rowS1);
187 } else if (interp==INTER_LANCZOS4){
188 copyMakeBorder(source,source_border,0,4,0,0,BORDER_CONSTANT,Scalar(0));
189 Mat rowS0 = source_border.row(S);
190 Mat rowS1 = source_border.row(S+1);
191 Mat rowS2 = source_border.row(S+2);
192 Mat rowS3 = source_border.row(S+3);
193 source_border.row(0).copyTo(rowS0);
194 source_border.row(1).copyTo(rowS1);
195 source_border.row(2).copyTo(rowS2);
196 source_border.row(3).copyTo(rowS3);
198 remap(source_border,out,CSIyx,ETAyx,interp);
200 Mat out_cropped=out(Range(top,N-1-bottom),Range(left,M-1-right));
205 LogPolar_Interp::~LogPolar_Interp()
209 //------------------------------------overlapping----------------------------------
211 LogPolar_Overlapping::LogPolar_Overlapping(int w, int h, Point2i center, int _R, double _ro0, int full, int _s, int sp)
213 if ( (center.x!=w/2 || center.y!=h/2) && full==0) full=1;
215 if (center.x<0) center.x=0;
216 if (center.y<0) center.y=0;
217 if (center.x>=w) center.x=w-1;
218 if (center.y>=h) center.y=h-1;
223 if (center.x<=w/2 && center.y>=h/2)
224 rtmp=(int)std::sqrt((float)center.y*center.y + (float)(w-center.x)*(w-center.x));
225 else if (center.x>=w/2 && center.y>=h/2)
226 rtmp=(int)std::sqrt((float)center.y*center.y + (float)center.x*center.x);
227 else if (center.x>=w/2 && center.y<=h/2)
228 rtmp=(int)std::sqrt((float)(h-center.y)*(h-center.y) + (float)center.x*center.x);
229 else //if (center.x<=w/2 && center.y<=h/2)
230 rtmp=(int)std::sqrt((float)(h-center.y)*(h-center.y) + (float)(w-center.x)*(w-center.x));
234 top = M/2 - center.y;
235 bottom = M/2 - (h-center.y);
236 left = M/2 - center.x;
237 right = M/2 - (w - center.x);
240 top=bottom=left=right=0;
246 int jc=M/2-1, ic=N/2-1;
247 int _romax=std::min(ic, jc);
248 double _a=std::exp(std::log((double)(_romax/2-1)/(double)ro0)/(double)R);
249 S=(int) floor(2*CV_PI/(_a-1)+0.5);
252 create_map(M, N, _R, _s, _ro0);
255 void LogPolar_Overlapping::create_map(int _M, int _n, int _R, int _s, double _ro0)
263 int jc=N/2-1, ic=M/2-1;
264 romax=std::min(ic, jc);
265 a=std::exp(std::log((double)romax/(double)ro0)/(double)R);
266 q=((double)S)/(2*CV_PI);
269 Rsri=Mat::zeros(S,R,CV_32FC1);
270 Csri=Mat::zeros(S,R,CV_32FC1);
271 ETAyx=Mat::zeros(N,M,CV_32FC1);
272 CSIyx=Mat::zeros(N,M,CV_32FC1);
276 w_ker_2D.resize(R*S);
278 for(int v=0; v<S; v++)
280 for(int u=0; u<R; u++)
282 Rsri.at<float>(v,u)=(float)(ro0*std::pow(a,u)*sin(v/q)+jc);
283 Csri.at<float>(v,u)=(float)(ro0*std::pow(a,u)*cos(v/q)+ic);
284 Rsr[v*R+u]=(int)floor(Rsri.at<float>(v,u));
285 Csr[v*R+u]=(int)floor(Csri.at<float>(v,u));
291 for(int i=0; i<R; i++)
293 Wsr[i]=ro0*(a-1)*std::pow(a,i-1);
294 if((Wsr[i]>1)&&(done==false))
301 for(int j=0; j<N; j++)
303 for(int i=0; i<M; i++)//mdf
307 theta=atan((double)(j-jc)/(double)(i-ic));
309 theta=atan((double)(j-jc)/(double)(i-ic))+CV_PI;
314 ETAyx.at<float>(j,i)=(float)(q*theta);
316 double ro2=(j-jc)*(j-jc)+(i-ic)*(i-ic);
317 CSIyx.at<float>(j,i)=(float)(0.5*std::log(ro2/(ro0*ro0))/std::log(a));
321 for(int v=0; v<S; v++)
322 for(int u=ind1; u<R; u++)
324 //double sigma=Wsr[u]/2.0;
325 double sigma=Wsr[u]/3.0;//modf
326 int w=(int) floor(3*sigma+0.5);
328 w_ker_2D[v*R+u].weights.resize((2*w+1)*(2*w+1));
329 double dx=Csri.at<float>(v,u)-Csr[v*R+u];
330 double dy=Rsri.at<float>(v,u)-Rsr[v*R+u];
332 for(int j=0; j<2*w+1; j++)
333 for(int i=0; i<2*w+1; i++)
335 (w_ker_2D[v*R+u].weights)[j*(2*w+1)+i]=std::exp(-(std::pow(i-w-dx, 2)+std::pow(j-w-dy, 2))/(2*sigma*sigma));
336 tot+=(w_ker_2D[v*R+u].weights)[j*(2*w+1)+i];
338 for(int j=0; j<(2*w+1); j++)
339 for(int i=0; i<(2*w+1); i++)
340 (w_ker_2D[v*R+u].weights)[j*(2*w+1)+i]/=tot;
344 const Mat LogPolar_Overlapping::to_cortical(const Mat &source)
346 Mat out(S,R,CV_8UC1,Scalar(0));
349 copyMakeBorder(source,source_border,top,bottom,left,right,BORDER_CONSTANT,Scalar(0));
351 remap(source_border,out,Csri,Rsri,INTER_LINEAR);
353 int wm=w_ker_2D[R-1].w;
354 std::vector<int> IMG((M+2*wm+1)*(N+2*wm+1), 0);
356 for(int j=0; j<N; j++)
357 for(int i=0; i<M; i++)
358 IMG[(M+2*wm+1)*(j+wm)+i+wm]=source_border.at<uchar>(j,i);
360 for(int v=0; v<S; v++)
361 for(int u=ind1; u<R; u++)
363 int w=w_ker_2D[v*R+u].w;
365 for(int rf=0; rf<(2*w+1); rf++)
367 for(int cf=0; cf<(2*w+1); cf++)
369 double weight=(w_ker_2D[v*R+u]).weights[rf*(2*w+1)+cf];
370 tmp+=IMG[(M+2*wm+1)*((rf-w)+Rsr[v*R+u]+wm)+((cf-w)+Csr[v*R+u]+wm)]*weight;
373 out.at<uchar>(v,u)=(uchar) floor(tmp+0.5);
379 const Mat LogPolar_Overlapping::to_cartesian(const Mat &source)
381 Mat out(N,M,CV_8UC1,Scalar(0));
384 copyMakeBorder(source,source_border,0,1,0,0,BORDER_CONSTANT,Scalar(0));
385 Mat rowS = source_border.row(S);
386 source_border.row(0).copyTo(rowS);
387 remap(source_border,out,CSIyx,ETAyx,INTER_LINEAR);
389 int wm=w_ker_2D[R-1].w;
391 std::vector<double> IMG((N+2*wm+1)*(M+2*wm+1), 0.);
392 std::vector<double> NOR((N+2*wm+1)*(M+2*wm+1), 0.);
394 for(int v=0; v<S; v++)
395 for(int u=ind1; u<R; u++)
397 int w=w_ker_2D[v*R+u].w;
398 for(int j=0; j<(2*w+1); j++)
400 for(int i=0; i<(2*w+1); i++)
402 int ind=(M+2*wm+1)*((j-w)+Rsr[v*R+u]+wm)+(i-w)+Csr[v*R+u]+wm;
403 IMG[ind]+=((w_ker_2D[v*R+u]).weights[j*(2*w+1)+i])*source.at<uchar>(v, u);
404 NOR[ind]+=((w_ker_2D[v*R+u]).weights[j*(2*w+1)+i]);
409 for(int i=0; i<((N+2*wm+1)*(M+2*wm+1)); i++)
412 //int xc=M/2-1, yc=N/2-1;
414 for(int j=wm; j<N+wm; j++)
415 for(int i=wm; i<M+wm; i++)
417 /*if(NOR[(M+2*wm+1)*j+i]>0)
418 ret[M*(j-wm)+i-wm]=(int) floor(IMG[(M+2*wm+1)*j+i]+0.5);*/
419 //int ro=(int)floor(std::sqrt((double)((j-wm-yc)*(j-wm-yc)+(i-wm-xc)*(i-wm-xc))));
420 int csi=(int) floor(CSIyx.at<float>(j-wm,i-wm));
422 if((csi>=(ind1-(w_ker_2D[ind1]).w))&&(csi<R))
423 out.at<uchar>(j-wm,i-wm)=(uchar) floor(IMG[(M+2*wm+1)*j+i]+0.5);
426 Mat out_cropped=out(Range(top,N-1-bottom),Range(left,M-1-right));
430 LogPolar_Overlapping::~LogPolar_Overlapping()
434 //----------------------------------------adjacent---------------------------------------
436 LogPolar_Adjacent::LogPolar_Adjacent(int w, int h, Point2i center, int _R, double _ro0, double smin, int full, int _s, int sp)
438 if ( (center.x!=w/2 || center.y!=h/2) && full==0) full=1;
440 if (center.x<0) center.x=0;
441 if (center.y<0) center.y=0;
442 if (center.x>=w) center.x=w-1;
443 if (center.y>=h) center.y=h-1;
448 if (center.x<=w/2 && center.y>=h/2)
449 rtmp=(int)std::sqrt((float)center.y*center.y + (float)(w-center.x)*(w-center.x));
450 else if (center.x>=w/2 && center.y>=h/2)
451 rtmp=(int)std::sqrt((float)center.y*center.y + (float)center.x*center.x);
452 else if (center.x>=w/2 && center.y<=h/2)
453 rtmp=(int)std::sqrt((float)(h-center.y)*(h-center.y) + (float)center.x*center.x);
454 else //if (center.x<=w/2 && center.y<=h/2)
455 rtmp=(int)std::sqrt((float)(h-center.y)*(h-center.y) + (float)(w-center.x)*(w-center.x));
459 top = M/2 - center.y;
460 bottom = M/2 - (h-center.y);
461 left = M/2 - center.x;
462 right = M/2 - (w - center.x);
465 top=bottom=left=right=0;
470 int jc=M/2-1, ic=N/2-1;
471 int _romax=std::min(ic, jc);
472 double _a=std::exp(std::log((double)(_romax/2-1)/(double)ro0)/(double)R);
473 S=(int) floor(2*CV_PI/(_a-1)+0.5);
476 create_map(M, N, _R, _s, _ro0, smin);
480 void LogPolar_Adjacent::create_map(int _M, int _n, int _R, int _s, double _ro0, double smin)
487 romax=std::min(M/2.0, N/2.0);
489 a=std::exp(std::log(romax/ro0)/(double)R);
495 for(int i=0; i<R*S; i++)
498 double xc=M/2.0, yc=N/2.0;
500 for(int j=0; j<N; j++)
501 for(int i=0; i<M; i++)
503 double x=i+0.5-xc, y=j+0.5-yc;
504 subdivide_recursively(x, y, i, j, 1, smin);
509 void LogPolar_Adjacent::subdivide_recursively(double x, double y, int i, int j, double length, double smin)
514 if(get_uv(x, y, u, v))
520 L[M*j+i].push_back(p);
521 A[v*R+u]+=length*length;
530 xs[0]=xs[3]=x+length/4.0;
531 xs[1]=xs[2]=x-length/4.0;
532 ys[1]=ys[0]=y+length/4.0;
533 ys[2]=ys[3]=y-length/4.0;
535 for(int z=0; z<4; z++)
536 get_uv(xs[z], ys[z], us[z], vs[z]);
539 for(int w=1; w<4; w++)
555 L[M*j+i].push_back(p);
556 A[vs[0]*R+us[0]]+=length*length;
562 for(int z=0; z<4; z++)
564 subdivide_recursively(xs[z], ys[z], i, j, length/2.0, smin);
570 const Mat LogPolar_Adjacent::to_cortical(const Mat &source)
573 copyMakeBorder(source,source_border,top,bottom,left,right,BORDER_CONSTANT,Scalar(0));
575 std::vector<double> map(R*S, 0.);
577 for(int j=0; j<N; j++)
578 for(int i=0; i<M; i++)
580 for(size_t z=0; z<(L[M*j+i]).size(); z++)
582 map[R*((L[M*j+i])[z].v)+((L[M*j+i])[z].u)]+=((L[M*j+i])[z].a)*(source_border.at<uchar>(j,i));
586 for(int i=0; i<R*S; i++)
589 Mat out(S,R,CV_8UC1,Scalar(0));
591 for(int i=0; i<S; i++)
593 out.at<uchar>(i,j)=(uchar) floor(map[i*R+j]+0.5);
598 const Mat LogPolar_Adjacent::to_cartesian(const Mat &source)
600 std::vector<double> map(M*N, 0.);
602 for(int j=0; j<N; j++)
603 for(int i=0; i<M; i++)
605 for(size_t z=0; z<(L[M*j+i]).size(); z++)
607 map[M*j+i]+=(L[M*j+i])[z].a*source.at<uchar>((L[M*j+i])[z].v,(L[M*j+i])[z].u);
611 Mat out(N,M,CV_8UC1,Scalar(0));
613 for(int i=0; i<N; i++)
614 for(int j=0; j<M; j++)
615 out.at<uchar>(i,j)=(uchar) floor(map[i*M+j]+0.5);
617 Mat out_cropped=out(Range(top,N-1-bottom),Range(left,M-1-right));
622 bool LogPolar_Adjacent::get_uv(double x, double y, int&u, int&v)
624 double ro=std::sqrt(x*x+y*y), theta;
628 theta=atan(y/x)+CV_PI;
638 u= (int) floor(std::log(ro/ro0)/std::log(a));
640 v= (int) floor(q*theta);
642 v= (int) floor(q*(theta+2*CV_PI));
647 LogPolar_Adjacent::~LogPolar_Adjacent()