#include "stdafx.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace cv;
#define max_uchar(a, b) (((a) > (b)) ? (a) : (b))
#define min_uchar(a, b) (((a) < (b)) ? (a) : (b))
// 计算彩色图像均值和标准差
void CompMeanAndVariance(Mat &img, Vec3f &mean3f, Vec3f &variance3f)
{
int row = img.rows;
int col = img.cols;
int total = row * col;
float sum[3] = { 0.0f };
// 均值
uchar *pImg = img.data;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
sum[0] += pImg[3*j + 0];
sum[1] += pImg[3*j + 1];
sum[2] += pImg[3*j + 2];
}
pImg += img.step;
}
mean3f[0] = sum[0] / total;
mean3f[1] = sum[1] / total;
mean3f[2] = sum[2] / total;
memset(sum, 0, sizeof(sum));
// 标准差
pImg = img.data;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
sum[0] += (pImg[3*j + 0] - mean3f[0]) * (pImg[3*j + 0] - mean3f[0]);
sum[1] += (pImg[3*j + 1] - mean3f[1]) * (pImg[3*j + 1] - mean3f[1]);
sum[2] += (pImg[3*j + 2] - mean3f[2]) * (pImg[3*j + 2] - mean3f[2]);
}
pImg += img.step;
}
variance3f[0] = sqrt(sum[0] / total);
variance3f[1] = sqrt(sum[1] / total);
variance3f[2] = sqrt(sum[2] / total);
}
// 颜色转换
void ColorTransfer(Mat &src, Mat &tar, Mat &dst)
{
Mat srcLab, tarLab;
Vec3f srcMean3f, tarMean3f;// 源/目标图像均值
Vec3f srcVariance3f, tarVariance3f;// 源/目标图像标准差
Vec3f ratioVariance3f;// 标准差比例
// BGR空间转Lab空间
cvtColor(src, srcLab, CV_BGR2Lab);
cvtColor(tar, tarLab, CV_BGR2Lab);
// 计算当前图像与目标图像均值及标准差
CompMeanAndVariance(srcLab, srcMean3f, srcVariance3f);
CompMeanAndVariance(tarLab, tarMean3f, tarVariance3f);
// 标准差比
ratioVariance3f[0] = tarVariance3f[0] / srcVariance3f[0];
ratioVariance3f[1] = tarVariance3f[1] / srcVariance3f[1];
ratioVariance3f[2] = tarVariance3f[2] / srcVariance3f[2];
// 计算颜色转换值
int row = srcLab.rows;
int col = srcLab.cols;
uchar *pImg = srcLab.data;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
pImg[3*j + 0] = (uchar)min_uchar(255, max_uchar(0, ratioVariance3f[0] * (pImg[3*j + 0] - srcMean3f[0]) + tarMean3f[0]));
pImg[3*j + 1] = (uchar)min_uchar(255, max_uchar(0, ratioVariance3f[1] * (pImg[3*j + 1] - srcMean3f[1]) + tarMean3f[1]));
pImg[3*j + 2] = (uchar)min_uchar(255, max_uchar(0, ratioVariance3f[2] * (pImg[3*j + 2] - srcMean3f[2]) + tarMean3f[2]));
}
pImg += srcLab.step;
}
// Lab空间转BGR空间
cvtColor(srcLab, dst, CV_Lab2BGR);
}
int main()
{
Mat src = imread("image\\src.jpg");
Mat tar = imread("image\\tar.jpg");
imshow("src", src);
imshow("tar", tar);
// 调色
Mat dst;
//ColorTransfer(src, tar, dst);
imshow("dst", dst);
waitKey();
return 0;
}