cv::getOptimalDFTSize --- OpenCV代码阅读
在DFT中,可以使用FFT来加速,但是如果选个长度很坑爹如某个素数,那FFT就惨了,直接发挥不了作用,这个时候就可以对原始的数据长度进行扩展,最好是2^x(<--一般书上都这样写`不是一般性`我们假设长度是2^n,每次我都看的很郁闷),但是发现1,2,4,....中间的跨度很大,如果我的序列长度是 2^n+1 那就得选得2^(n+1)对内存来说是巨大的浪费,OpenCV中选择的是2^x*3^y*5^z,这样子选择256+1时可以选择270(3^3*2*5),没必要一下子选择512,来浪费内存.
当然在OpenCV中是维护了一张表optimalDFTSizeTab,属于空间换时间的方法,没有使用如下的方法
int getMultipliers(int n, int *n1, int *n2) { int multiplier, i; if (n == 1) { *n1 = 1; *n2 = 1; return FFT_ERROR; // n = 1 } multiplier = n / 2; for (i = multiplier; i >= 2; i--) { if (n % i == 0) { *n1 = i; *n2 = n / i; return FFT_OK; // n = n1 * n2 } } *n1 = 1; *n2 = n; return FFT_ERROR; // n - prime number }
当然其实上面的代码也是在OpenCV中的.
建立表后就可以查找值了.
查找使用传说中的二分法.
int cv::getOptimalDFTSize( int size0 ) { int a = 0, b = sizeof(optimalDFTSizeTab)/sizeof(optimalDFTSizeTab[0]) - 1; if( (unsigned)size0 >= (unsigned)optimalDFTSizeTab[b] ) return -1; while( a < b ) { int c = (a + b) >> 1; if( size0 <= optimalDFTSizeTab[c] ) b = c; else a = c+1; } return optimalDFTSizeTab[b]; }
开始时判断是否在表中,如果在的话迭代搜索,速度很快.....