概述
今天闲来无事把经典的颜色迁移文章来拿看看,突然发现自己还没动手实现过color transfer between images这篇文章,想当初自己的毕业设计就是做的这个,真是有点惭愧。
关于这篇文章的代码网上有很多,但是我找了很久,发现现在网上的代码有一个通病,一个是很乱,另一个是很多都是转载的,作者自己肯定都不太清楚是什么代码就转过来了,结果误导了很多想学习的好同志,所以决定以后养成好习惯,遇到好的代码要自己记下来,或者发到博客上一遍保存和以后自己拿出来翻看。
有一篇比较好的文章是在rachel-zhang(我的女神)的博客上看到的,代码写的非常清晰,模块也分得很好,几分钟就看明白了,不过她的代码都是在RGB空间直接进行颜色迁移的,代码如下:
#include "iostream"
#include <opencv2opencv.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);
}
还是用上面的图片,不过结果稍有不同:
可以看到结果差别还是有的,迁移之后的图像效果更好。
最后
以上就是动听山水为你收集整理的color transfer between images论文实现的全部内容,希望文章能够帮你解决color transfer between images论文实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复