一种基于DeltaE(CIE 1976)的找色算法
// QuickFinder.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#define _USE_MATH_DEFINES
#include <cmath>
#include <ctime>
unsigned char buf[1080][1920][3];
const float param_13 = 1.0f / 3.0f;
const float param_16116 = 16.0f / 116.0f;
const float Xn = 0.950456f;
const float Yn = 1.0f;
const float Zn = 1.088754f;
inline float gamma(float x)
{
return x > 0.04045 ? powf((x+0.055f) / 1.055f, 2.4f) : (x / 12.92);
}
float bL[256][256][256];
float ba[256][256][256];
float bb[256][256][256];
inline void RGB2Lab(uint8_t R, uint8_t G, uint8_t B, float &L, float &a, float &b)
{
float RR = gamma(R / 255.0);
float GG = gamma(G / 255.0);
float BB = gamma(B / 255.0);
float X,Y,Z,fX, fY, fZ;
X = 0.4124564f * RR + 0.3575761f * GG + 0.1804375f * BB;
Y = 0.2126729f * RR + 0.7151522f * GG + 0.0721750f * BB;
Z = 0.0193339f * RR + 0.1191920f * GG + 0.9503041f * BB;
X /= (Xn);
Y /= (Yn);
Z /= (Zn);
if (Y > 0.008856f)
fY = pow(Y, param_13);
else
fY = 7.787f * Y + param_16116;
if (X > 0.008856f)
fX = pow(X, param_13);
else
fX = 7.787f * X + param_16116;
if (Z > 0.008856)
fZ = pow(Z, param_13);
else
fZ = 7.787f * Z + param_16116;
L = 116.0f * fY - 16.0f;
L = L > 0.0f ? L : 0.0f;
a = 500.0f * (fX - fY);
b = 200.0f * (fY - fZ);
}
void initTable()
{
for (int r = 0; r < 256; r++)
for (int g = 0; g < 256; g++)
for (int b = 0; b < 256; b++)
RGB2Lab(r, g, b, bL[r][g][b], ba[r][g][b], bb[r][g][b]);
}
inline void TableRGB2Lab(uint8_t R, uint8_t G, uint8_t B, float& L, float& a, float& b)
{
L = bL[R][G][B];
a = ba[R][G][B];
b = bb[R][G][B];
}
//计算颜色之间的Delta E
//<= 1.0:人眼无法感知差异
//1 - 2:仔细观察可以感知差异
//2 - 10:随意一看便可以感知差异
//11 - 49:色彩的相似程度大于相反程度
//100:色彩完全失真
//CIE 1976
inline float DeltaE(float L1,float a1,float b1, float L2, float a2, float b2)
{
float deltaL = L1 - L2;
float deltaA = a1 - a2;
float deltaB =b1 - b2;
return sqrt(deltaL * deltaL + deltaA * deltaA + deltaB * deltaB);
}
int main()
{
int st = clock();
initTable();
printf("Init Table %d\n", clock() - st);
for (int i = 0; i < 1080; i++)
{
for (int j = 0; j < 1920; j++)
buf[i][j][0] = rand() % 256, buf[i][j][1] = rand() % 256, buf[i][j][2] = rand() % 256;
}
unsigned char target[] = { 23,23,23 };
float tL, ta, tb;
RGB2Lab(target[2], target[1], target[0], tL, ta, tb);
int count = 0;
st = clock();
for (int i = 0; i < 1080; i++)
{
for (int j = 0; j < 1920; j++)
{
float L=0, a=0, b=0;
TableRGB2Lab(buf[i][j][2], buf[i][j][1], buf[i][j][0], L, a, b);
if (DeltaE(L, a, b, tL, ta, tb) < 2)
count++;
}
}
printf("%d", clock() - st);
printf("\nret: %d", count);
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
在i9 13900HX上取得 1080P 58ms的成绩,主要是读取table过慢