您的位置:首页 > Web前端

color transfer between images论文实现

2016-01-28 20:28 387 查看
今天闲来无事把经典的颜色迁移文章来拿看看,突然发现自己还没动手实现过color transfer between images这篇文章,想当初自己的毕业设计就是做的这个,真是有点惭愧。

关于这篇文章的代码网上有很多,但是我找了很久,发现现在网上的代码有一个通病,一个是很乱,另一个是很多都是转载的,作者自己肯定都不太清楚是什么代码就转过来了,结果误导了很多想学习的好同志,所以决定以后养成好习惯,遇到好的代码要自己记下来,或者发到博客上一遍保存和以后自己拿出来翻看。

有一篇比较好的文章是在rachel-zhang(我的女神)的博客上看到的,代码写的非常清晰,模块也分得很好,几分钟就看明白了,不过她的代码都是在RGB空间直接进行颜色迁移的,代码如下:

#include "iostream"
  #include <opencv2\opencv.hpp>
  #include <highgui.h>
  using namespace std;
  

  
  IplImage* Transform(IplImage* A,CvScalar avg_src, CvScalar avg_dst,CvScalar std_src, CvScalar std_dst)
  {
  	for(int i=0;i<3;i++)
  	{
  		for(int x=0;x<A->height;x++)
  		{
  			uchar *ptr=(uchar*)(A->imageData+x*A->widthStep);
  			for(int y=0;y<A->width;y++)
  			{
  				double tmp=ptr[3*y+i];
				int t=(int)((tmp-avg_dst.val[i])*(std_src.val[i]/std_dst.val[i])+avg_src.val[i]);
  				t = t<0?0:t;
  				t = t>255?255:t;
  				ptr[3*y+i]=t;
  			}
  		}
  	}
  	return A;
  }
  
  int main()
  {
  	//load 
  	IplImage* source = cvLoadImage("..\\Images\\snow.jpeg",CV_LOAD_IMAGE_COLOR);  
  	IplImage* dst = cvLoadImage("..\\Images\\grass.jpg",CV_LOAD_IMAGE_COLOR);
  	IplImage* dstlab = cvCreateImage(cvGetSize(dst),dst->depth,dst->nChannels);  
  	IplImage* res  = cvCreateImage(cvGetSize(dst),dst->depth,dst->nChannels);
  
   	dstlab = cvCloneImage(dst);

  	//calculate average and standard derivation
  	CvScalar avg_src,avg_dst,std_src, std_dst; 
  	cvAvgSdv(source,&avg_src,&std_src);
  	cvAvgSdv(dstlab, &avg_dst, &std_dst);
  	
	//transform
	dstlab = Transform(dstlab,avg_src,avg_dst,std_src, std_dst);
  	res = cvCloneImage(dstlab);
  	cvSaveImage("..\\Images\\out.jpg",res);
  	
  	cvWaitKey();
  
  	cvReleaseImage(&source);
  	cvReleaseImage(&dst);
  	cvReleaseImage(&dstlab);
  	cvReleaseImage(&res);
	getchar();
  }
代码很简单,就一个函数调用,直接对每个像素进行均值和方差的运算,最后得到输出图像

其中输入图片为



样本图片为:



使用上诉代码的运行结果为:(忽略图片大小问题,为了便于排版所有图片均为截图)



但是color transfer between images论文提到的方法需要把图片转换到LAB空间,所以我就想大概转换到LAB空间之后处理的效果会不一样,所以对代码稍作修改,改为下面的:

#include <highgui.h>
#include <cv.h>
#include <iostream>

using namespace std;

IplImage* Transform(IplImage* A,CvScalar avg_dst,CvScalar avg_src,  CvScalar std_dst,CvScalar std_src)
  {
  	for(int i=0;i<3;i++)
  	{
  		for(int x=0;x<A->height;x++)
  		{
  			uchar *ptr=(uchar*)(A->imageData+x*A->widthStep);
  			for(int y=0;y<A->width;y++)
  			{
  				double tmp=ptr[3*y+i];
				int t=(int)((tmp-avg_dst.val[i])*(std_src.val[i]/std_dst.val[i])+avg_src.val[i]);
  				t = t<0?0:t;
  				t = t>255?255:t;
  				ptr[3*y+i]=t;
  			}
  		}
  	}
  	return A;
  }
int main()
{
	IplImage *src = cvLoadImage("grass.jpg",CV_LOAD_IMAGE_COLOR);
	IplImage *dst = cvLoadImage("snow.jpeg",CV_LOAD_IMAGE_COLOR);
	IplImage *out = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
	cvNamedWindow("first",CV_WINDOW_AUTOSIZE);
	cvNamedWindow("good",CV_WINDOW_AUTOSIZE);
	cvShowImage("first",src);
	cvShowImage("good",dst);

	IplImage *srclab = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
	IplImage *dstlab = cvCreateImage(cvGetSize(dst),dst->depth,dst->nChannels);

	cvCvtColor(src,srclab,CV_BGR2Lab);
	cvCvtColor(dst,dstlab,CV_BGR2Lab);

	CvScalar avg_src,avg_dst,std_src, std_dst; 
  	cvAvgSdv(srclab,&avg_src, &std_src);
	cvAvgSdv(dstlab,&avg_dst, &std_dst);
	
	cout<<"hello"<<endl;
	out = Transform(srclab,avg_src,avg_dst,std_src,std_dst);

	IplImage* outimage = cvCreateImage(cvGetSize(src),src->depth,src->nChannels);
	cvCvtColor(out,outimage,CV_Lab2BGR);
	cvNamedWindow("second",CV_WINDOW_AUTOSIZE);
	cvShowImage("second",outimage);

	cvWaitKey(0);
	cvReleaseImage(&src);
	cvReleaseImage(&dst);
	cvReleaseImage(&srclab);
	cvReleaseImage(&dstlab);
	cvWaitKey(0);
}

还是用上面的图片,不过结果稍有不同:



可以看到结果差别还是有的,迁移之后的图像效果更好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: