Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何进一步优化此色差函数?_Java_Algorithm_Optimization_Colors_Color Space - Fatal编程技术网

Java 如何进一步优化此色差函数?

Java 如何进一步优化此色差函数?,java,algorithm,optimization,colors,color-space,Java,Algorithm,Optimization,Colors,Color Space,我使用这个函数来计算CIE实验室颜色空间中的色差,但它缺乏速度。由于我不是Java专家,我想知道周围的Java大师是否有一些技巧可以提高这里的速度 代码基于注释块中提到的matlab函数 /** * Compute the CIEDE2000 color-difference between the sample color with * CIELab coordinates 'sample' and a standard color with CIELab coordinates * '

我使用这个函数来计算CIE实验室颜色空间中的色差,但它缺乏速度。由于我不是Java专家,我想知道周围的Java大师是否有一些技巧可以提高这里的速度

代码基于注释块中提到的matlab函数

/**
 * Compute the CIEDE2000 color-difference between the sample color with
 * CIELab coordinates 'sample' and a standard color with CIELab coordinates
 * 'std'
 *
 * Based on the article:
 * "The CIEDE2000 Color-Difference Formula: Implementation Notes,
 * Supplementary Test Data, and Mathematical Observations,", G. Sharma,
 * W. Wu, E. N. Dalal, submitted to Color Research and Application,
 * January 2004.
 * available at http://www.ece.rochester.edu/~gsharma/ciede2000/
 */
public static double deltaE2000(double[] lab1, double[] lab2)
{
    double L1 = lab1[0];
    double a1 = lab1[1];
    double b1 = lab1[2];

    double L2 = lab2[0];
    double a2 = lab2[1];
    double b2 = lab2[2];

    // Cab = sqrt(a^2 + b^2)
    double Cab1 = Math.sqrt(a1 * a1 + b1 * b1);
    double Cab2 = Math.sqrt(a2 * a2 + b2 * b2);

    // CabAvg = (Cab1 + Cab2) / 2
    double CabAvg = (Cab1 + Cab2) / 2;

    // G = 1 + (1 - sqrt((CabAvg^7) / (CabAvg^7 + 25^7))) / 2
    double CabAvg7 = Math.pow(CabAvg, 7);
    double G = 1 + (1 - Math.sqrt(CabAvg7 / (CabAvg7 + 6103515625.0))) / 2;

    // ap = G * a
    double ap1 = G * a1;
    double ap2 = G * a2;

    // Cp = sqrt(ap^2 + b^2)
    double Cp1 = Math.sqrt(ap1 * ap1 + b1 * b1);
    double Cp2 = Math.sqrt(ap2 * ap2 + b2 * b2);

    // CpProd = (Cp1 * Cp2)
    double CpProd = Cp1 * Cp2;

    // hp1 = atan2(b1, ap1)
    double hp1 = Math.atan2(b1, ap1);
    // ensure hue is between 0 and 2pi
    if (hp1 < 0) {
        // hp1 = hp1 + 2pi
        hp1 += 6.283185307179586476925286766559;
    }

    // hp2 = atan2(b2, ap2)
    double hp2 = Math.atan2(b2, ap2);
    // ensure hue is between 0 and 2pi
    if (hp2 < 0) {
        // hp2 = hp2 + 2pi
        hp2 += 6.283185307179586476925286766559;
    }

    // dL = L2 - L1
    double dL = L2 - L1;

    // dC = Cp2 - Cp1
    double dC = Cp2 - Cp1;

    // computation of hue difference
    double dhp = 0.0;
    // set hue difference to zero if the product of chromas is zero
    if (CpProd != 0) {
        // dhp = hp2 - hp1
        dhp = hp2 - hp1;
        if (dhp > Math.PI) {
            // dhp = dhp - 2pi
            dhp -= 6.283185307179586476925286766559;
        } else if (dhp < -Math.PI) {
            // dhp = dhp + 2pi
            dhp += 6.283185307179586476925286766559;
        }
    }

    // dH = 2 * sqrt(CpProd) * sin(dhp / 2)
    double dH = 2 * Math.sqrt(CpProd) * Math.sin(dhp / 2);

    // weighting functions
    // Lp = (L1 + L2) / 2 - 50
    double Lp = (L1 + L2) / 2 - 50;

    // Cp = (Cp1 + Cp2) / 2
    double Cp = (Cp1 + Cp2) / 2;

    // average hue computation
    // hp = (hp1 + hp2) / 2
    double hp = (hp1 + hp2) / 2;

    // identify positions for which abs hue diff exceeds 180 degrees
    if (Math.abs(hp1 - hp2) > Math.PI) {
        // hp = hp - pi
        hp -= Math.PI;
    }
    // ensure hue is between 0 and 2pi
    if (hp < 0) {
        // hp = hp + 2pi
        hp += 6.283185307179586476925286766559;
    }

    // LpSqr = Lp^2
    double LpSqr = Lp * Lp;

    // Sl = 1 + 0.015 * LpSqr / sqrt(20 + LpSqr)
    double Sl = 1 + 0.015 * LpSqr / Math.sqrt(20 + LpSqr);

    // Sc = 1 + 0.045 * Cp
    double Sc = 1 + 0.045 * Cp;

    // T = 1 - 0.17 * cos(hp - pi / 6) +
    //       + 0.24 * cos(2 * hp) +
    //       + 0.32 * cos(3 * hp + pi / 30) -
    //       - 0.20 * cos(4 * hp - 63 * pi / 180)
    double hphp = hp + hp;
    double T = 1 - 0.17 * Math.cos(hp - 0.52359877559829887307710723054658)
            + 0.24 * Math.cos(hphp)
            + 0.32 * Math.cos(hphp + hp + 0.10471975511965977461542144610932)
            - 0.20 * Math.cos(hphp + hphp - 1.0995574287564276334619251841478);

    // Sh = 1 + 0.015 * Cp * T
    double Sh = 1 + 0.015 * Cp * T;

    // deltaThetaRad = (pi / 3) * e^-(36 / (5 * pi) * hp - 11)^2
    double powerBase = hp - 4.799655442984406;
    double deltaThetaRad = 1.0471975511965977461542144610932 * Math.exp(-5.25249016001879 * powerBase * powerBase);

    // Rc = 2 * sqrt((Cp^7) / (Cp^7 + 25^7))
    double Cp7 = Math.pow(Cp, 7);
    double Rc = 2 * Math.sqrt(Cp7 / (Cp7 + 6103515625.0));

    // RT = -sin(delthetarad) * Rc
    double RT = -Math.sin(deltaThetaRad) * Rc;

    // de00 = sqrt((dL / Sl)^2 + (dC / Sc)^2 + (dH / Sh)^2 + RT * (dC / Sc) * (dH / Sh))
    double dLSl = dL / Sl;
    double dCSc = dC / Sc;
    double dHSh = dH / Sh;
    return Math.sqrt(dLSl * dLSl + dCSc * dCSc + dHSh * dHSh + RT * dCSc * dHSh);
}
/**
*使用以下公式计算样本颜色之间的CIEDE2000色差:
*CIELab坐标“样本”和带有CIELab坐标的标准颜色
*“性病”
*
*根据该条:
*“CIEDE2000色差公式:实施说明,
*补充试验数据和数学观察”,G.Sharma,
*W.Wu,E.N.Dalal,提交颜色研究和应用,
*2004年1月。
*可在http://www.ece.rochester.edu/~gsharma/ciede2000/
*/
公共静态双deltaE2000(双[]lab1,双[]lab2)
{
双L1=lab1[0];
双a1=lab1[1];
双b1=lab1[2];
双L2=lab2[0];
双a2=lab2[1];
双b2=lab2[2];
//Cab=sqrt(a^2+b^2)
双Cab1=数学sqrt(a1*a1+b1*b1);
双Cab2=数学sqrt(a2*a2+b2*b2);
//CabAvg=(Cab1+Cab2)/2
双CabAvg=(Cab1+Cab2)/2;
//G=1+(1-sqrt((CabAvg^7)/(CabAvg^7+25^7))/2
双CabAvg7=数学功率(CabAvg,7);
双G=1+(1-数学sqrt(CabAvg7/(CabAvg7+6103515625.0))/2;
//ap=G*a
双ap1=G*a1;
双ap2=G*a2;
//Cp=sqrt(ap^2+b^2)
双Cp1=数学sqrt(ap1*ap1+b1*b1);
双Cp2=数学sqrt(ap2*ap2+b2*b2);
//CpProd=(Cp1*Cp2)
双CpProd=Cp1*Cp2;
//hp1=atan2(b1,ap1)
双hp1=数学atan2(b1,ap1);
//确保色调介于0和2pi之间
如果(hp1<0){
//hp1=hp1+2pi
hp1+=6.283185307179586476925286766559;
}
//hp2=atan2(b2,ap2)
双hp2=数学atan2(b2,ap2);
//确保色调介于0和2pi之间
如果(hp2<0){
//hp2=hp2+2pi
hp2+=6.283185307179586476925286766559;
}
//dL=L2-L1
双dL=L2-L1;
//dC=Cp2-Cp1
双dC=Cp2-Cp1;
//色差计算
双dhp=0.0;
//如果色度的乘积为零,则将色调差设置为零
如果(CpProd!=0){
//dhp=hp2-hp1
dhp=hp2-hp1;
if(dhp>Math.PI){
//dhp=dhp-2pi
dhp-=6.283185307179586476925286766559;
}否则如果(dhp<-Math.PI){
//dhp=dhp+2pi
dhp+=6.283185307179586476925286766559;
}
}
//dH=2*sqrt(CpProd)*sin(dhp/2)
双dH=2*数学sqrt(CpProd)*数学sin(dhp/2);
//加权函数
//Lp=(L1+L2)/2-50
双Lp=(L1+L2)/2-50;
//Cp=(Cp1+Cp2)/2
双Cp=(Cp1+Cp2)/2;
//平均色调计算
//hp=(hp1+hp2)/2
双hp=(hp1+hp2)/2;
//确定abs色调差异超过180度的位置
if(Math.abs(hp1-hp2)>Math.PI){
//hp=hp-pi
hp-=Math.PI;
}
//确保色调介于0和2pi之间
如果(hp<0){
//hp=hp+2pi
hp+=6.283185307179586476925286766559;
}
//LpSqr=Lp^2
双LpSqr=Lp*Lp;
//Sl=1+0.015*LpSqr/sqrt(20+LpSqr)
双Sl=1+0.015*LpSqr/数学sqrt(20+LpSqr);
//Sc=1+0.045*Cp
双Sc=1+0.045*Cp;
//T=1-0.17*cos(hp-pi/6)+
//+0.24*cos(2*hp)+
//+0.32*cos(3*hp+pi/30)-
//-0.20*cos(4*hp-63*pi/180)
双hp=hp+hp;
双T=1-0.17*数学系数(hp-0.52359877559829887307710723054658)
+0.24*Math.cos(hphp)
+0.32*数学系数(hphp+hp+0.10471975511965977461542144610932)
-0.20*数学系数(hphp+hphp-1.0995574287564276334619251841478);
//Sh=1+0.015*Cp*T
双Sh=1+0.015*Cp*T;
//德尔塔塔拉德=(π/3)*e^-(36/(5*π)*马力-11)^2
双powerBase=hp-4.799655442984406;
双deltaThetaRad=1.0471975511965977461542144610932*Math.exp(-5.25249016001879*powerBase*powerBase);
//Rc=2*sqrt((Cp^7)/(Cp^7+25^7))
双Cp7=数学功率(Cp,7);
双Rc=2*数学sqrt(Cp7/(Cp7+6103515625.0));
//RT=-sin(德尔塔)*Rc
双RT=-Math.sin(deltaThetaRad)*Rc;
//de00=sqrt((dL/Sl)^2+(dC/Sc)^2+(dH/Sh)^2+RT*(dC/Sc)*(dH/Sh))
双dLSl=dL/Sl;
双dCSc=dC/Sc;
双dHSh=dH/Sh;
返回Math.sqrt(dLSl*dLSl+dCSc*dCSc+dHSh*dHSh+RT*dCSc*dHSh);
}

cos
很贵,尤其是一排4个。您似乎在计算cos(na+b),其中b是常数,n是小整数。这意味着您可以预计算cos(b)和sin(b),并在运行时只计算cos(hp)和sin(hp)。通过重复使用,你可以得到cos(na+b)

cos(a+b) = cos(a)*cos(b)-sin(a)*sin(b)
您将用两个
sin
s和
cos
s来交换一些乘法和加法,几乎肯定是值得的

如果你有雄心壮志,你可以做得更好。您从
atan2
间接获得
hp
。模式
trig函数(有理函数(逆trig函数(x))
通常可以被多项式和根的某些组合所取代,这些组合比trig函数的计算速度更快

我不知道
pow
是如何在Java中实现的,但如果它使用日志,您最好使用
Cp2=Cp*Cp获得
Cp7
;Cp4=Cp2*Cp2;Cp7=Cp4*Cp2*Cp

更新:由于我没有时间真正重写代码,所以现在有点推测性。功率优化和三角优化实际上是伪装的同一件事!trig优化是应用于复数的幂优化的一个版本。W
double dH = 2 * Math.sqrt(CpProd) * Math.sin(dhp / 2);