在进入频域变换之前, 我们还是轻松一下,再搞点平面上的变化来看看。这把选了一个双线性插值(Bilinear interpolation)来实现是源于看到了csdn上别人的问题, 权且实现一个函数,方便大家的使用吧。

双线性插值简单的说,就是扩展了之后的图像像素坐标映射回原来的坐标空间的时候, 如果出现了没有对应到整数点的情况。这时候需要做2次线性的插值计算出新的坐标的像素值,比如说:

这里可以看到这个P点落在了ABCD区间内, 如果我们本着最朴素的这个P点最靠近谁权重就越大的加权平均的思想, 我们很容易得到这样的论断:

A点对P的影响就是Sa的面积, B点的影响就是Sb, C点就Sc, d就是Sd。这样越近就是权重越大,基本上就是这样的逻辑。

这样P的像素可以简单的用 (A*Sa+B*Sb+C*Sc+D*Sd )/(Sa+Sb+Sc+Sd);来得到了。以我的雷厉风行,马上写出了如下的代码:

  1. /**
  2. ** method to remove sharp the raw image with unsharp mask
  3. * @param src input grayscale binary array
  4. * @param dst output grayscale result, the memory need to be allocated outside of the function
  5. * @param srcWidth width of the input grayscale image
  6. * @param srcHeight height of the input grayscale image
  7. * @param scalePercent, scale percentage (0-xxx)
  8. */
  9. void stretchImage (const unsigned char* src, unsigned char* dst, int srcWidth, int srcHeight, int scalePercent)
  10. {
  11. if (scalePercent < 0)
  12. return;
  13. int x, y;
  14. int ox, oy;
  15. int tmpx,tmpy;
  16. int ratio = (100 << 8)/scalePercent;
  17. int dstWidth = srcWidth * scalePercent / 100;
  18. int dstHeight = srcHeight * scalePercent / 100;
  19. unsigned char color[2][2];
  20. for (int j = 0; j < dstHeight; j ++)
  21. {
  22. for (int i = 0; i < dstWidth; i ++)
  23. {
  24. tmpx = i * ratio;
  25. tmpy = j * ratio;
  26. ox = tmpx >> 8;
  27. oy = tmpy >> 8;
  28. x = tmpx & 0xFF;
  29. y = tmpy & 0xFF;
  30. color[0][0] = src[ oy*srcWidth + ox ];
  31. color[1][0] = src[ oy*srcWidth + ox +1 ];
  32. color[0][1] = src[ (oy+1)*srcWidth + ox ];
  33. color[1][1] = src[ (oy+1)*srcWidth + ox+1 ];
  34. int final = (0x100 - x)*(0x100 - y)*color[0][0] + x*(0x100 - y)*color[1][0] + (0x100-x)*y*color[0][1] + x*y*color[1][1];
  35. final = final >> 16;
  36. if (final>255)
  37. final = 255;
  38. if (final<0)
  39. final = 0;
  40. dst [ j*dstWidth + i] = (unsigned char)final;
  41. }
  42. }
  43. }

/**
** method to remove sharp the raw image with unsharp mask
* @param src input grayscale binary array
* @param dst output grayscale result, the memory need to be allocated outside of the function
* @param srcWidth width of the input grayscale image
* @param srcHeight height of the input grayscale image
* @param scalePercent, scale percentage (0-xxx)
*/
void stretchImage (const unsigned char* src, unsigned char* dst, int srcWidth, int srcHeight, int scalePercent)
{
if (scalePercent < 0)
return;
int x, y;
int ox, oy;
int tmpx,tmpy;
int ratio = (100 << 8)/scalePercent;
int dstWidth = srcWidth * scalePercent / 100;
int dstHeight = srcHeight * scalePercent / 100;
unsigned char color[2][2];
for (int j = 0; j < dstHeight; j ++)
{
for (int i = 0; i < dstWidth; i ++)
{
tmpx = i * ratio;
tmpy = j * ratio;
ox = tmpx >> 8;
oy = tmpy >> 8;
x = tmpx & 0xFF;
y = tmpy & 0xFF;
color[0][0] = src[ oy*srcWidth + ox ];
color[1][0] = src[ oy*srcWidth + ox +1 ];
color[0][1] = src[ (oy+1)*srcWidth + ox ];
color[1][1] = src[ (oy+1)*srcWidth + ox+1 ];
int final = (0x100 - x)*(0x100 - y)*color[0][0] + x*(0x100 - y)*color[1][0] + (0x100-x)*y*color[0][1] + x*y*color[1][1];
final = final >> 16;
if (final>255)
final = 255;
if (final<0)
final = 0;
dst [ j*dstWidth + i] = (unsigned char)final;
}
}
}

需要说明的事情是, 浮点数需要引入效率上一定的损失, 当然我们这里就用大数来和谐。但是只是随便写写的代码, 我们没有加入超出int范围的检查或者说明,暂时也只能这样了:)。用了这个函数的效果还是不错的, 我们来看看在75%,125%和250%时候的效果:

原图:

%75效果图:

125%效果图:

250%效果图:

其实从效果图多少可以看出一些的问题就是, 随着图像的拉伸, 图像的锐度其实降低了, 这个比较容易想象的,因为我们这个拉伸的办法本身就是线性的,无疑来扩大的时候把锐利的边缘模糊化了,所以自然在图像扩大很多倍的时候效果不是很好了。

http://blog.csdn.net/hhygcy/article/details/4434870#comments

图像处理之基础---图像缩放中的双线性插值c实现的更多相关文章

  1. opencv学习笔记——图像缩放函数resize

    opencv提供了一种图像缩放函数 功能:实现对输入图像缩放到指定大小 函数原型: void cv::resize ( InputArray src, OutputArray dst, Size ds ...

  2. opencv3 图像处理(一)图像缩放( python与c++ 实现)

    opencv3 图像处理 之 图像缩放( python与c++实现 ) 一. 主要函数介绍 1) 图像大小变换 Resize () 原型: void Resize(const CvArr* src,C ...

  3. 邻近双线性插值图像缩放的Python实现

    最近在查找有关图像缩放之类的算法,因工作中需要用到诸如此类的图像处理算法就在网上了解了一下相关算法,以及其原理,并用Python实现,且亲自验证过,在次与大家分享. 声明:本文代码示例针对的是plan ...

  4. c#数字图像处理(十)图像缩放

    图像几何变换(缩放.旋转)中的常用的插值算法 在图像几何变换的过程中,常用的插值方法有最邻近插值(近邻取样法).双线性内插值和三次卷积法. 最邻近插值: 这是一种最为简单的插值方法,在图像中最小的单位 ...

  5. 实现基于最近邻内插和双线性内插的图像缩放C++实现

    平时我们写图像处理的代码时,如果需要缩放图片,我们都是直接调用图像库的resize函数来完成图像的缩放.作为一个机器视觉或者图像处理算法的工作者,图像缩放代码的实现应该是必须掌握的.在众多图像缩放算法 ...

  6. OpenCV计算机视觉学习(11)——图像空间几何变换(图像缩放,图像旋转,图像翻转,图像平移,仿射变换,镜像变换)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 图像 ...

  7. 图像缩放_OpenCv

    图像缩放是一种比较简单的图像处理操作,这里给出opencv中的代码, opencv的版本C语言接口 int resize_c() { const char *pstrImageName = " ...

  8. opencv2 矩阵方式 resize图像缩放代码(转载)

    http://blog.sina.com.cn/s/blog_74a459380101r0yx.html opencv2 矩阵方式 resize图像缩放代码(转载) (2014-05-16 09:55 ...

  9. OpenCV探索之路(二):图像处理的基础知识点串烧

    opencv图像初始化操作 #include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp> using n ...

随机推荐

  1. wdcp 打开网页显示 Apache 2 Test Page powered by CentOS -- 来自辉哥博客

    是因为更新过系统,安装并更新了系统自带的apache 执行这个命令即可 #ln -sf /www/wdlinux/init.d/httpd /etc/rc.d/init.d/httpd#reboot ...

  2. 奇异值分解 SVD 的数学解释

    奇异值分解(Singular Value Decomposition,SVD)是一种矩阵分解(Matrix Decomposition)的方法.除此之外,矩阵分解还有很多方法,例如特征分解(Eigen ...

  3. 零基础入门学习Python(18)--函数:灵活即强大

    前言 上一节课我们基本介绍Python函数的用法,这一节课我们主要针对函数的参数进行进一步的深入学习. 知识点 形参(parameter)和实参(argument) >>> def ...

  4. 关于latch: cache buffers chains的sql优化

    前段时间,优化了一些耗buffer比较多的sql,但是CPU使用率还是没下来 . 查看操作系统CPU使用率 查看awr,发现又有一条超级耗性能的sql冒出来了. 该SQL每次执行耗费3e多个buffe ...

  5. PHP读取超大的excel文件数据的方案

    场景和痛点 说明 今天因为一个老同学找我,说自己公司的物流业务都是现在用excel处理,按月因为数据量大,一个excel差不多有百万数据,文件有接近100M,打开和搜索就相当的慢 联想到场景:要导入数 ...

  6. vscode 解决符号无法识别的问题

    一开始浏览代码出现了下面这个问题, __attribute__ 标记为红色,符号无法识别,下面还出现了很多提示需要加 ), } 等符号,虽然编译没问题,但是看着红色标记和一堆提示真是要逼死强迫症. 既 ...

  7. STL优先队列重载

    priority_queue默认是大根堆,如果需要使用小根堆,如下 int main(){ priority_queue<int,vector<int>,greater<int ...

  8. h-ui.admin.pro.iframe头部和标签Tab修改CSS

    原效果:头部高度偏高,tab标签不太好看 ​ 修改后:缩小高度,调整tab标签css样式 ​ 百度网盘链接:https://pan.baidu.com/s/1qknPNAMGL7BFUIsleOF9M ...

  9. MVC系统学习8——AsyncController

    关于为什么使用异步Controller,这里不做备忘,三岁小孩都懂.主要的备忘是如何使用AsyncController. //这个action以Async结尾,并且返回值是void public vo ...

  10. URAL 1297 求最长回文字符串

    有种简单的方法,数组从左到右扫一遍,每次以当前的点为中心,只要左右相等就往左右走,这算出来的回文字符串是奇数长度的 还有偶数长度的回文字符串就是以当前扫到的点和它左边的点作为中心,然后往左右扫 这是O ...