前段时间,关于主色提取方面,用到了色差的概念。色差是应用在Lab颜色空间上的,个人感觉效果还可以,不知道为何关于这方面的应用不是很多,是不是有什么大的弊端,还请大家多多指教!
色差相关定义可以参阅:http://www.cgan.net/book/books/print/packcolor/link/5-4-3.html
code:
/****************************************************************************** * * CIEDE2000 Color Difference Calculator * * Copyright (c) 2007 yoneh (http://d.hatena.ne.jp/yoneh/) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * ****************************************************************************** * * References: * [1] Gaurav Sharma, Wencheng Wu, and Edul N. Dalal, ``The CIEDE2000 Color- * Difference Formula: Implementation Notes, Supplementary Test Data, * and Mathematical Observations'', Color Research and Application, Vol. 30, * No. 1, Feb 2005. * ******************************************************************************/ #include <cmath> #include <iostream> using namespace std; double CIEDE2000(const double L1,const double a1,const double b1, const double L2,const double a2,const double b2); int main(void) { double L1,a1,b1; double L2,a2,b2; cout << "<<< CIEDE2000 Color Difference Calculator >>>" << endl << endl; cout << "L1 = "; cin >> L1; cout << "a1 = "; cin >> a1; cout << "b1 = "; cin >> b1; cout << endl; cout << "L2 = "; cin >> L2; cout << "a2 = "; cin >> a2; cout << "b2 = "; cin >> b2; cout << endl; cout << "E00 = " << CIEDE2000(L1,a1,b1,L2,a2,b2) << endl; return 0; } /** * Can x be assumed to be 0 * @param x a value * @return true if x can be assumed to be 0 */ inline bool tolerance_zero(const double x) { return fabs(x)<1e-9; } /** * cosine * @param degree angle [degree] * @return cosine value */ inline double cosd(const double degree) { return cos(degree*M_PI/180.0); } /** * sine * @param degree angle [degree] * @return sine value */ inline double sind(const double degree) { return sin(degree*M_PI/180.0); } /** * arctangent (four quadrant) * @param y y-coordinate * @param x x-coordinate * @return angle [degree] */ inline double fqatan(const double y,const double x) { double t=atan2(y,x)/M_PI*180.0; if(t<0.0) t+=360.0; return t; } /** * Calculate f7(x)=(x^7 / (x^7+25^7))^0.5 * @param x a value * @return f7(x) */ inline double f7(const double x) { // if x is small, using the following approx. if(x<1.0) return pow(x/25.0,3.5); return 1.0/sqrt(1.0+pow(25.0/x,7.0)); } /** * Calculate `CIEDE2000 Color Difference' * @param L1 L* parameter of a color * @param a1 a* parameter of a color * @param b1 b* parameter of a color * @param L2 L* parameter of a color * @param a2 a* parameter of a color * @param b2 b* parameter of a color * @return `CIEDE2000 Color Difference' between (L1,a1,b1) and (L2,a2,b2) */ double CIEDE2000(const double L1,const double a1,const double b1, const double L2,const double a2,const double b2) { const double epsilon=1e-9; // Calculate C1', C2', h1', and h2' double C1ab,C2ab; double Cab,G; double a1_,a2_; double C1_,C2_; double h1_,h2_; C1ab=sqrt(a1*a1+b1*b1); C2ab=sqrt(a2*a2+b2*b2); Cab=(C1ab+C2ab)/2.0; G=0.5*(1.0-f7(Cab)); a1_=(1.0+G)*a1; a2_=(1.0+G)*a2; C1_=sqrt(a1_*a1_+b1*b1); C2_=sqrt(a2_*a2_+b2*b2); if(tolerance_zero(a1_) && tolerance_zero(b1)) h1_=0.0; else h1_=fqatan(b1,a1_); if(tolerance_zero(a2_) && tolerance_zero(b2)) h2_=0.0; else h2_=fqatan(b2,a2_); // Calculate dL', dC', and dH' double dL_,dC_,dH_,dh_; double C12; dL_=L2-L1; dC_=C2_-C1_; C12=C1_*C2_; if(tolerance_zero(C12)) { dh_=0.0; } else { double tmp=h2_-h1_; if(fabs(tmp)<=180.0+epsilon) dh_=tmp; else if(tmp>180.0) dh_=tmp-360.0; else if(tmp<-180.0) dh_=tmp+360.0; } dH_=2.0*sqrt(C12)*sind(dh_/2.0); // Calculate L', C', h', T, and dTh double L_,C_,h_,T,dTh; L_=(L1+L2)/2.0; C_=(C1_+C2_)/2.0; if(tolerance_zero(C12)) { h_=h1_+h2_; } else { double tmp1=fabs(h1_-h2_); double tmp2=h1_+h2_; if(tmp1<=180.0+epsilon) h_=tmp2/2.0; else if(tmp2<360.0) h_=(tmp2+360.0)/2.0; else if(tmp2>=360.0) h_=(tmp2-360.0)/2.0; } T=1.0-0.17*cosd(h_-30.0)+0.24*cosd(2.0*h_) +0.32*cosd(3.0*h_+6.0)-0.2*cosd(4.0*h_-63.0); dTh=30.0*exp(-pow((h_-275.0)/25.0,2.0)); // Calculate RC, SL, SC, SH, and RT double RC,SL,SC,SH,RT; double L_2=(L_-50.0)*(L_-50.0); RC=2.0*f7(C_); SL=1.0+0.015*L_2/sqrt(20.0+L_2); SC=1.0+0.045*C_; SH=1.0+0.015*C_*T; RT=-sind(2.0*dTh)*RC; // Calculate dE00 const double kL=1.0; // These are proportionally coefficients const double kC=1.0; // and vary according to the condition. const double kH=1.0; // These mostly are 1. double LP=dL_/(kL*SL); double CP=dC_/(kC*SC); double HP=dH_/(kH*SH); return sqrt(LP*LP+CP*CP+HP*HP+RT*CP*HP); }