题目:
可以根据课程 PPT 和对应参考文献(“Color transfer between images”)实现颜色转换。
(a) 测试图像集合不低于 5 对图像(参考图和原图);
(b) 最后对实验结果进行分析,特别是存在问题进行分析,给出初步的改进建议方法和给出参考文献。
图像间的颜色转化:
这个算法的核心关键在于两部分:
- 1是rgb空间和lab空间的相互转化
- 2是在lab空间根据两幅图提取的均值和标准差进行转换处理
rgb-lab
CImg<float> ImgConverse::RGB_LAB(CImg<float> picture, float *mean, float *std) {
CImg<float> pic = picture;
float sum[3];
float sum_std[3];
for (int i = 0; i < 3; i++) {
sum[i] = 0.0; sum_std[i] = 0.0;
}
int size = pic.width()*pic.height();
cimg_forXY(pic, x, y) {
float r = pic(x, y, 0);
float g = pic(x, y, 1);
float b = pic(x, y, 2);
float L = 0.3811 * r + 0.5783 * g + 0.0402 * b;
float M = 0.1967 * r + 0.7244 * g + 0.0782 * b;
float S = 0.0241 * r + 0.1288 * g + 0.8444 * b;
if (L == 0) L = log(1); else L = log(L);
if (M == 0) M = log(1); else M = log(M);
if (S == 0) S = log(1); else S = log(S);
float l = (1.0 / sqrt(3)) * (L + M + S);
float A = 1.0 / sqrt(6) * L + 1.0 / sqrt(6) * M - 2.0 / sqrt(6) * S;
float B= 1.0 / sqrt(2) * L - 1.0 / sqrt(2) * M;
pic(x, y, 0) = l; pic(x, y, 1) = A; pic(x, y, 2) = B;
sum[0] += l;
sum[1] += A;
sum[2] += B;
}
mean[0] = sum[0] / size;
mean[1] = sum[1] / size;
mean[2] = sum[2] / size;
cimg_forXY(pic, x, y) {
sum_std[0] += pow((pic(x, y, 0) - mean[0]), 2);
sum_std[1] += pow((pic(x, y, 1) - mean[1]), 2);
sum_std[2] += pow((pic(x, y, 2) - mean[2]), 2);
}
std[0] = sqrt(sum_std[0] / size);
std[1] = sqrt(sum_std[1] / size);
std[2] = sqrt(sum_std[2] / size);
return pic;
}
lab-rgb
CImg<float> ImgConverse::LAB_RGB(CImg<float> picture) {
CImg<float> pic = picture;
cimg_forXY(pic, x, y) {
float L = sqrt(3) / 3 * pic(x, y, 0) + sqrt(6) / 6 * pic(x, y, 1) + sqrt(2) / 2 * pic(x, y, 2);
float M = sqrt(3) / 3 * pic(x, y, 0) + sqrt(6) / 6 * pic(x, y, 1) - sqrt(2) / 2 * pic(x, y, 2);
float S = sqrt(3) / 3 * pic(x, y, 0) - sqrt(6) / 3 * pic(x, y, 1);
L = exp(L);
M = exp(M);
S = exp(S);
pic(x, y, 0) = 4.4679 * L - 3.5873 * M + 0.1193 * S;
pic(x, y, 1) = -1.2186 * L + 2.3809 * M - 0.1624 * S;
pic(x, y, 2) = 0.0497 * L - 0.2439 * M + 1.2045 * S;
}
return pic;
}
转化处理:
void ImgConverse::colorTransfer() {
sourceImg.display("源图");
targetImg.display("目标图");
sourcelab = RGB_LAB(sourceImg, mean0, std0);
targetlab = RGB_LAB(targetImg, mean1, std1);
result = sourcelab;
cimg_forXY(result, x, y) {
result(x, y, 0) = (result(x, y, 0) - mean0[0])*std1[0] / std0[0] + mean1[0];
result(x, y, 1) = (result(x, y, 1) - mean0[1])*std1[1] / std0[1] + mean1[1];
result(x, y, 2) = (result(x, y, 2) - mean0[2])*std1[2] / std0[2] + mean1[2];
}
//targetlab = LAB_RGB(targetlab);
result = LAB_RGB(result);
result.display("结果图");
}
测试效果:
先拿ppt上的测试图进行一个效果测试,发现结果还不错。
之后又测试了几张图
效果分析:
从以上多张图的效果分析我们可以看出算法只是以参考区域的色彩信息作为准则,而完全忽略了目标区域的边缘,纹理等细节信息,只追求色彩与参考区域的完全一致,可能会使目标区域的细节信息过度丢失。通俗的说也就是有的图片效果会给人一种蒙蒙的感觉。
所以想到的解决方法也是用边缘分割以及通过调整梯度的阈值来获取局部边缘纹理等信息,通过调整不同目标对象的颜色迁移的幅度大小,实现的功能是类似与photoshop中添加蒙版以及通过调整流量和不透明度来是图片融合效果不显得那么突兀。
参考文献:
-
Color transfer between images
-
Novel Algorithm for Local Color Transfer Based on Preserving Detail Texture
完整代码参见:
https://github.com/WangPerryWPY/Computer-Version/tree/master/Exp4