https://www.cnblogs.com/Imageshop/archive/2011/11/12/2246808.html
https://www.cnblogs.com/yssongest/p/5303151.html

直接进行计算的话,由于计算的srcX和srcY 都是浮点数,后续会进行大量的乘法,而图像数据量又大,速度不会理想,解决思路是:浮点运算→→整数运算→→”<<左右移按位运算”。
  放大的主要对象是u,v这些浮点数,OpenCV选择的放大倍数是2048“如何取这个合适的放大倍数呢,要从三个方面考虑,第一:精度问题,如果这个数取得过小,那么经过计算后可能会导致结果出现较大的误差。第二,这个数不能太大,太大会导致计算过程超过长整形所能表达的范围。第三:速度考虑。假如放大倍数取为12,那么算式在最后的结果中应该需要除以1212=144,但是如果取为16,则最后的除数为1616=256,这个数字好,我们可以用右移来实现,而右移要比普通的整除快多了。”我们利用左移11位操作就可以达到放大目的。

uchar* dataDst = matDst1.data;int stepDst = matDst1.step;uchar* dataSrc = matSrc.data;int stepSrc = matSrc.step;int iWidthSrc = matSrc.cols;int iHiehgtSrc = matSrc.rows;for (int j = 0; j < matDst1.rows; ++j){float fy = (float)((j + 0.5) * scale_y - 0.5);int sy = cvFloor(fy);fy -= sy;sy = std::min(sy, iHiehgtSrc - 2);sy = std::max(0, sy);short cbufy[2];cbufy[0] = cv::saturate_cast<short>((1.f - fy) * 2048);cbufy[1] = 2048 - cbufy[0];for (int i = 0; i < matDst1.cols; ++i){float fx = (float)((i + 0.5) * scale_x - 0.5);int sx = cvFloor(fx);fx -= sx;if (sx < 0) {fx = 0, sx = 0;}if (sx >= iWidthSrc - 1) {fx = 0, sx = iWidthSrc - 2;}short cbufx[2];cbufx[0] = cv::saturate_cast<short>((1.f - fx) * 2048);cbufx[1] = 2048 - cbufx[0];for (int k = 0; k < matSrc.channels(); ++k){*(dataDst+ j*stepDst + 3*i + k) = (*(dataSrc + sy*stepSrc + 3*sx + k) * cbufx[0] * cbufy[0] + *(dataSrc + (sy+1)*stepSrc + 3*sx + k) * cbufx[0] * cbufy[1] + *(dataSrc + sy*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[0] + *(dataSrc + (sy+1)*stepSrc + 3*(sx+1) + k) * cbufx[1] * cbufy[1]) >> 22;}}}cv::imwrite("linear_1.jpg", matDst1);cv::resize(matSrc, matDst2, matDst1.size(), 0, 0, 1);cv::imwrite("linear_2.jpg", matDst2);

一个简单的数学表达式可以表示如下:

f(x,y)=f(0,0)(1-x)(1-y)+f(1,0)x(1-y)+f(0,1)(1-x)y+f(1,1)xy

合并有关项,可写为: f(x,y)=(f(0,0)(1-x)+f(1,0)x) (1-y)+(f(0,1)(1-x)+f(1,1)x)y

由上式可以看出,这个过程存在着大量的浮点数运算,对于图像这样大的计算用户来说,是一个较为耗时的过程。

考虑到图像的特殊性,他的像素值的计算结果需要落在0到255之间,最多只有256种结果,由上式可以看出,一般情况下,计算出的f(x,y)是个浮点数,我们还需要对该浮点数进行取整。因此,我们可以考虑将该过程中的所有类似于1-x、1-y的变量放大合适的倍数,得到对应的整数,最后再除以一个合适的整数作为插值的结果。

如何取这个合适的放大倍数呢,要从三个方面考虑,第一:精度问题,如果这个数取得过小,那么经过计算后可能会导致结果出现较大的误差。第二,这个数不能太大,太大会导致计算过程超过长整形所能表达的范围。第三:速度考虑。假如放大倍数取为12,那么算式在最后的结果中应该需要除以1212=144,但是如果取为16,则最后的除数为1616=256,这个数字好,我们可以用右移来实现,而右移要比普通的整除快多了。

综合考虑上述三条,我们选择2048这个数比较合适。

下面我们假定某个算法得到了我们要取样的坐标分别PosX以及PosY,其中PosX=25.489,PosY=58.698。则这个过程的类似代码片段如下:

 1 NewX = Int(PosX)                        '向下取整,NewX=252 NewY = Int(PosY)                        '向下取整,NewY=583 PartX = (PosX - NewX) * 2048            '对应表达式中的X4 PartY = (PosY - NewY) * 2048            '对应表达式中的Y5 InvX = 2048 - PartX                     '对应表达式中的1-X6 InvY = 2048 - PartY                     '对应表达式中的1-Y7 8 Index1 = SamStride * NewY + NewX * 3    '计算取样点左上角邻近的那个像素点的内存地址9 Index2 = Index1 + SamStride          '左下角像素点地址
10 ImageData(Speed + 2) = ((Sample(Index1 + 2) * InvX + Sample(Index1 + 5) * PartX) * InvY + (Sample(Index2 + 2) * InvX + Sample(Index2 + 5) * PartX) * PartY) \ 4194304       '处理红色分量
11 ImageData(Speed + 1) = ((Sample(Index1 + 1) * InvX + Sample(Index1 + 4) * PartX) * InvY + (Sample(Index2 + 1) * InvX +Sample(Index2 + 4) * PartX) * PartY) \ 4194304       '处理绿色分量
12 ImageData(Speed) = ((Sample(Index1) * InvX + Sample(Index1 + 3) * PartX) * InvY + (Sample(Index2) * InvX +Sample(Index2 + 3) * PartX) * PartY) \ 4194304           '处理蓝色分量

以上代码中涉及到的变量都为整型(PosX及PosY当然为浮点型)。

  代码中Sample数组保存了从中取样的图像数据,SamStride为该图像的扫描行大小。观察上述代码,除了有2句涉及到了浮点计算,其他都是整数之间的运算。在Basic语言中,编译时如果勾选所有的高级优化,则\ 4194304会被编译为>>22,即右移22位,如果使用的是C语言,则直接写为>>22。需要注意的是,在进行这代代码前,需要保证PosX以及PosY在合理的范围内,即不能超出取样图像的宽度和高度范围。通过这样的改进,速度较直接用浮点类型快至少100%以上,而处理后的效果基本没有什么区别。

【上采样问题】将浮点运算转换成整数运算相关推荐

  1. oracle 转化为整数,字符串转换成整数——从源码学习

    字符串转换成整数:输入一个表示整数的字符串,把该字符串转换成整数并输出,例如输入字符串"345",则输出整数345. 在笔试面试中,atoi 即「字符串转换成整数」是一个经典问题了 ...

  2. 关于把字符串整数转换成整数的程序

    前几天去了先锋商泰面试,在面试时做了一个把输入的整数(例如:4238)重新排序成2348输出的题目. 由于自己没有准备充分,只是把功能写出来了.后来没有拿到offer. 今天在看<剑指offer ...

  3. 49.把字符串转换成整数

    题目描述 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一 ...

  4. 剑指offer——面试题49:把字符串转换成整数

    剑指offer--面试题49:把字符串转换成整数 Solution1: 代码写的啰嗦,但思路清晰..LeetCode上有相似的题目并考虑了溢出,可以参考LeetCode8答案 class Soluti ...

  5. 【华为OD机试真题 JS】IPv4地址转换成整数

    标题:IPv4地址转换成整数 | 时间限制:1秒 | 内存限制:262144K | 语言限制:不限 存在一种虚拟IPv4地址,由4小节组成,每节的范围为0~255,以#号间隔,虚拟IPv4地址可以转换 ...

  6. 程序员编程艺术第三十 三十一章 字符串转换成整数,通配符字符串匹配

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 第三十~ ...

  7. 字符串转换成整数,带通配符的字符串匹配

    之前本一直想写写神经网络算法和EM算法,但写这两个算法实在需要大段大段的时间,而平时上班,周末则跑去北大教室自习看书(顺便以时间为序,说下过去半年看过的自觉还不错的数学史方面的书:<数理统计学简 ...

  8. 【LeetCode】【Java】13. 罗马数字转整数——给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

    13. 罗马数字转整数 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 ...

  9. 编程题:将字符串转换成整数 C++实现

    First:按照题目要求将一个字符串转换成一个整数,首先忽略掉前面的"+""-"后,主要的逻辑就是将字符串 中的元素一个一个拿出来转换成整数然后循环乘10后进行 ...

  10. 如何把一个字符串转换成整数

    剑指offer第一章的例子,据说是微软的面试题,发现自己又躺枪了.字符串处理有多烦人不用我多说了吧. //基础版代码 int StrToInt(char* string) {int number = ...

最新文章

  1. [转]matlab GUI 新手入门——最基本的几个概念
  2. Vmware安装与使用
  3. 后端直接跳转前端页面_WEB前端开发中页面跳转等待时间过长如何解决?
  4. 反馈网络信息改善用户体验
  5. 集成Dapr的 Azure 容器应用
  6. JWT认证原理、整合springboot实战应用
  7. input:hidden的作用
  8. JAVA多线程(转)
  9. Java读取数据库中的数据
  10. 软件设计师 2022年上半年下午题
  11. ACM比赛代码文件读写调试方案
  12. 如何用电脑查看自己的IP地址
  13. 成功解决win10下某些文件路径不存在问题
  14. 用DrRacket写scheme语言的hello world
  15. 动荡市场的利剑——“统计套利”
  16. 右键快捷创建mk文件
  17. 违规对店铺综合质量评分、个性化推荐影响 以及标题 、修改sku的影响
  18. 制作一个GUI仪表盘,安排!LVGL『Gauge仪表盘控件』介绍
  19. 使用curl下载压缩文件
  20. 电脑改装linux游戏机下载,将 GameShell 改造为下载利器

热门文章

  1. 微信解绑手机号服务器会保留吗,我把我的微信号给了别人,银行卡都解绑了,但手机号还在绑定,会不会有危险...
  2. Solr分析器IK-analyzer配置及错误java.lang.AbstractMethodError解决
  3. JSP技术-01-语法及运行原理
  4. Struts2-02-OGNL及值栈
  5. 为什么 Flink 无法实时写入 MySQL?
  6. 封装Apache http client工具类
  7. 是的,我开始做这么一件事了
  8. php实现观看记录,PHP实现浏览历史记录
  9. oracle 基本dos命令,Oracle 常用 Dos命令
  10. mysql身份证校验码_通过SQL校验身份证号码是否正确