图像金字塔及尺寸缩放

旧城等待, 2022-06-17 08:06 473阅读 0赞
  1. 对图像尺度变换方法:resize函数可以直接。pyrUp()(拉普拉斯) ,pyrUDown()函数(高斯)(图像金字塔)。
  2. 图像金字塔:主要用于图像分割,是一种以多分辨率来解释图像的有效但概念简单的结构。
  3. 是一系列以金字塔形状排列的,分辨率逐渐降低接来源于同一张原始图的图像集合。通过梯次向下采样获得,直到达到某个终止条件才停止采样。

金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。

金字塔有两种:

1、高斯金字塔—————-用来向下采样(主要)。

2、拉普拉斯金字塔———————用来从金字塔低层图像重建上层未采样图像即最大程度的还原图像,配合高斯金字塔使用。

  1. 高斯金字塔原理:从金字塔i层生成i+1层(Gi+1),先用高斯核对Gi进行卷积,然后删除所有偶数行和偶数列,所得图像面积会变成原图的1/4

当图像金字塔向上移动时,尺寸和分辨率会降低。向下采样,向上就是图像尺寸加倍,向下就是图像尺寸减半。

高斯金字塔:

它是通过高斯平滑核亚采样获得一系列采样图像即第K层高斯金字塔通过平滑、亚采样可获得K+1层高斯图像。高斯金字塔包含了一系列低通滤波器,其截止频率从上一层到下一层一因子2逐渐增加,so高斯金字塔可以跨越很大的频率范围。

1、向下取样(缩小图像)

对图像Gi进行高斯核卷积且去除偶数行和列。

2、向上取样(放大图像)

  1. 将图像在每个方向扩大为原来的两倍,新增的行和列以0补充。使用先前同样的内核(乘以4)与放大后的图像卷积,获得“新增像素”的近似值。得到的图像极为放大的图像,但与原来的图像相比会发现比较模糊(丢失部分信息)采用拉普拉斯金字塔。

注意:上面所说的向上(拉普拉斯图像重建—加倍,倒金字塔)向下(高斯图像缩减—减半,正金字塔,)是针对图像尺寸的(和金字塔的方向相反)。

  1. void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType )
  2. void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType )
  3. {
  4. CV_Assert(borderType == BORDER_DEFAULT);
  5. CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
  6. ocl_pyrUp(_src, _dst, _dsz, borderType))
  7. Mat src = _src.getMat();
  8. Size dsz = _dsz.area() == 0 ? Size(src.cols*2, src.rows*2) : _dsz;
  9. _dst.create( dsz, src.type() );
  10. Mat dst = _dst.getMat();
  11. int depth = src.depth();
  12. #ifdef HAVE_TEGRA_OPTIMIZATION
  13. if(borderType == BORDER_DEFAULT && tegra::useTegra() && tegra::pyrUp(src, dst))
  14. return;
  15. #endif
  16. #if IPP_VERSION_X100 >= 801 && 0
  17. CV_IPP_CHECK()
  18. {
  19. bool isolated = (borderType & BORDER_ISOLATED) != 0;
  20. int borderTypeNI = borderType & ~BORDER_ISOLATED;
  21. if (borderTypeNI == BORDER_DEFAULT && (!src.isSubmatrix() || isolated) && dsz == Size(src.cols*2, src.rows*2))
  22. {
  23. typedef IppStatus (CV_STDCALL * ippiPyrUp)(const void* pSrc, int srcStep, void* pDst, int dstStep, IppiSize srcRoi, Ipp8u* buffer);
  24. int type = src.type();
  25. CV_SUPPRESS_DEPRECATED_START
  26. ippiPyrUp pyrUpFunc = type == CV_8UC1 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_8u_C1R :
  27. type == CV_8UC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_8u_C3R :
  28. type == CV_32FC1 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C1R :
  29. type == CV_32FC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C3R : 0;
  30. CV_SUPPRESS_DEPRECATED_END
  31. if (pyrUpFunc)
  32. {
  33. int bufferSize;
  34. IppiSize srcRoi = { src.cols, src.rows };
  35. IppDataType dataType = depth == CV_8U ? ipp8u : ipp32f;
  36. CV_SUPPRESS_DEPRECATED_START
  37. IppStatus ok = ippiPyrUpGetBufSize_Gauss5x5(srcRoi.width, dataType, src.channels(), &bufferSize);
  38. CV_SUPPRESS_DEPRECATED_END
  39. if (ok >= 0)
  40. {
  41. Ipp8u* buffer = ippsMalloc_8u(bufferSize);
  42. ok = pyrUpFunc(src.data, (int) src.step, dst.data, (int) dst.step, srcRoi, buffer);
  43. ippsFree(buffer);
  44. if (ok >= 0)
  45. {
  46. CV_IMPL_ADD(CV_IMPL_IPP);
  47. return;
  48. }
  49. setIppErrorStatus();
  50. }
  51. }
  52. }
  53. }
  54. #endif
  55. PyrFunc func = 0;
  56. if( depth == CV_8U )
  57. func = pyrUp_<FixPtCast<uchar, 6>, PyrUpVec_32s8u >;
  58. else if( depth == CV_16S )
  59. func = pyrUp_<FixPtCast<short, 6>, PyrUpVec_32s16s >;
  60. else if( depth == CV_16U )
  61. func = pyrUp_<FixPtCast<ushort, 6>, PyrUpVec_32s16u >;
  62. else if( depth == CV_32F )
  63. func = pyrUp_<FltCast<float, 6>, PyrUpVec_32f >;
  64. else if( depth == CV_64F )
  65. func = pyrUp_<FltCast<double, 6>, PyrUpNoVec<double, double> >;
  66. else
  67. CV_Error( CV_StsUnsupportedFormat, "" );
  68. func( src, dst, borderType );
  69. }

拉普拉斯金字塔:

  1. 数学定义:Li=Gi-UPGi+1\*g
  2. 将源图像中位置(xy)的像素映射到目标图像的(2x+12y+1)位置,即在进行向上取样。拉普拉斯金字塔是通过源图像减去先缩小后放大的图像的一系列图像构成。
  3. void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType )
  4. void cv::pyrDown( InputArray _src, OutputArray _dst, const Size& _dsz, int borderType )
  5. {
  6. CV_Assert(borderType != BORDER_CONSTANT);
  7. CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),
  8. ocl_pyrDown(_src, _dst, _dsz, borderType))
  9. Mat src = _src.getMat();
  10. Size dsz = _dsz.area() == 0 ? Size((src.cols + 1)/2, (src.rows + 1)/2) : _dsz;
  11. _dst.create( dsz, src.type() );
  12. Mat dst = _dst.getMat();
  13. int depth = src.depth();
  14. #ifdef HAVE_TEGRA_OPTIMIZATION
  15. if(borderType == BORDER_DEFAULT && tegra::useTegra() && tegra::pyrDown(src, dst))
  16. return;
  17. #endif
  18. #if IPP_VERSION_X100 >= 801 && 0
  19. CV_IPP_CHECK()
  20. {
  21. bool isolated = (borderType & BORDER_ISOLATED) != 0;
  22. int borderTypeNI = borderType & ~BORDER_ISOLATED;
  23. if (borderTypeNI == BORDER_DEFAULT && (!src.isSubmatrix() || isolated) && dsz == Size((src.cols + 1)/2, (src.rows + 1)/2))
  24. {
  25. typedef IppStatus (CV_STDCALL * ippiPyrDown)(const void* pSrc, int srcStep, void* pDst, int dstStep, IppiSize srcRoi, Ipp8u* buffer);
  26. int type = src.type();
  27. CV_SUPPRESS_DEPRECATED_START
  28. ippiPyrDown pyrDownFunc = type == CV_8UC1 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_8u_C1R :
  29. type == CV_8UC3 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_8u_C3R :
  30. type == CV_32FC1 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_32f_C1R :
  31. type == CV_32FC3 ? (ippiPyrDown) ippiPyrDown_Gauss5x5_32f_C3R : 0;
  32. CV_SUPPRESS_DEPRECATED_END
  33. if (pyrDownFunc)
  34. {
  35. int bufferSize;
  36. IppiSize srcRoi = { src.cols, src.rows };
  37. IppDataType dataType = depth == CV_8U ? ipp8u : ipp32f;
  38. CV_SUPPRESS_DEPRECATED_START
  39. IppStatus ok = ippiPyrDownGetBufSize_Gauss5x5(srcRoi.width, dataType, src.channels(), &bufferSize);
  40. CV_SUPPRESS_DEPRECATED_END
  41. if (ok >= 0)
  42. {
  43. Ipp8u* buffer = ippsMalloc_8u(bufferSize);
  44. ok = pyrDownFunc(src.data, (int) src.step, dst.data, (int) dst.step, srcRoi, buffer);
  45. ippsFree(buffer);
  46. if (ok >= 0)
  47. {
  48. CV_IMPL_ADD(CV_IMPL_IPP);
  49. return;
  50. }
  51. setIppErrorStatus();
  52. }
  53. }
  54. }
  55. }
  56. #endif
  57. PyrFunc func = 0;
  58. if( depth == CV_8U )
  59. func = pyrDown_<FixPtCast<uchar, 8>, PyrDownVec_32s8u>;
  60. else if( depth == CV_16S )
  61. func = pyrDown_<FixPtCast<short, 8>, PyrDownVec_32s16s >;
  62. else if( depth == CV_16U )
  63. func = pyrDown_<FixPtCast<ushort, 8>, PyrDownVec_32s16u >;
  64. else if( depth == CV_32F )
  65. func = pyrDown_<FltCast<float, 8>, PyrDownVec_32f>;
  66. else if( depth == CV_64F )
  67. func = pyrDown_<FltCast<double, 8>, PyrDownNoVec<double, double> >;
  68. else
  69. CV_Error( CV_StsUnsupportedFormat, "" );
  70. func( src, dst, borderType );
  71. }
  72. 可以理解拉普拉斯金字塔是高斯金字塔的逆行式。

尺寸调整:resize()函数

  1. void resize( InputArray src, OutputArray dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR );
  2. void cv::resize( InputArray _src, OutputArray _dst, Size dsize,
  3. double inv_scale_x, double inv_scale_y, int interpolation )
  4. {
  5. static ResizeFunc linear_tab[] =
  6. {
  7. resizeGeneric_<
  8. HResizeLinear<uchar, int, short,
  9. INTER_RESIZE_COEF_SCALE,
  10. HResizeLinearVec_8u32s>,
  11. VResizeLinear<uchar, int, short,
  12. FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS*2>,
  13. VResizeLinearVec_32s8u> >,
  14. 0,
  15. resizeGeneric_<
  16. HResizeLinear<ushort, float, float, 1,
  17. HResizeLinearVec_16u32f>,
  18. VResizeLinear<ushort, float, float, Cast<float, ushort>,
  19. VResizeLinearVec_32f16u> >,
  20. resizeGeneric_<
  21. HResizeLinear<short, float, float, 1,
  22. HResizeLinearVec_16s32f>,
  23. VResizeLinear<short, float, float, Cast<float, short>,
  24. VResizeLinearVec_32f16s> >,
  25. 0,
  26. resizeGeneric_<
  27. HResizeLinear<float, float, float, 1,
  28. HResizeLinearVec_32f>,
  29. VResizeLinear<float, float, float, Cast<float, float>,
  30. VResizeLinearVec_32f> >,
  31. resizeGeneric_<
  32. HResizeLinear<double, double, float, 1,
  33. HResizeNoVec>,
  34. VResizeLinear<double, double, float, Cast<double, double>,
  35. VResizeNoVec> >,
  36. 0
  37. };
  38. static ResizeFunc cubic_tab[] =
  39. {
  40. resizeGeneric_<
  41. HResizeCubic<uchar, int, short>,
  42. VResizeCubic<uchar, int, short,
  43. FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS*2>,
  44. VResizeCubicVec_32s8u> >,
  45. 0,
  46. resizeGeneric_<
  47. HResizeCubic<ushort, float, float>,
  48. VResizeCubic<ushort, float, float, Cast<float, ushort>,
  49. VResizeCubicVec_32f16u> >,
  50. resizeGeneric_<
  51. HResizeCubic<short, float, float>,
  52. VResizeCubic<short, float, float, Cast<float, short>,
  53. VResizeCubicVec_32f16s> >,
  54. 0,
  55. resizeGeneric_<
  56. HResizeCubic<float, float, float>,
  57. VResizeCubic<float, float, float, Cast<float, float>,
  58. VResizeCubicVec_32f> >,
  59. resizeGeneric_<
  60. HResizeCubic<double, double, float>,
  61. VResizeCubic<double, double, float, Cast<double, double>,
  62. VResizeNoVec> >,
  63. 0
  64. };
  65. static ResizeFunc lanczos4_tab[] =
  66. {
  67. resizeGeneric_<HResizeLanczos4<uchar, int, short>,
  68. VResizeLanczos4<uchar, int, short,
  69. FixedPtCast<int, uchar, INTER_RESIZE_COEF_BITS*2>,
  70. VResizeNoVec> >,
  71. 0,
  72. resizeGeneric_<HResizeLanczos4<ushort, float, float>,
  73. VResizeLanczos4<ushort, float, float, Cast<float, ushort>,
  74. VResizeLanczos4Vec_32f16u> >,
  75. resizeGeneric_<HResizeLanczos4<short, float, float>,
  76. VResizeLanczos4<short, float, float, Cast<float, short>,
  77. VResizeLanczos4Vec_32f16s> >,
  78. 0,
  79. resizeGeneric_<HResizeLanczos4<float, float, float>,
  80. VResizeLanczos4<float, float, float, Cast<float, float>,
  81. VResizeLanczos4Vec_32f> >,
  82. resizeGeneric_<HResizeLanczos4<double, double, float>,
  83. VResizeLanczos4<double, double, float, Cast<double, double>,
  84. VResizeNoVec> >,
  85. 0
  86. };
  87. static ResizeAreaFastFunc areafast_tab[] =
  88. {
  89. resizeAreaFast_<uchar, int, ResizeAreaFastVec<uchar, ResizeAreaFastVec_SIMD_8u> >,
  90. 0,
  91. resizeAreaFast_<ushort, float, ResizeAreaFastVec<ushort, ResizeAreaFastVec_SIMD_16u> >,
  92. resizeAreaFast_<short, float, ResizeAreaFastVec<short, ResizeAreaFastVec_SIMD_16s> >,
  93. 0,
  94. resizeAreaFast_<float, float, ResizeAreaFastVec_SIMD_32f>,
  95. resizeAreaFast_<double, double, ResizeAreaFastNoVec<double, double> >,
  96. 0
  97. };
  98. static ResizeAreaFunc area_tab[] =
  99. {
  100. resizeArea_<uchar, float>, 0, resizeArea_<ushort, float>,
  101. resizeArea_<short, float>, 0, resizeArea_<float, float>,
  102. resizeArea_<double, double>, 0
  103. };
  104. Size ssize = _src.size();
  105. CV_Assert( ssize.area() > 0 );
  106. CV_Assert( dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0) );
  107. if( dsize.area() == 0 )
  108. {
  109. dsize = Size(saturate_cast<int>(ssize.width*inv_scale_x),
  110. saturate_cast<int>(ssize.height*inv_scale_y));
  111. CV_Assert( dsize.area() > 0 );
  112. }
  113. else
  114. {
  115. inv_scale_x = (double)dsize.width/ssize.width;
  116. inv_scale_y = (double)dsize.height/ssize.height;
  117. }
  118. CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat() && _src.cols() > 10 && _src.rows() > 10,
  119. ocl_resize(_src, _dst, dsize, inv_scale_x, inv_scale_y, interpolation))
  120. Mat src = _src.getMat();
  121. _dst.create(dsize, src.type());
  122. Mat dst = _dst.getMat();
  123. #ifdef HAVE_TEGRA_OPTIMIZATION
  124. if (tegra::useTegra() && tegra::resize(src, dst, (float)inv_scale_x, (float)inv_scale_y, interpolation))
  125. return;
  126. #endif
  127. int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
  128. double scale_x = 1./inv_scale_x, scale_y = 1./inv_scale_y;
  129. int k, sx, sy, dx, dy;
  130. int iscale_x = saturate_cast<int>(scale_x);
  131. int iscale_y = saturate_cast<int>(scale_y);
  132. bool is_area_fast = std::abs(scale_x - iscale_x) < DBL_EPSILON &&
  133. std::abs(scale_y - iscale_y) < DBL_EPSILON;
  134. #if IPP_VERSION_X100 >= 701
  135. CV_IPP_CHECK()
  136. {
  137. #define IPP_RESIZE_EPS 1e-10
  138. double ex = fabs((double)dsize.width / src.cols - inv_scale_x) / inv_scale_x;
  139. double ey = fabs((double)dsize.height / src.rows - inv_scale_y) / inv_scale_y;
  140. if ( ((ex < IPP_RESIZE_EPS && ey < IPP_RESIZE_EPS && depth != CV_64F) || (ex == 0 && ey == 0 && depth == CV_64F)) &&
  141. (interpolation == INTER_LINEAR || interpolation == INTER_CUBIC) &&
  142. !(interpolation == INTER_LINEAR && is_area_fast && iscale_x == 2 && iscale_y == 2 && depth == CV_8U))
  143. {
  144. int mode = -1;
  145. if (interpolation == INTER_LINEAR && src.rows >= 2 && src.cols >= 2)
  146. mode = ippLinear;
  147. else if (interpolation == INTER_CUBIC && src.rows >= 4 && src.cols >= 4)
  148. mode = ippCubic;
  149. if( mode >= 0 && (cn == 1 || cn == 3 || cn == 4) &&
  150. (depth == CV_16U || depth == CV_16S || depth == CV_32F ||
  151. (depth == CV_64F && mode == ippLinear)))
  152. {
  153. bool ok = true;
  154. Range range(0, src.rows);
  155. IPPresizeInvoker invoker(src, dst, inv_scale_x, inv_scale_y, mode, &ok);
  156. parallel_for_(range, invoker, dst.total()/(double)(1<<16));
  157. if( ok )
  158. {
  159. CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);
  160. return;
  161. }
  162. setIppErrorStatus();
  163. }
  164. }
  165. #undef IPP_RESIZE_EPS
  166. }
  167. #endif
  168. if( interpolation == INTER_NEAREST )
  169. {
  170. resizeNN( src, dst, inv_scale_x, inv_scale_y );
  171. return;
  172. }
  173. {
  174. // in case of scale_x && scale_y is equal to 2
  175. // INTER_AREA (fast) also is equal to INTER_LINEAR
  176. if( interpolation == INTER_LINEAR && is_area_fast && iscale_x == 2 && iscale_y == 2 )
  177. interpolation = INTER_AREA;
  178. // true "area" interpolation is only implemented for the case (scale_x <= 1 && scale_y <= 1).
  179. // In other cases it is emulated using some variant of bilinear interpolation
  180. if( interpolation == INTER_AREA && scale_x >= 1 && scale_y >= 1 )
  181. {
  182. if( is_area_fast )
  183. {
  184. int area = iscale_x*iscale_y;
  185. size_t srcstep = src.step / src.elemSize1();
  186. AutoBuffer<int> _ofs(area + dsize.width*cn);
  187. int* ofs = _ofs;
  188. int* xofs = ofs + area;
  189. ResizeAreaFastFunc func = areafast_tab[depth];
  190. CV_Assert( func != 0 );
  191. for( sy = 0, k = 0; sy < iscale_y; sy++ )
  192. for( sx = 0; sx < iscale_x; sx++ )
  193. ofs[k++] = (int)(sy*srcstep + sx*cn);
  194. for( dx = 0; dx < dsize.width; dx++ )
  195. {
  196. int j = dx * cn;
  197. sx = iscale_x * j;
  198. for( k = 0; k < cn; k++ )
  199. xofs[j + k] = sx + k;
  200. }
  201. func( src, dst, ofs, xofs, iscale_x, iscale_y );
  202. return;
  203. }
  204. ResizeAreaFunc func = area_tab[depth];
  205. CV_Assert( func != 0 && cn <= 4 );
  206. AutoBuffer<DecimateAlpha> _xytab((ssize.width + ssize.height)*2);
  207. DecimateAlpha* xtab = _xytab, *ytab = xtab + ssize.width*2;
  208. int xtab_size = computeResizeAreaTab(ssize.width, dsize.width, cn, scale_x, xtab);
  209. int ytab_size = computeResizeAreaTab(ssize.height, dsize.height, 1, scale_y, ytab);
  210. AutoBuffer<int> _tabofs(dsize.height + 1);
  211. int* tabofs = _tabofs;
  212. for( k = 0, dy = 0; k < ytab_size; k++ )
  213. {
  214. if( k == 0 || ytab[k].di != ytab[k-1].di )
  215. {
  216. assert( ytab[k].di == dy );
  217. tabofs[dy++] = k;
  218. }
  219. }
  220. tabofs[dy] = ytab_size;
  221. func( src, dst, xtab, xtab_size, ytab, ytab_size, tabofs );
  222. return;
  223. }
  224. }
  225. int xmin = 0, xmax = dsize.width, width = dsize.width*cn;
  226. bool area_mode = interpolation == INTER_AREA;
  227. bool fixpt = depth == CV_8U;
  228. float fx, fy;
  229. ResizeFunc func=0;
  230. int ksize=0, ksize2;
  231. if( interpolation == INTER_CUBIC )
  232. ksize = 4, func = cubic_tab[depth];
  233. else if( interpolation == INTER_LANCZOS4 )
  234. ksize = 8, func = lanczos4_tab[depth];
  235. else if( interpolation == INTER_LINEAR || interpolation == INTER_AREA )
  236. ksize = 2, func = linear_tab[depth];
  237. else
  238. CV_Error( CV_StsBadArg, "Unknown interpolation method" );
  239. ksize2 = ksize/2;
  240. CV_Assert( func != 0 );
  241. AutoBuffer<uchar> _buffer((width + dsize.height)*(sizeof(int) + sizeof(float)*ksize));
  242. int* xofs = (int*)(uchar*)_buffer;
  243. int* yofs = xofs + width;
  244. float* alpha = (float*)(yofs + dsize.height);
  245. short* ialpha = (short*)alpha;
  246. float* beta = alpha + width*ksize;
  247. short* ibeta = ialpha + width*ksize;
  248. float cbuf[MAX_ESIZE];
  249. for( dx = 0; dx < dsize.width; dx++ )
  250. {
  251. if( !area_mode )
  252. {
  253. fx = (float)((dx+0.5)*scale_x - 0.5);
  254. sx = cvFloor(fx);
  255. fx -= sx;
  256. }
  257. else
  258. {
  259. sx = cvFloor(dx*scale_x);
  260. fx = (float)((dx+1) - (sx+1)*inv_scale_x);
  261. fx = fx <= 0 ? 0.f : fx - cvFloor(fx);
  262. }
  263. if( sx < ksize2-1 )
  264. {
  265. xmin = dx+1;
  266. if( sx < 0 && (interpolation != INTER_CUBIC && interpolation != INTER_LANCZOS4))
  267. fx = 0, sx = 0;
  268. }
  269. if( sx + ksize2 >= ssize.width )
  270. {
  271. xmax = std::min( xmax, dx );
  272. if( sx >= ssize.width-1 && (interpolation != INTER_CUBIC && interpolation != INTER_LANCZOS4))
  273. fx = 0, sx = ssize.width-1;
  274. }
  275. for( k = 0, sx *= cn; k < cn; k++ )
  276. xofs[dx*cn + k] = sx + k;
  277. if( interpolation == INTER_CUBIC )
  278. interpolateCubic( fx, cbuf );
  279. else if( interpolation == INTER_LANCZOS4 )
  280. interpolateLanczos4( fx, cbuf );
  281. else
  282. {
  283. cbuf[0] = 1.f - fx;
  284. cbuf[1] = fx;
  285. }
  286. if( fixpt )
  287. {
  288. for( k = 0; k < ksize; k++ )
  289. ialpha[dx*cn*ksize + k] = saturate_cast<short>(cbuf[k]*INTER_RESIZE_COEF_SCALE);
  290. for( ; k < cn*ksize; k++ )
  291. ialpha[dx*cn*ksize + k] = ialpha[dx*cn*ksize + k - ksize];
  292. }
  293. else
  294. {
  295. for( k = 0; k < ksize; k++ )
  296. alpha[dx*cn*ksize + k] = cbuf[k];
  297. for( ; k < cn*ksize; k++ )
  298. alpha[dx*cn*ksize + k] = alpha[dx*cn*ksize + k - ksize];
  299. }
  300. }
  301. for( dy = 0; dy < dsize.height; dy++ )
  302. {
  303. if( !area_mode )
  304. {
  305. fy = (float)((dy+0.5)*scale_y - 0.5);
  306. sy = cvFloor(fy);
  307. fy -= sy;
  308. }
  309. else
  310. {
  311. sy = cvFloor(dy*scale_y);
  312. fy = (float)((dy+1) - (sy+1)*inv_scale_y);
  313. fy = fy <= 0 ? 0.f : fy - cvFloor(fy);
  314. }
  315. yofs[dy] = sy;
  316. if( interpolation == INTER_CUBIC )
  317. interpolateCubic( fy, cbuf );
  318. else if( interpolation == INTER_LANCZOS4 )
  319. interpolateLanczos4( fy, cbuf );
  320. else
  321. {
  322. cbuf[0] = 1.f - fy;
  323. cbuf[1] = fy;
  324. }
  325. if( fixpt )
  326. {
  327. for( k = 0; k < ksize; k++ )
  328. ibeta[dy*ksize + k] = saturate_cast<short>(cbuf[k]*INTER_RESIZE_COEF_SCALE);
  329. }
  330. else
  331. {
  332. for( k = 0; k < ksize; k++ )
  333. beta[dy*ksize + k] = cbuf[k];
  334. }
  335. }
  336. func( src, dst, xofs, fixpt ? (void*)ialpha : (void*)alpha, yofs,
  337. fixpt ? (void*)ibeta : (void*)beta, xmin, xmax, ksize );
  338. }

发表评论

表情:
评论列表 (有 0 条评论,473人围观)

还没有评论,来说两句吧...

相关阅读

    相关 模型尺寸问题

    前要:前段时间因为项目开发,3d美术做的模型是非人形模型,不需要绑定骨骼,美术做的了第一版后面需要修改,但是替换的时候发现美术的子物体缩放值都没有统一,美术每次修改都会变换,但

    相关 图像算法

    怎样计算缩放比例? 有四种方法:1.对角线法,以对角线长度为准,其伸长者为放大,缩短者为缩小,其底边并行线即为新尺寸。2.计算器法,先输入欲缩放宽度,按除键,再输入原稿尺

    相关 OpenCV 几何变换-图像

    图像的缩放主要用于改变图像的大小,缩放后图像的图像的宽度和高度会发生变化。在图像处理中是一种很基础的几何变换,但是具有很重要的作用,比如:当输入图片尺寸过大时,处理速度会很慢,