1.结合灰度世界和完美反射的颜色校正方法原理
《基于图像分析的偏色检测及颜色校正方法》
2.opencv实现
ColorCalibrate.h
#ifndef COLORCALIBRATE_H
#define COLORRALIBRATE_H
#include <opencv.hpp>
using namespace cv;
class ColorCalibrate
{
private:
float ur, vr;//校正系数
float ub, vb;
Mat src;
public:
ColorCalibrate(const Mat& img);
void clcCalibateCoefficient();
Mat getCalibratePlane();
};
#endif
ColorCalibrate.cpp
#include"ColorCalibrate.h"
ColorCalibrate::ColorCalibrate(const Mat& img)
{
src = img;
ur = 0;
vr = 0;
vb = 0;
ub = 0;
}
void ColorCalibrate::clcCalibateCoefficient()
{
if (src.isContinuous())
{
src.reshape(1, src.cols*src.rows);
}
double sumSquareB = 0, sumValB = 0;
double maxSquareB = 0, maxValB = 0;
double sumSquareR = 0, sumValR = 0;
double maxSquareR = 0, maxValR = 0;
double sumValG = 0;
double maxValG = 0;
for (int rowCount = 0; rowCount < src.rows; rowCount++)
{
uchar* rowPt = src.ptr<uchar>(rowCount);
for (int colCount = 0; colCount < src.cols*src.channels(); colCount += 3)
{
maxValB = maxValB < rowPt[colCount] ? rowPt[colCount] : maxValB;
sumValB += rowPt[colCount];
sumSquareB += rowPt[colCount] * rowPt[colCount];
maxValG = maxValG < rowPt[colCount+1] ? rowPt[colCount+1] : maxValG;
sumValG += rowPt[colCount+1];
maxValR = maxValR < rowPt[colCount+2] ? rowPt[colCount+2] : maxValR;
sumValR += rowPt[colCount+2];
sumSquareR += rowPt[colCount+2] * rowPt[colCount+2];
}
}
maxSquareB = maxValB*maxValB;
maxSquareR = maxValB*maxValR;
vb = (float)((sumValG*maxSquareB-sumSquareB*maxValG)/(sumValB*maxSquareB - sumSquareB*maxValB));
ub = (float)((sumValG - sumValB*vb) / sumSquareB);
vr = (float)((sumValG*maxSquareR - sumSquareR*maxValG) / (sumValR*maxSquareR - sumSquareR*maxValR));
ur = (float)((sumValG - sumValR*vr) / sumSquareR);
}
Mat ColorCalibrate::getCalibratePlane()
{
if (ur == 0 || vr == 0 || vb == 0 || vb == 0)
clcCalibateCoefficient();
if (src.isContinuous())
{
src.reshape(1, src.cols*src.rows);
}
Mat cali(src.size(),src.type());
for (int rowCount = 0; rowCount < src.rows; rowCount++)
{
uchar* rowPt = src.ptr<uchar>(rowCount);
uchar* caliPt = cali.ptr<uchar>(rowCount);
for (int colCount = 0; colCount < src.cols*src.channels(); colCount += 3)
{
caliPt[colCount] = ub*rowPt[colCount] * rowPt[colCount] + vb*rowPt[colCount];
caliPt[colCount + 1] = rowPt[colCount + 1];
caliPt[colCount+2] = ur*rowPt[colCount+2] * rowPt[colCount+2] + vr*rowPt[colCount+2];
}
}
return cali;
}
3.结果分析
原图
校正后图像
从实验结果看,只有图像偏蓝的时候效果比较好,比单纯的灰度世界法和完美反射法都好,但是其他情况下会失效。
可能是代码实现有问题。