原文地址:http://blog.csdn.net/hjimce/article/details/46550001

作者:hjimce

一、背景意义

写这篇博文是应为目前为止我看到了好多领域里的经典paper算法都有涉及到移动最小二乘(MLS)。可见这个算法非常重要,先来看一下它的相关经典应用:

1、图像变形。在图像处理领域paper:《Image Deformation Using Moving Least Squares》利用移动最小二乘的原理实现了图像的相关变形,而且这篇paper的引用率非常高,可以说是图像变形算法的经典算法,Siggraph上面的paper。

利用移动最小二乘实现图像变形

2、点云滤波。利用MLS实现点云滤波,是三维图像学点云处理领域的一大应用,我所知道点云滤波经典算法包括:双边滤波、MLS、WLOP。

3、Mesh Deformation。用这个算法实现三角网格模型的变形应用也是非常不错的,相关的paper《3D Deformation Using Moving Least Squares》

OK,接着我就以《Image Deformation Using Moving Least Squares》算法为例,进行讲解基于移动最小二乘的图像变形算法实现。

二、算法实现

在这里我没有打算将算法原理的推导过程,直接讲算法的实现步骤公式。

这篇paper根据变换矩阵的不同,可以分为三种变形方法,分别是仿射变换、相似变换、刚性变换。其中刚性变换的效果是最好的,我这边从简单的讲,只讲仿射变换的变形算法实现:

问题:原图像的各个控制顶点坐标p,原图像上的像素点v的坐标。变形后图像的控制顶点位置q,求v在变形后图像中对应位置f(v)。

总计算公式为:

上面中lv(x)和f(v)是同一个函数。因为x就是我们输入的原图像的像素点坐标v。

因此我们的目标就是要知道p*,q*,变换矩阵M。这样输入一个参数x,我们就可以计算出它在变换后图像中的位置了。

OK,只要我们知道上面公式中,各个参数的计算方法,我们就可以计算出变形后图像对应的坐标点f(v)了。

1、权重w的计算方法为:

也就是计算v到控制顶点pi的距离倒数作为权重,参数a一般取值为1。

这一步实现代码如下:

[cpp] view plaincopy
  1. //计算各个控制顶点的权重,也就是计算点t到各个顶点的距离1/sqr(d)
  2. while(iter!=p.end())
  3. {
  4. double temp;
  5. if(iter->x!=t.x || iter->y!=t.y)
  6. temp=1/((iter->x-t.x)*(iter->x-t.x)+(iter->y-t.y)*(iter->y-t.y));
  7. else//如果t为控制顶点,那么需要把该控制顶点的权重设置为无穷大
  8. temp=MAXNUM;
  9. w.push_back(temp);
  10. iter++;
  11. }

2、q*,p*的计算公式如下:

也就是计算控制顶点pi和qi的加权求和重心位置。

[cpp] view plaincopy
  1. double px=0,py=0,qx=0,qy=0,tw=0;
  2. while(iterw!=w.end())
  3. {
  4. px+=(*iterw)*(iter->x);//所有控制顶点p的加权位置
  5. py+=(*iterw)*(iter->y);
  6. qx+=(*iterw)*(iterq->x);//所有控制顶点q的加权位置
  7. qy+=(*iterw)*(iterq->y);
  8. tw+=*iterw;//总权重
  9. iter++;
  10. iterw++;
  11. iterq++;
  12. }
  13. pc.x=px/tw;
  14. pc.y=py/tw;
  15. qc.x=qx/tw;
  16. qc.y=qy/tw;

3、仿射变换矩阵M的计算公式如下:

只要把相关的参数都带进去就可以计算了。

最后贴一些完整的MLS源代码:

[cpp] view plaincopy
  1. //输入原图像的t点,输出变形后图像的映射点f(v)
  2. MyPoint CMLSDlg::MLS(const MyPoint& t)
  3. {
  4. if(p.empty())//原图像的控制顶点p,与输入点t为同一副图像坐标系下
  5. return t;
  6. MyPoint fv;
  7. double A[2][2],B[2][2],M[2][2];
  8. iter=p.begin();
  9. w.erase(w.begin(),w.end());
  10. //计算各个控制顶点的权重,也就是计算点t到各个顶点的距离1/sqr(d)
  11. while(iter!=p.end())
  12. {
  13. double temp;
  14. if(iter->x!=t.x || iter->y!=t.y)
  15. temp=1/((iter->x-t.x)*(iter->x-t.x)+(iter->y-t.y)*(iter->y-t.y));
  16. else//如果t为控制顶点,那么需要把该控制顶点的权重设置为无穷大
  17. temp=MAXNUM;
  18. w.push_back(temp);
  19. iter++;
  20. }
  21. vector<double>::iterator iterw=w.begin();
  22. vector<MyPoint>::iterator iterq=q.begin();//q为目标图像的控制点的位置,我们的目标是找到t在q中的对应位置
  23. iter=p.begin();
  24. MyPoint pc,qc;
  25. double px=0,py=0,qx=0,qy=0,tw=0;
  26. while(iterw!=w.end())
  27. {
  28. px+=(*iterw)*(iter->x);//所有控制顶点p的加权位置
  29. py+=(*iterw)*(iter->y);
  30. qx+=(*iterw)*(iterq->x);//所有控制顶点q的加权位置
  31. qy+=(*iterw)*(iterq->y);
  32. tw+=*iterw;//总权重
  33. iter++;
  34. iterw++;
  35. iterq++;
  36. }
  37. pc.x=px/tw;
  38. pc.y=py/tw;
  39. qc.x=qx/tw;
  40. qc.y=qy/tw;
  41. iter=p.begin();
  42. iterw=w.begin();
  43. iterq=q.begin();
  44. for(int i=0;i<2;i++)
  45. for(int j=0;j<2;j++)
  46. {
  47. A[i][j]=0;
  48. B[i][j]=0;
  49. M[i][j]=0;
  50. }
  51. while(iter!=p.end())
  52. {
  53. double P[2]={iter->x-pc.x,iter->y-pc.y};
  54. double PT[2][1];
  55. PT[0][0]=iter->x-pc.x;
  56. PT[1][0]=iter->y-pc.y;
  57. double Q[2]={iterq->x-qc.x,iterq->y-qc.y};
  58. double T[2][2];
  59. T[0][0]=PT[0][0]*P[0];
  60. T[0][1]=PT[0][0]*P[1];
  61. T[1][0]=PT[1][0]*P[0];
  62. T[1][1]=PT[1][0]*P[1];
  63. for(int i=0;i<2;i++)
  64. for(int j=0;j<2;j++)
  65. {
  66. A[i][j]+=(*iterw)*T[i][j];
  67. }
  68. T[0][0]=PT[0][0]*Q[0];
  69. T[0][1]=PT[0][0]*Q[1];
  70. T[1][0]=PT[1][0]*Q[0];
  71. T[1][1]=PT[1][0]*Q[1];
  72. for(int i=0;i<2;i++)
  73. for(int j=0;j<2;j++)
  74. {
  75. B[i][j]+=(*iterw)*T[i][j];
  76. }
  77. iter++;
  78. iterw++;
  79. iterq++;
  80. }
  81. //cvInvert(A,M);
  82. double det=A[0][0]*A[1][1]-A[0][1]*A[1][0];
  83. if(det<0.0000001)
  84. {
  85. fv.x=t.x+qc.x-pc.x;
  86. fv.y=t.y+qc.y-pc.y;
  87. return fv;
  88. }
  89. double temp1,temp2,temp3,temp4;
  90. temp1=A[1][1]/det;
  91. temp2=-A[0][1]/det;
  92. temp3=-A[1][0]/det;
  93. temp4=A[0][0]/det;
  94. A[0][0]=temp1;
  95. A[0][1]=temp2;
  96. A[1][0]=temp3;
  97. A[1][1]=temp4;
  98. M[0][0]=A[0][0]*B[0][0]+A[0][1]*B[1][0];
  99. M[0][1]=A[0][0]*B[0][1]+A[0][1]*B[1][1];
  100. M[1][0]=A[1][0]*B[0][0]+A[1][1]*B[1][0];
  101. M[1][1]=A[1][0]*B[0][1]+A[1][1]*B[1][1];
  102. double V[2]={t.x-pc.x,t.y-pc.y};
  103. double R[2][1];
  104. R[0][0]=V[0]*M[0][0]+V[1]*M[1][0];//lv(x)总计算公式
  105. R[1][0]=V[0]*M[0][1]+V[1]*M[1][1];
  106. fv.x=R[0][0]+qc.x;
  107. fv.y=R[1][0]+qc.y;
  108. return fv;
  109. }

调用方法示例:

[cpp] view plaincopy
  1. int i=0,j=0;
  2. dImage=cvCreateImage(cvSize(2*pImage->width,2*pImage->height),pImage->depth,pImage->nChannels);//创建新的变形图像
  3. cvSet(dImage,cvScalar(0));
  4. MyPoint Orig=MLS(MyPoint(IR_X,IR_Y));
  5. int Orig_x=(int)(Orig.x)-(int)(pImage->width/2);
  6. int Orig_y=(int)(Orig.y)-(int)(pImage->height/2);
  7. for(i=0;i<pImage->height;i++)//遍历原图像的每个像素
  8. {
  9. for(j=0;j<pImage->width;j++)
  10. {
  11. CvScalar color;
  12. double x=j+IR_X;
  13. double y=i+IR_Y;
  14. MyPoint t=MLS(MyPoint(x,y));//MLS计算原图像(x,y)在目标图像的映射位置f(v)
  15. int m=(int)(t.x);
  16. int n=(int)(t.y);
  17. m-=Orig_x;
  18. n-=Orig_y;
  19. color=cvGet2D(pImage,i,j);//像素获取
  20. if(0<=m && dImage->width>m && 0<=n && dImage->height>n)
  21. {
  22. cvSet2D(dImage,n,m,color);
  23. }
  24. }
  25. }

图像变形算法,有正向映射和逆向映射,如果按照每个像素点,都通过上面的计算方法求取其对应变换后的像素点位置,那么其实计算量是非常大的,因为一幅图像的像素点,实在是太多了,如果每个像素点,都用上面的函数遍历过一遍,那计算量可想而知。

因此一般的变形算法是对待图像进行三角剖分:

然后只根据只对三角网格模型的顶点,根据变形算法,计算出三角网格模型每个顶点的新位置,最后再用三角形仿射变换的方法,计算三角形内每个像素点的值,得到变形后的图像,这样不仅速度快,同事解决了正向映射与逆向映射变形算法存在的不足之处,具体图像变形的正向和逆向映射存在的缺陷,可以自己查看相关的文献。

另外两种相似变换和刚性变换,可以自己查看M矩阵的计算公式,编写实现相关代码。

本文地址:http://blog.csdn.net/hjimce/article/details/46550001     作者:hjimce     联系qq:1393852684   更多资源请关注我的博客:http://blog.csdn.net/hjimce                原创文章,转载请保留本行信息*************

参考文献:

1、《Image Deformation Using Moving Least Squares》

2、《3D Deformation Using Moving Least Squares》

基于移动最小二乘的图像变形相关推荐

  1. 图像处理(十九)基于移动最小二乘的图像变形-Siggraph 2006

    基于移动最小二乘的图像变形 原文地址:http://blog.csdn.net/hjimce/article/details/46550001 作者:hjimce 一.背景意义 写这篇博文是应为目前为 ...

  2. 基于移动最小二乘(MLS)的图像扭曲刚性变形python实现

    基于移动最小二乘(MLS)的图像扭曲刚性变形python实现 简单介绍一下基于mls的图像变形 直接上代码 用来做的一个瘦脸前后对比 写在后面 简单介绍一下基于mls的图像变形 先假设我们的图片像素为 ...

  3. 图像处理(十)基于特征线的图像变形-Siggraph 1992

    这里要跟大家分享的paper为基于特征线的图像 morphing,对应的英文文献为<Feature-Based Image Metamorphosis>,是1992年SIGGRAPH 上的 ...

  4. 图像控制点 形变_基于控制点的图象变形方法及其应用

    基于控制点的图象变形方法及其应用 杨金钟 ; 刘政凯 ; 俞能海 ; 吴皓 [期刊名称] <中国图象图形学报> [年 ( 卷 ), 期] 2001(006)011 [摘要] 根据人脸 , ...

  5. 图像控制点 形变_基于控制点的图像变形方法的研究与实现

    基于控制点的图像变形方法的研究与实现 林军 ; 李新华 [期刊名称] <北京电力高等专科学校学报 ( 自然科学版 ) > [年 ( 卷 ), 期] 2011(028)005 [摘要] 根据 ...

  6. html5动画变形效果,碉堡了,基于HTML5 WebGL的图像扭曲变形动画开源特效

    简要说明 这是一款基于HTML5 WebGL的图像扭曲变形动画特效.该特效中,通过Three.js来制作从一幅缩略图,扭曲变形为全屏大图的动画特效,共有6种炫酷的动画效果. 视频加载中... 该特效提 ...

  7. 图像处理(十三)保刚性图像变形算法-Siggraph 2004

    图像变形可以说是很多图像.动画领域的一个非常常见的功能,就说ps.天天P图.美图秀秀.可牛等这些每个软件,有好多个功能都要用到图像变形,比如图像方向校正.图像全景.视频防抖等,在我的另外一篇博文全景矩 ...

  8. c语言编程图像拼接,一种基于Lucas-Kanade算法的图像配准和拼接方法

    一种基于Lucas-Kanade算法的图像配准和拼接方法 [技术领域] [0001 ]本发明涉及图像处理技术领域,具体涉及一种基于Lucas-Kanade算法的图像配准 和拼接方法. [背景技术] [ ...

  9. 【图像修复】基于matlab深度信息图像修复【含Matlab源码 2299期】

    ⛄一.深度信息图像修复简介 0 引言 图像修复是指对待修复图像中缺损的部分,利用已有的图像信息对缺损区域进行修复,是计算机图像和视觉中的研究热点之一.在图像修复领域,通常采用的是基于块的纹理合成的修复 ...

  10. 基于深度学习的图像超分辨率——综述

    2021-Deep Learning for Image Super-resolution:A Survey 基本信息 作者: Zhihao Wang, Jian Chen, Steven C.H. ...

最新文章

  1. 添加类iOS cocos2d 2游戏开发实战(第3版)
  2. ggplot2设置坐标轴范围_Matplotlib入门-2-坐标轴axis/axes设置
  3. RxJava在闲鱼系统吞吐量提升上的实践
  4. 手写简版spring --9--对象作用域和FactoryBean
  5. JZOJ 5377. 【NOIP2017提高A组模拟9.19】开拓
  6. NOIP2013Day1T3 表示只能过一个点
  7. 100行JavaScript代码实现JavaScript
  8. 数据库---主键约束
  9. 插件不既有Chrome版也有飞鸽传书
  10. 【Express】—路由配置
  11. POJ-1328 Radar Installation 贪心
  12. Linux 安装 informix
  13. 魔方cfop公式软件_【二阶篇】一个万能公式还原二阶魔方
  14. 鼠标失灵了?我来给你解决吧!
  15. 温德姆集团加速麦客达品牌在华扩张;柏悦酒店将进驻长沙;希尔顿惠庭中国首店将在深圳开业 | 美通社头条...
  16. 全新 Amazon RDS for MySQL 和 PostgreSQL 多可用区 (Multi-AZ) 部署选项
  17. Erdaicms旅游网站程序微信和手机端分销系统正式上线发布啦
  18. Android开源的社交应用
  19. 访问控制模型总结(DAC MAC RBAC ABAC)
  20. 计算机多媒体处理的是什么意思,多媒体系统是什么意思有什么组成

热门文章

  1. STL中的关联式容器——map(映射)
  2. Mac下关于ssh命令的简化
  3. ZeroMQ之Request/Response (Java)
  4. 使用PYTHON列表生成式过滤数据
  5. 杭电1181--变形课(Dfs)
  6. CentOS7/RHEL7 systemd详解
  7. 【趣文翻译】如何用各种编程语言杀死一条龙,PHP大亮 [转]
  8. 数据结构 - 字符串的模式匹配
  9. Cassandra -- Cassandra 3.0版本安装
  10. Python爬虫开发【第1篇】【正则表达式】