颜色迁移之二——Reinhard经典算法
来源:互联网 发布:windows触摸屏无法使用 编辑:程序博客网 时间:2024/05/22 12:03
接自上一篇“基础知识”,本文里的色彩空间的转换不再赘述。。。
Reinhard等人根据lαβ颜色空间中各通道互相不关联的特点,提出了一组适用于各颜色分量的色彩迁移公式,较好的实现了彩色图像之间的色彩迁移。基本思想就是根据着色图像的统计分析确定一个线性变换,使得目标图像和源图像在lαβ空间中具有同样的均值和方差。
因此需要计算两幅图像的均值和标准方差。假设l、a、b分别是源图像lαβ通道原有的数据,L、A、B分别是变换后得到新的源图像lαβ通道的值,ml、ma、mb和ml’、ma’、mb’分别是源图像和着色图像的三个颜色通道的均值,nl、na、nb和nl’、na’、nb’表示它们的标准方差。
首先,将源图像原有的数据减掉源图像的均值
L = l – ml
A = a – ma
B = b – mb
再将得到的新数据按比例放缩,其放缩系数是两幅图像标准方差的比值
L’ = (nl’ / nl)* L
A’ = (na’ / na)* A
B’ = (nb’ / nb)* B
将得到的l’、a’、b’分别加上目标图像三个通道的均值,得到最终数据
L = L’ + ml’
A = A’ + ma’
B = B’ + mb’
整理后得到目标图像与源图像之间的像素关系表达
L = (nl’ / nl)* (l – ml) + ml’
A = (na’ / na)* (a – ma) + ma’
B = (nb’ / nb)* (b – mb) + mb’
事实上这组式子表示的就是一个线性方程,以两幅图像的标准方差的比值作为斜率,两幅图像各个通道的均值作为一个点。这个简单的线性变换保证了目标图像和着色图像在lαβ颜色空间中具有相同的均值和方差。将变换后l、α、β的值作为新图像三个通道的值,然后显示的时候再将这三个通道转换为RGB值进行显示。
图 reinhard算法效果图
Reinhard 等人的色彩迁移算法的优点是实现简单,且运行效率很高。但该算法由于是整体色彩迁移,因此它对全局颜色基调单一的图像的有着良好的迁移效果。而对于颜色内容丰富的图像,则效果并不那么明显。一般解决方式是引入人机交互选取样本块的方法,同时还要求用户指定样本块之间的对应关系。这样就给用户增加了许多繁琐的交互。当图像的色彩比较复杂时,用户是无法手工精确地选取样本块的,此时,该算法也将失去作用。
BOOL TranRein(LPBYTE lpDIBBits, LONG lmageWidth, LONG lmageHeight,LPBYTE lpDIBBits2, LONG lmageWidth2, LONG lmageHeight2,LPBYTE lpDIBBits3){int i;int j;int nindex;double al,aa,ab,vl,va,vb,al2,aa2,ab2,vl2,va2,vb2;double* lpImageLab = new double[lmageWidth*lmageHeight*3];double* lpImageLab2 = new double[lmageWidth2*lmageHeight2*3];double* lpImageLab3 = new double[lmageWidth*lmageHeight*3];//目标图像转换为lab,并求lab的均值及标准差for(j = 0;j <lmageHeight; j++){for(i = 0; i <lmageWidth; i++){nindex=((lmageHeight-j-1)*lmageWidth+i);RgbToLab(lpDIBBits[nindex*3+2],lpDIBBits[nindex*3+1],lpDIBBits[nindex*3+0],lpImageLab[nindex*3+0],lpImageLab[nindex*3+1],lpImageLab[nindex*3+2]);}}AverageVariance(lpImageLab,lmageWidth,lmageHeight,al,aa,ab,vl,va,vb);//源图像转换为lab,并求lab的均值及标准差for(j = 0;j <lmageHeight2; j++){for(i = 0; i <lmageWidth2; i++){nindex=((lmageHeight2-j-1)*lmageWidth2+i);RgbToLab(lpDIBBits2[nindex*3+2],lpDIBBits2[nindex*3+1],lpDIBBits2[nindex*3+0],lpImageLab2[nindex*3+0],lpImageLab2[nindex*3+1],lpImageLab2[nindex*3+2]);}}AverageVariance(lpImageLab2,lmageWidth2,lmageHeight2,al2,aa2,ab2,vl2,va2,vb2);//求结果图像的labfor(i = 0;i <lmageWidth*lmageHeight; i++){lpImageLab3[i*3+0] = (lpImageLab[i*3+0] - al) * vl2/vl + al2;lpImageLab3[i*3+1] = (lpImageLab[i*3+1] - aa) * va2/va + aa2;lpImageLab3[i*3+2] = (lpImageLab[i*3+2] - ab) * vb2/vb + ab2;}//将结果图像的lab转换为RGBfor(j = 0;j <lmageHeight; j++){for(i = 0; i <lmageWidth; i++){nindex=((lmageHeight-j-1)*lmageWidth+i);LabToRgb(lpImageLab3[nindex*3+0],lpImageLab3[nindex*3+1],lpImageLab3[nindex*3+2],lpDIBBits3[nindex*3+2],lpDIBBits3[nindex*3+1],lpDIBBits3[nindex*3+0]);}}return TRUE;}
void AverageVariance(double* lpLab,int Width,int Height,double& al,double& aa,double& ab,double& vl,double& va,double& vb){double suml=0;double suma=0;double sumb=0;double lsuml=0;double lsuma=0;double lsumb=0;//分行求平均,避免和过大而溢出for(int j=0;j<Height;j++){for(int i=0;i<Width;i++){lsuml+=lpLab[(j*Width+i)*3];lsuma+=lpLab[(j*Width+i)*3+1];lsumb+=lpLab[(j*Width+i)*3+2];}suml += lsuml/Width;suma += lsuma/Width;sumb += lsumb/Width;lsuml=lsuma=lsumb=0;}al = suml/Height;aa = suma/Height;ab = sumb/Height;suml=suma=sumb=0;for(int i=0;i<Width*Height;i++){suml += pow(lpLab[i*3]-al,2);suma += pow(lpLab[i*3+1]-aa,2);sumb += pow(lpLab[i*3+2]-ab,2);}vl = sqrt(suml);va = sqrt(suma);vb = sqrt(sumb);}
PS:其中RgbToLab函数与LabToRgb函数在上一篇中。。。。。。。。。。。。。。
代码链接
- 颜色迁移之二——Reinhard经典算法
- 颜色迁移之二——Reinhard经典算法
- 《Reinhard颜色迁移算法》读书笔记
- 颜色迁移之三——Welsh经典算法
- 颜色迁移之三——Welsh经典算法
- 颜色迁移之五——自适应迁移算法
- 颜色迁移之四——模糊聚类(FCM)算法
- C#编程之经典算法——排序(二)
- C#编程之经典算法——查找(二)
- java经典算法之二——分解质因数
- JAVA之经典算法二
- 笔试准备之——C经典算法18例之二
- 数字图像处理——直方图均衡化与颜色迁移算法的c++实现
- 迁移学习:经典算法解析
- 颜色迁移— —重新说说这个
- C#编程之经典算法——递归过程(二)
- 经典算法之二《插入排序》
- 经典排序算法之实现(二)
- 004_005 Python 在不适用引用的时候,创建列表的列表
- 基于浏览器的在线代码编辑器
- 自绘按钮实现颜色选择器
- AVL树及C语言实现
- Java多线程2:synchronized
- 颜色迁移之二——Reinhard经典算法
- 在Eclipse中debug源码OpenERP7.0的步骤
- oracle sql语句
- Windows,linux双系统,删除linux.之后恢复损坏的MBR方法
- SVN问题
- jQueryMobile主题修改的若干问题
- 搜索题
- 找出在数组中出现次数超过一半的那个数
- 06 Unity3D摄像机与层--《程序员学Unity3d》