【上采样问题】将浮点运算转换成整数运算
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%以上,而处理后的效果基本没有什么区别。
【上采样问题】将浮点运算转换成整数运算相关推荐
- oracle 转化为整数,字符串转换成整数——从源码学习
字符串转换成整数:输入一个表示整数的字符串,把该字符串转换成整数并输出,例如输入字符串"345",则输出整数345. 在笔试面试中,atoi 即「字符串转换成整数」是一个经典问题了 ...
- 关于把字符串整数转换成整数的程序
前几天去了先锋商泰面试,在面试时做了一个把输入的整数(例如:4238)重新排序成2348输出的题目. 由于自己没有准备充分,只是把功能写出来了.后来没有拿到offer. 今天在看<剑指offer ...
- 49.把字符串转换成整数
题目描述 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数. 数值为0或者字符串不是一 ...
- 剑指offer——面试题49:把字符串转换成整数
剑指offer--面试题49:把字符串转换成整数 Solution1: 代码写的啰嗦,但思路清晰..LeetCode上有相似的题目并考虑了溢出,可以参考LeetCode8答案 class Soluti ...
- 【华为OD机试真题 JS】IPv4地址转换成整数
标题:IPv4地址转换成整数 | 时间限制:1秒 | 内存限制:262144K | 语言限制:不限 存在一种虚拟IPv4地址,由4小节组成,每节的范围为0~255,以#号间隔,虚拟IPv4地址可以转换 ...
- 程序员编程艺术第三十 三十一章 字符串转换成整数,通配符字符串匹配
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 第三十~ ...
- 字符串转换成整数,带通配符的字符串匹配
之前本一直想写写神经网络算法和EM算法,但写这两个算法实在需要大段大段的时间,而平时上班,周末则跑去北大教室自习看书(顺便以时间为序,说下过去半年看过的自觉还不错的数学史方面的书:<数理统计学简 ...
- 【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 ...
- 编程题:将字符串转换成整数 C++实现
First:按照题目要求将一个字符串转换成一个整数,首先忽略掉前面的"+""-"后,主要的逻辑就是将字符串 中的元素一个一个拿出来转换成整数然后循环乘10后进行 ...
- 如何把一个字符串转换成整数
剑指offer第一章的例子,据说是微软的面试题,发现自己又躺枪了.字符串处理有多烦人不用我多说了吧. //基础版代码 int StrToInt(char* string) {int number = ...
最新文章
- [转]matlab GUI 新手入门——最基本的几个概念
- Vmware安装与使用
- 后端直接跳转前端页面_WEB前端开发中页面跳转等待时间过长如何解决?
- 反馈网络信息改善用户体验
- 集成Dapr的 Azure 容器应用
- JWT认证原理、整合springboot实战应用
- input:hidden的作用
- JAVA多线程(转)
- Java读取数据库中的数据
- 软件设计师 2022年上半年下午题
- ACM比赛代码文件读写调试方案
- 如何用电脑查看自己的IP地址
- 成功解决win10下某些文件路径不存在问题
- 用DrRacket写scheme语言的hello world
- 动荡市场的利剑——“统计套利”
- 右键快捷创建mk文件
- 违规对店铺综合质量评分、个性化推荐影响 以及标题 、修改sku的影响
- 制作一个GUI仪表盘,安排!LVGL『Gauge仪表盘控件』介绍
- 使用curl下载压缩文件
- 电脑改装linux游戏机下载,将 GameShell 改造为下载利器
热门文章
- 微信解绑手机号服务器会保留吗,我把我的微信号给了别人,银行卡都解绑了,但手机号还在绑定,会不会有危险...
- Solr分析器IK-analyzer配置及错误java.lang.AbstractMethodError解决
- JSP技术-01-语法及运行原理
- Struts2-02-OGNL及值栈
- 为什么 Flink 无法实时写入 MySQL?
- 封装Apache http client工具类
- 是的,我开始做这么一件事了
- php实现观看记录,PHP实现浏览历史记录
- oracle 基本dos命令,Oracle 常用 Dos命令
- mysql身份证校验码_通过SQL校验身份证号码是否正确