Lanczos 滤波器,因发明者而得名,在信号处理领域,主要用在增加采样率和低通滤波,在图像处理领域用于图像缩放、旋转,其可以在减小锯齿、锐度、振铃效应( aliasing, sharpness, and minimal ringing)取得最好的平衡。
滤波函数如下:
L(x)={sinc⁡(x)&ThinSpace;sinc⁡(x/a)if −a&lt;x&lt;a,0otherwise.{\displaystyle L(x)={\begin{cases}\operatorname {sinc} (x)\,\operatorname {sinc} (x/a)&amp;{\text{if}}\ -a&lt;x&lt;a,\\0&amp;{\text{otherwise}}.\end{cases}}}L(x)={sinc(x)sinc(x/a)0​if −a<x<a,otherwise.​
等价于:
L(x)={1if x=0,asin⁡(πx)sin⁡(πx/a)π2x2if −a≤x&lt;aand x≠0,0otherwise.{\displaystyle L(x)={\begin{cases}1&amp;{\text{if}}\ x=0,\\{\dfrac {a\sin(\pi x)\sin(\pi x/a)}{\pi ^{2}x^{2}}}&amp;{\text{if}}\ -a\leq x&lt;a\ {\text{and}}\ x\neq 0,\\0&amp;{\text{otherwise}}.\end{cases}}}L(x)=⎩⎪⎪⎨⎪⎪⎧​1π2x2asin(πx)sin(πx/a)​0​if x=0,if −a≤x<a and x̸​=0,otherwise.​
当a取3时,就是Lanczos3滤波器。
插值公式:
S(x)=∑i=⌊x⌋−a+1⌊x⌋+asiL(x−i)S(x) = \sum_{i=\lfloor x \rfloor - a + 1}^{\lfloor x \rfloor + a} s_{i} L(x - i)S(x)=i=⌊x⌋−a+1∑⌊x⌋+a​si​L(x−i)
a是滤波尺寸,⌊x⌋\lfloor x \rfloor⌊x⌋是向下取整。
性质:
1、a>0,Lanczos 核函数对每个点都是连续,并且其倒数也是连续,因此S(x)S(x)S(x)连续,其倒数连续;
2、Lanczos 核函数在整数点值为零,除了 x = 0,核函数为1,相当于原始x处信号值不变,仅仅对小数位置进行插值;
二维的情形:
L(x,y)=L(x)L(y){\displaystyle L(x,y)=L(x)L(y)}L(x,y)=L(x)L(y)
算法实现:
代码实现参考https://github.com/richgel999/imageresampler

#define  M_PI       3.14159265358979323846
//sinc函数值
static double sinc(double x)
{x = (x * M_PI);if ((x < 0.01f) && (x > -0.01f))return 1.0f + x*x*(-1.0f / 6.0f + x*x*1.0f / 120.0f);return sin(x) / x;
}

对于0附近的sinc函数值,采用其泰勒展开式计算:
sinc⁡(x)=sin⁡(x)x=∑n=0∞(−x2)n(2n+1)!\operatorname {sinc} (x)={\frac {\sin(x)}{x}}=\sum _{n=0}^{\infty }{\frac {\left(-x^{2}\right)^{n}}{(2n+1)!}}sinc(x)=xsin(x)​=n=0∑∞​(2n+1)!(−x2)n​

//计算Lanczos3核函数
static float clip(double t)
{const float eps = .0000125f;if (fabs(t) < eps)return 0.0f;return (float)t;
}static inline float lancos(float t)
{if (t < 0.0f)t = -t;if (t < 3.0f)return clip(sinc(t) * sinc(t / 3.0f));elsereturn (0.0f);
}
//x方向的插值:
static inline float lancos3_resample_x(uint8_t** arr,int src_w, int src_h, int y, int x,float xscale)
{float s = 0;float coef_sum = 0.0f;float coef;float pix;int i;int l, r;float c;float hw;//对于缩小的情况hw相当于扩大了领域像素个数,这里如果不作此处理,最终缩小图片效果跟最近领域插值法没多少区别,其效果相当于先低通滤波,再插值if (xscale > 1.0f)hw = 3.0f;elsehw = 3.0f / xscale;c = (float)x / xscale;l = (int)floor(c - hw);r = (int)ceil(c + hw);if (y < 0)y = 0;if (y >= src_h)y = src_h - 1;if (xscale > 1.0f)xscale = 1.0f;for (i = l; i <= r; i++){   x = i;if (i < 0)x = 0;if (i >= src_w)x = src_w - 1;pix = arr[y][x];coef = lancos((c-i)*xscale);s += pix * coef;coef_sum += coef;}s /= coef_sum; return s;
}
void img_resize_using_lancos3(uint8_2d* src, uint8_2d* dst)
{int src_rows, src_cols;int dst_rows, dst_cols;int i, j;if (!src || !dst)return;uint8_t** src_arr;uint8_t** dst_arr;float xratio;float yratio;float pix;int val;int k;float hw;src_arr = src->arr;dst_arr = dst->arr;src_rows = src->rows;src_cols = src->cols;dst_rows = dst->rows;dst_cols = dst->cols;xratio = (float)(dst_cols) / (float)src_cols;yratio = (float)(dst_rows) / (float)src_rows;float scale = 0.0f;if (yratio > 1.0f){hw = 3.0;scale = 1.0f;}else{hw = 3.0 / yratio;scale = yratio;}for (i = 0; i < dst_rows; i++){for (j = 0; j < dst_cols; j++){int t, b;float c;float s = 0;float coef_sum = 0.0f;float coef;float pix;c = (float)i / yratio;t = (int)floor(c - hw);b = (int)ceil(c + hw);//先对x方向插值,再进行y方向插值。for (k = t; k <= b; k++){pix = lancos3_resample_x(src_arr, src_cols,src_rows, k, j,xratio);coef = lancos((c - k)*scale);coef_sum += coef;pix *= coef;s += pix;}val = (int)s / coef_sum;if (val < 0)val = 0;if (val > 255)val = 255;dst_arr[i][j] = val;}}
}

测试代码:

void test_lancos3_resize(dai_image* img, float factor)
{uint8_2d* r = NULL;uint8_2d* g = NULL;uint8_2d* b = NULL;uint8_2d* r1 = NULL;uint8_2d* g1 = NULL;uint8_2d* b1 = NULL;dai_image* img1 = NULL;if (!img)return;split_img_data(img, &r, &g, &b);int w, h;int w1, h1;w = img->width;h = img->height;w1 = factor*w;h1 = factor*h;r1 = create_uint8_2d(h1, w1);g1 = create_uint8_2d(h1, w1);b1 = create_uint8_2d(h1, w1);img_resize_using_lancos3(r, r1);img_resize_using_lancos3(g, g1);img_resize_using_lancos3(b, b1);merge_img_data(r1, g1, b1, &img1);if (img1){img1->type = EJPEG;dai_save_image("resize_lancos3.jpg", img1);dai_destroy_image(&img1);}destroy_uint8_2d(&r);destroy_uint8_2d(&g);destroy_uint8_2d(&b);destroy_uint8_2d(&r1);destroy_uint8_2d(&g1);destroy_uint8_2d(&b1);
}

效果图:
原图:

缩小3倍的图:


另外,缩小之后,图像相对变暗,这时,可以采用gama校正改变亮度。

参考文献:
1、http://www.realitypixels.com/turk/computergraphics/ResamplingFilters.pdf
2、https://en.wikipedia.org/wiki/Lanczos_resampling
3、https://github.com/richgel999/imageresampler

图像Lanczos3滤波——C实现相关推荐

  1. 图像Lanczos3滤波C实现——优化

    上一篇博文给出了图像Lanczos3滤波的直观实现,但是整个算法实现过于低效,其原因在于对于每个插值点,都需要重新计算Lanczos系数,本文参考https://github.com/richgel9 ...

  2. 【python图像处理】图像的滤波(ImageFilter类详解)

    在图像处理中,经常需要对图像进行平滑.锐化.边界增强等滤波处理.在使用PIL图像处理库时,我们通过Image类中的成员函数filter()来调用滤波函数对图像进行滤波,而滤波函数则通过ImageFil ...

  3. 【转】由投影重建图像:滤波反投影、FDK、TFDK三维重建算法理论基础

    转自:由投影重建图像:滤波反投影.FDK.TFDK三维重建算法理论基础_m0_37357063的博客-CSDN博客_fdk算法 1. 基础理论从: [1] RafaelC.Gonzalez, Rich ...

  4. C语言数字图像处理---2.3图像空域滤波

    本文主要给大家讲解图像空间域滤波的相关内容,包括空域滤波概念,以及常用的空域滤波算法,并通过C语言编程来实现几种常用空域滤波(均值滤波.中值滤波.最大值滤波.最小值滤波.高斯滤波和统计滤波),帮助初学 ...

  5. C语言数字图像处理---2.5图像频域滤波

    上一小节我们介绍了图像频域变换,本小节将以此为基础,介绍图像频域滤波的相关内容,包含常见高通/低通/带通/带阻/方向滤波等频域滤波方法,同时以C语言编码实现,帮助初学者理解和掌握如何进行图像的频域滤波 ...

  6. OpenCV图像各向异性滤波

    OpenCV图像各向异性滤波 各向异性概念 各向异性(英文名称:anisotropy)是指材料在各方向的力学和物理性能呈现差异的特性.晶体的各向异性即沿晶格的不同方向,原子排列的周期性和疏密程度不尽相 ...

  7. 【OpenCV图像处理】十五、图像空域滤波(上)

    1.空域滤波介绍 空域滤波是一种邻域处理方法,通过直接在图像空间中对邻域内像素进行处理,达到平滑或锐化图像的作用.此外,在图像识别中,通过滤波还可以抽出图像的特征作为图像识别的特征模式. 空域滤波是图 ...

  8. 【OpenCV图像处理】十六、图像空域滤波(下)

    空域滤波的后半部分主要讲图像的锐化相关操作. 图像锐化: 由于成像机理和成像设备的限制,尤其是对于一些专用成像设备,如医学成像,遥感成像和视频捕获等等,所成图像可能会变得模糊.图像锐化的作用就是增强图 ...

  9. java 图像傅里叶变换_图像频域滤波与傅里叶变换

    1.频率滤波 图像的空间域滤波:用各种模板直接与图像进行卷积运算,实现对图像的处理,这种方法直接对图像空间操作,操作简单.图像处理不仅可以在空间域进行还可以在频率域进行,把空间域的图像开窗卷积形式,变 ...

最新文章

  1. linux重新编译mysql_linux下编译安装mysql++ | 学步园
  2. 火影忍者手游服务器维护4月4,火影忍者手游4月14日联服公告-火影忍者手游4月14日联服时间_牛游戏网...
  3. VTK:Rendering之StripFran
  4. java 日期及别的小技巧
  5. python3多线程第三方库_Python3 多线程
  6. [Pku 2774] 字符串(六) {后缀数组的构造}
  7. mysql一对多增删改查_SQLAlchemy 增删改查 一对多 多对多
  8. 四个角不是直角的四边形_同步资料人教版四上数学第五单元平行四边形和梯形5.1...
  9. 运行python的两种方式磁盘式_python计算机基础-Day1
  10. yolov5的wts权重转成tensorrt的engine权重一定要注意的问题:版本匹配(有什么问题可以私信我)
  11. Java异常处理机制(基础知识)
  12. 何万青:7月24日阿里云上海峰会超算大神
  13. 基于Python编写的倒计时工具
  14. 第21期状元简讯:自贸区首个跨境电商平台将上线
  15. 苹果手机网页上点击数字可能拨打电话的解决办法
  16. 计算机硬盘有坏道,电脑硬盘有坏道怎么办
  17. Xmarks无法同步问题解决(转)
  18. PDFbox-PDF解析(坐标定位,分页读取)
  19. 三年程序员生涯的感悟、总结和憧憬
  20. 淘宝联盟 淘宝客私域用户管理 百川SDK 接入简介

热门文章

  1. vue2使用element日期选择控件显示农历数据
  2. div css实现进度条
  3. chp2-2-2_fmm_word_seg通过最大正向匹配算法对句子进行切分
  4. 信号能量密度公式_信号时频分析方法汇总
  5. php冰蝎一句话,利用动态二进制加密实现新型一句话木马之PHP篇(转)冰蝎
  6. 计算机组成原理 — CPU — 多核处理器体系结构
  7. linux+swap分区规则_linux关于swap分区的划分规则
  8. 指点迷津!十二星座程序猿个性,你属于哪个?
  9. PAT甲级Invert a Binary Tree 柳神层序遍历的思路值得借鉴
  10. 重磅消息:Lazada和Shopee通过中国执照就可以开通本地店铺,享受更多的流量和资源扶持