基本原理:连接RGB中心点与溢出像素点,与RGB空间的交点即为对溢出像素修正的颜色值。
上图立方体为RGB颜色空间,B为色彩溢出点所在位置,C为修正后的颜色值。
#ifndef _CV2GAMUT_H_
#define _CV2GAMUT_H_
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc.hpp>
using namespace cv;
using namespace std;
class Cv2Gamut{
private:
Vec3f OF_RGB;
Vec3f iDot;//线面交点
Vec3f oDot = Vec3f(0.5, 0.5, 0.5);//RGB 立方体中心
Vec3f pDot;//平面经过的一点坐标
Vec3f PnorVec;//平面法向量
Vec3f LnorVec;//直线方向向量
float vpt;//直线向量与法向量的乘积
float t;
public:
Cv2Gamut(const Vec3f &OF_RGB){
this->OF_RGB = OF_RGB;
}
Cv2Gamut(){
}
void setRGB(const Vec3f &OF_RGB){
this->OF_RGB = OF_RGB;
}
void lineXplane(){
LnorVec = OF_RGB - oDot;
vpt = LnorVec.val[0] * PnorVec.val[0] + LnorVec.val[1] * PnorVec.val[1] + LnorVec.val[2] * PnorVec.val[2];
if (vpt == 0){
iDot = Vec3f(-0.5, -0.5, -0.5);
}
else{
t = ((pDot.val[0] - 0.5)*PnorVec.val[0] + (pDot.val[1] - 0.5)*PnorVec.val[1] + (pDot.val[2] - 0.5)*PnorVec.val[2]) / vpt;
iDot.val[0] = 0.5 + LnorVec.val[0] * t;
iDot.val[1] = 0.5 + LnorVec.val[1] * t;
iDot.val[2] = 0.5 + LnorVec.val[2] * t;
}
}
bool Judge(){
bool J = 1;
if (iDot.val[0] > 1)J = 0;
if (iDot.val[0] < 0)J = 0;
if (iDot.val[1] > 1)J = 0;
if (iDot.val[1] < 0)J = 0;
if (iDot.val[2] > 1)J = 0;
if (iDot.val[2] < 0)J = 0;
if (OF_RGB.val[0]>1 && iDot.val[0] < 0.5)J = 0;
if (OF_RGB.val[1]>1 && iDot.val[1] < 0.5)J = 0;
if (OF_RGB.val[2]>1 && iDot.val[2] < 0.5)J = 0;
if (OF_RGB.val[0]<0&& iDot.val[0] > 0.5)J = 0;
if (OF_RGB.val[1]<0 && iDot.val[1] > 0.5)J = 0;
if (OF_RGB.val[2]<0 && iDot.val[2] > 0.5)J = 0;
return J;
}
Vec3f submit(){
if (OF_RGB[2] <= 1 && OF_RGB[0] <= 1 && OF_RGB[1] <= 1 && OF_RGB[2] >= 0 && OF_RGB[1] >= 0 && OF_RGB[0] >= 0)return OF_RGB;
pDot = Vec3f(0, 1, 0);//平面经过的一点坐标
PnorVec = Vec3f(0, 1, 0);//平面法向量
lineXplane();
if (Judge())return iDot;
else{
pDot = Vec3f(1, 0, 0);
PnorVec = Vec3f(1, 0, 0);
lineXplane();
if (Judge())return iDot;
else{
pDot = Vec3f(1, 0, 0);
PnorVec = Vec3f(0, 0, -1);
lineXplane();
if (Judge())return iDot;
else{
pDot = Vec3f(0, 0, 1);
PnorVec = Vec3f(0, 0, 1);
lineXplane();
if (Judge())return iDot;
else{
pDot = Vec3f(0, 0, 1);
PnorVec = Vec3f(0, -1, 0);
lineXplane();
if (Judge())return iDot;
else{
pDot = Vec3f(0, 0, 1);
PnorVec = Vec3f(-1, 0, 0);
lineXplane();
return iDot;
}
}
}
}
}
}
};
#endif
上面为颜色溢出修正类的代码,输入为Vec3f BGR值,输出为 修正好的 Vec3fBGR值,范围为0~1;
本修正方法保留了hue值的不变。
如下图所示:
下图中左侧为已经溢出的颜色值,不能正常显示色相为101.538的绿色色相,右侧为修正结果。