颜色迁移之五——自适应迁移算法

颜色空间为一个三维的线性空间,通常使用红色、绿色和蓝色(RGB)作为颜色空间的基,但这三原色不能直观地度量色调、饱和度和亮度(HSV),为了体现颜色空间中的不同特性,人们总结了很多颜色空间。由Smith等提出的LMS颜色空间的三个分量分别表示长、中、短激发光谱。而人的视网膜中锥状细胞的光感器对光的波长最敏感。在这个意义上,我们把计算机里的RGB图像表示转换成基于人眼更为敏感波长的LMS表示。实际上不同颜色空间是同构的,因此它们之间必然存在变换矩阵,事实上在Reinhard等给出了RGB和LMS之间的颜色变换,经过变换后的LMS值的分布域和RGB
值的分布域一样,还是比较发散,为了使得LMS数据点更加聚敛,Reinhard等对LMS做了对数变换L=logL,M=logM,S=logS来代替LMS的值。胡国飞等在此基础上求出了LMS的相关矩阵

其中rLM,rMS,rLS分别表示L和M,M和S,L和S的相关系数。大量图像样本的实验结果表明相关矩阵通常不是一个三对角矩阵,甚至根本不是对角占优的矩阵,也就是说LMS三个分量间具有严重的相关性。然后利用特征值分析和主元分析方法来得到复合线性变换矩阵,对LMS值采取一系列平移旋转和变比的线性变换,使得所得的图像各像素的颜色分量基本上消除这种相关性。根据矩阵论,很容易地对相关矩阵进行特征值分解,求出特征值λ1,λ2,λ3和特征向量e1,e2,e3,并记特征矩阵为

然后由求出负载因子矩阵,接着就可以求出LMS到lαβ颜色空间的基向量的过渡矩阵(其中为特征值矩阵的逆),这个C就是要求的复合变换矩阵,即。

对每一幅欲处理的图像,都有不同的过渡矩阵C。利用对自适应的处理颜色图像和形状图像所得到的和,分别求出各自的lαβ颜色空间上的值。而不是利用一个固定的C来处理所有的图像。虽然此算法在运算时间上付出一点代价,自适应的方法更符合图像本身的颜色分布。另外,对一幅图像的所有像素进行处理可以增加统计量的精确度,但是出于计算速度和存储资源考虑,也可以间隔采样以减少处理的数据量,而不影响整体效果。

——————————————————————————————————————-——————————————————————

用的一些函数,其他的大部分参考我之前写的Reinhard算法的给出代码

//矩阵求特征值与特征向量
bool JacbiCor(double *pMatrix,int nDim, double *pdblVects, double *pdbEigenValues, double dbEps,int nJt)
{
	for(int i = 0; i < nDim; i ++)
	{
		pdblVects[i*nDim+i] = 1.0f;
		for(int j = 0; j < nDim; j ++)
		{
			if(i != j)
				pdblVects[i*nDim+j]=0.0f;
		}
	}   

	int nCount = 0;     //迭代次数
	while(1)
	{
		//在pMatrix的非对角线上找到最大元素
		double dbMax = pMatrix[1];
		int nRow = 0;
		int nCol = 1;
		for (int i = 0; i < nDim; i ++)          //行
		{
			for (int j = 0; j < nDim; j ++)      //列
			{
				double d = fabs(pMatrix[i*nDim+j]);   

				if((i!=j) && (d> dbMax))
				{
					dbMax = d;
					nRow = i;
					nCol = j;
				}
			}
		}  

		if(dbMax < dbEps)     //精度符合要求
			break;    

		if(nCount > nJt)       //迭代次数超过限制
			break;  

		nCount++;  

		double dbApp = pMatrix[nRow*nDim+nRow];
		double dbApq = pMatrix[nRow*nDim+nCol];
		double dbAqq = pMatrix[nCol*nDim+nCol];  

		//计算旋转角度
		double dbAngle = 0.5*atan2(-2*dbApq,dbAqq-dbApp);
		double dbSinTheta = sin(dbAngle);
		double dbCosTheta = cos(dbAngle);
		double dbSin2Theta = sin(2*dbAngle);
		double dbCos2Theta = cos(2*dbAngle);  

		pMatrix[nRow*nDim+nRow] = dbApp*dbCosTheta*dbCosTheta +
			dbAqq*dbSinTheta*dbSinTheta + 2*dbApq*dbCosTheta*dbSinTheta;
		pMatrix[nCol*nDim+nCol] = dbApp*dbSinTheta*dbSinTheta +
			dbAqq*dbCosTheta*dbCosTheta - 2*dbApq*dbCosTheta*dbSinTheta;
		pMatrix[nRow*nDim+nCol] = 0.5*(dbAqq-dbApp)*dbSin2Theta + dbApq*dbCos2Theta;
		pMatrix[nCol*nDim+nRow] = pMatrix[nRow*nDim+nCol];  

		for(int i = 0; i < nDim; i ++)
		{
			if((i!=nCol) && (i!=nRow))
			{
				int u = i*nDim + nRow;  //p
				int w = i*nDim + nCol;  //q
				dbMax = pMatrix[u];
				pMatrix[u]= pMatrix[w]*dbSinTheta + dbMax*dbCosTheta;
				pMatrix[w]= pMatrix[w]*dbCosTheta - dbMax*dbSinTheta;
			}
		}   

		for (int j = 0; j < nDim; j ++)
		{
			if((j!=nCol) && (j!=nRow))
			{
				int u = nRow*nDim + j;  //p
				int w = nCol*nDim + j;  //q
				dbMax = pMatrix[u];
				pMatrix[u]= pMatrix[w]*dbSinTheta + dbMax*dbCosTheta;
				pMatrix[w]= pMatrix[w]*dbCosTheta - dbMax*dbSinTheta;
			}
		}  

		//计算特征向量
		for(int i = 0; i < nDim; i ++)
		{
			int u = i*nDim + nRow;      //p
			int w = i*nDim + nCol;      //q
			dbMax = pdblVects[u];
			pdblVects[u] = pdblVects[w]*dbSinTheta + dbMax*dbCosTheta;
			pdblVects[w] = pdblVects[w]*dbCosTheta - dbMax*dbSinTheta;
		}   

	}  

	for(int i = 0; i < nDim; i ++)
			pdbEigenValues[i] = pMatrix[i*nDim+i];   

	//设定正负号
	for(int i = 0; i < nDim; i ++)
	{
		double dSumVec = 0;
		for(int j = 0; j < nDim; j ++)
			dSumVec += pdblVects[j * nDim + i];
		if(dSumVec<0)
		{
			for(int j = 0;j < nDim; j ++)
				pdblVects[j * nDim + i] *= -1;
		}
	}
	return 1;
}
//矩阵求逆
void InverseMatrix(double A[3][3],double B[3][3],int n)
{
	int i,j,k,m=2*n;
	double mik,temp;
	double a[3][6]={0};

	for(i=0;i<n;i++)
	{
		for(j=0;j<n;j++)
		{
			if(i==j)
				B[i][j]=1.0;
			else
				B[i][j]=0.0;
		}
	}        //初始化B=E

	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			a[i][j]=A[i][j];  //复制A到a,避免改变A的值
	for(i=0;i<n;i++)
		for(j=n;j<m;j++)
			a[i][j]=B[i][j-n];  //复制B到a,增广矩阵

	for(k=1;k<=n-1;k++)
	{
		for(i=k+1;i<=n;i++)
		{
			mik=a[i-1][k-1]/a[k-1][k-1];
			for(j=k+1;j<=m;j++)
			{
				a[i-1][j-1]-=mik*a[k-1][j-1];
			}
		}
	}        //顺序高斯消去法化左下角为零

	for(i=1;i<=n;i++)
	{
		temp=a[i-1][i-1];
		for(j=1;j<=m;j++)
		{
			a[i-1][j-1]/=temp;
		}
	}        //归一化

	for(k=n-1;k>=1;k--)
	{
		for(i=k;i>=1;i--)
		{
			mik=a[i-1][k];
			for(j=k+1;j<=m;j++)
			{
				a[i-1][j-1]-=mik*a[k][j-1];
			}
		}
	}        //逆序高斯消去法化增广矩阵左边为单位矩阵

	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			B[i][j]=a[i][j+n];  //取出求逆结果

	for(i=0;i<n;i++)
		for(j=0;j<n;j++)
			if(fabs(B[i][j])<0.0001)
				B[i][j]=0.0;
}

——————————————————————————————————————-——————————————————————

参考文献:胡国飞, 傅健, 彭群生. 自适应颜色迁移[J]. 计算机学报, 2004,27(9):1245-1249.

时间: 2024-10-08 21:49:51

颜色迁移之五——自适应迁移算法的相关文章

服务器迁移之文件服务器迁移(基于WSMT的FSRM)

环境介绍: 某公司现在有一台组装的文件服器(2008R2现有域的成员服务器)!因公司发展及服务器性能等原因,现购一台HP服务器用作新的文件服务器(2008R2),需要将所有旧服务器上的共享目录迁移到新的服务器上,保证数据完整性.共享权限一致! 我以前写过一篇文章,将2003的文件服务器,用FSMT将文件迁移到2008R2环境下,参考以下链接: http://hubuxcg.blog.51cto.com/2559426/458091: 因为2008R2上已有自已的服务器迁移工具:Windows S

EX2010与EX2013共存迁移06-本地迁移

写这篇文章时我们已经进入最后一章节,就是邮箱数据迁移,也有可能还会有其他章节,如:Exchange 2010卸载啊,总之要看大家反馈,到时候视情况而定. Exchange 2013邮箱迁移主要有三种方式: 1)本地:不同数据库之间邮箱迁移. 2)跨林:森林之间的邮箱迁移. 3)远程:在混合部署中的Exchange组织与Exchange Online或异构邮件系统之间的迁移. Exchange 2013迁移增加了一些新的特性 1)能大批量移动多个邮箱(默认20.最大100) 2)电子邮件通知移动完

EF CodeFirs 代码迁移、数据迁移

最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精    标题叫EF CodeFirs 代码迁移.数据迁移. 那么:到底叫代码迁移还是数据迁移?我在网上看了大半天,怎么叫的都有,后来查了MSDN,MSDN上叫代码迁移.在此,我们也称之为代码迁移. 为什么有人将其称为数据迁移呢?可能是因为本节内容和操作数据库有关<增加一张表,删除一张表,增加一个表字段,删除一个表字段,修改一个表字段等>,所以网友称之为数

CentOS7.4——KVM虚拟化二 共享存储之动态迁移与静态迁移

KVM虚拟化二 共享存储之动态迁移与静态迁移 目录第一部分 运行环境第二部分 配置nfs共享服务器第三部分 配置kvm服务器并实现动态迁移第四部分 配置静态迁移 第一部分 运行环境 KVM虚拟机两台(linux 7.4)IP地址:192.168.80.40(kvm01)IP地址:192.168.80.50(kvm02)注意:kvm01上需要有一个镜像文件,此处不再详细说明,基本配置操作请考上一个文档http://blog.51cto.com/12227558/2097113 共享服务器一台(li

虚拟机的迁移(热迁移)

迁移: 系统的迁移是指把源主机上的操作系统和应用程序移动到目的主机,并且能够在目的主机上正常运行 迁移的目的: 1.简化系统维护管理 2.高系统负载均衡 3.增强系统错误容忍度 4.优化系统电源管理 KVM 虚拟机的热迁移 ---Live Migration 热迁移(又叫动态迁移.实时迁移),即虚拟机保存( save ) / 恢复 (restore) :将整个虚拟机的运行状态完整保存下来,同时可以快速的恢复到原有硬件平台甚至是不同硬件平台上.恢复以后,虚拟机仍旧平滑运行,用户不会察觉到任何差异.

DHCP服务器迁移(Win2003迁移到Win2008R2)

公司的DHCP服务器当初搭建的时候是Win2003,很多年一直未升级.考虑到SCCM存储空间有限,WSUS下载的补丁包越来越多,决定把Win2008R2以下的系统全部换掉,删除Win2008 SP2和Win2003的更新包.近期把Windows 2008 SP2(x64位)升级到2008R2,而DHCP是Win2003(32位)无法升级,于是迁移到2008R2.因不想修改交换机 ip helper-address,使用原来的服务器IP. 步骤如下: 1.在VMware vSphere 环境新建一

Azure 国际篇_新旧版本迁移(二)_迁移VHD文件

如果要使用新版本ARM上的资源,例如虚拟网络,存储,网关等等,我们就要把旧版本的Classic 迁移到ARM上.迁移的办法非常简单. 现在RAM的"虚拟机(经典)"上找到旧版本的虚拟机DC01,接下来我们要把这台VM迁移到"虚拟机"这里. 新版本RAM上发虚拟机为空. 在RAM上新建资源组markleong 下载安装Azure Explore:http://storageexplorer.com/,安装完毕后,输入帐号登录,找到旧版本的虚拟机VHD文件.关闭虚拟机后

KVM虚拟机共享存储动态迁移与冷迁移

运行环境一. 配置nfs共享服务器二. 配置KVM虚拟化三. 创建桥接网卡四. 配置kvm服务器并实现动态迁移五. 配置冷迁移运行环境KVM虚拟机两台(linux 7.4)IP地址:192.168.80.100(KVM01)IP地址:192.168.80.200(KVM02)共享服务器一台(linux 7.4)IP地址:192.168.80.102(share) 所有主机都执行:service firewalld stopsetenforce 0 一.配置nfs共享服务器yum install

08r2活动目录迁移升级2012r2--(DHCP迁移)

在目标系统添加DHCP角色服务DHCP角色安装完成,但先不要配置因旧DHCP 作用域配置了故障转移,有3个作用域因历史原因无法取消故障转移配置,且无法删除,在迁移的时候导出DHCP.xml文件的时候编辑该文件,将这3个作用域手动删除后再导入在目标DHCP服务器创建DHCPBak文件夹,用于存放DHCP备份数据在目标DHCP服务器运行命令Export-DhcpServer -ComputerName dc1.xxx.com.cn -Leases -File d:\DHCPBak\dhcp.xml