2009年3月31日火曜日

bicubic 法

 配列をリサイズしたかったので、Bicubic を使おうと OpenCV で試してみたら、扱いたいデータ型が未対応で、全然使えなかった。そこで、車輪の開発をする事に…。2次元配列は、1次元配列としてアクセスしています。また、boost::multi_array は、やや遅いので却下。
画像で使いたい方は、gil でチャレンジしてみるといいかも?


#ifndef ALGO_BICUBIC_HPP
#define ALGO_BICUBIC_HPP
// BICUBIC 法による配列変換

#include <cmath>

template <class T>
void bicubic_resize(
T* dst, //!< ターゲット
int dwidth, //!< 変換後幅
int dheight, //!< 変換後高
T* src, //!< ソース
int swidth, //!< 幅
int sheight //!< 高
) {
double wfact = static_cast<double>(swidth)/static_cast<double>(dwidth);
double hfact = static_cast<double>(sheight)/static_cast<double>(dheight);

for( int y = 0; y < dheight; ++y ) {
for( int x = 0; x < dwidth; ++x ) {
double sx = wfact * static_cast<double>(x);
double sy = hfact * static_cast<double>(y);
int six = static_cast<int>(sx);
int siy = static_cast<int>(sy);
T value = T();
for( int ry = siy-1; ry < siy+3; ++ry ) {
for( int rx = six-1; rx < six+3; ++rx ) {
double dx = std::abs( sx - static_cast<double>(rx) );
double dy = std::abs( sy - static_cast<double>(ry) );
double wx, wy;
if( dx < 1.0 ) wx = (dx - 1.0) * (dx * dx - dx - 1.0);
else wx = (1.0 - dx) * (dx - 2.0) * (dx - 2.0);
if( dy < 1.0 ) wy = (dy - 1.0) * (dy * dy - dy - 1.0);
else wy = (1.0 - dy) * (dy - 2.0) * (dy - 2.0);
int xo = rx;
if( xo < 0 ) xo = six; //0;
if(swidth <= xo) xo = six; //swidth-1;
int yo = ry;
if( yo < 0 ) yo = siy; //0;
if( sheight <= yo) yo = siy; //sheight-1;
value += src[ yo * swidth + xo ] * wx * wy;
}
}
dst[ y * dheight + x ] = value;
}
}
}

#endif // ALGO_BICUBIC_HPP


参考URL : http://www.geocities.jp/asumaroyuumaro/program/tips/BiCubic.html

0 件のコメント: