int main() { double test[] = {1,1}; // double test[] = {1.5,2}; // double test[] = {-1.2,1}; //double test[] = {-1,-1}; Matrix x0(test,2); std::cout << "x0 = " << std::endl << x0.t() << std::endl; powell(test7, x0); return 0; }
Matrix dixon(Parser parser, const Matrix& x) { Matrix x0(x); Matrix x1(x); Matrix p(x); unsigned k = 0; do { k++; x0 = x1; if (k == 1) { p = -1*grad(parser, x0); } else { double beta = -pow(grad(parser,x0).norm(),2)/getScalarPr(p,-p); p = -1*grad(parser, x0) + beta*p; } double alpha = powell(parser,x0,p,swenn_1(parser, x0,p,1)); x1 = x0 + p*alpha; } while(k < 100 && grad(parser,x0).norm() > myEPS && myEPS && fabs(parser.f(x0)-parser.f(x1))>myEPS); qDebug() << "iteration = " << k; return x1; }
/* return the technical gamma needed for the correct 50% response. */ static double xicc_tech_gamma( double egamma, /* effective gamma needed */ double off, /* Output offset required */ double outoprop /* Prop. of offset to be accounted for on output */ ) { gam_fits gf; double outo; double op[1], sa[1], rv; if (off <= 0.0) { return egamma; } /* We set up targets without outo being added */ outo = off * outoprop; /* Offset acounted for in output */ gf.bp = off - outo; /* Black value for 0 % input */ gf.wp = 1.0 - outo; /* White value for 100% input */ gf.thyr = pow(0.5, egamma) - outo; /* Advetised 50% target */ op[0] = egamma; sa[0] = 0.1; if (powell(&rv, 1, op, sa, 1e-6, 500, gam_fit, (void *)&gf, NULL, NULL) != 0) warning("Computing effective gamma and input offset is inaccurate"); return op[0]; }
void zspace_minimization(char *fname) { int n,niter,i,j; double *a,**pp,*yy,FTOL=1.0E-3,chi2min,qromo(),midpnt(),s1; fprintf(stderr,"\n\nCHI2 MINIMIZATION OF W_P(R_P)+xi(s,p) DATA..........\n"); fprintf(stderr, "-----------------------------------------------------\n\n"); OUTPUT=0; wp_input(); Work.imodel=2; /* Find the number of free parameters in the minimization * for the real-space correlation function. */ for(n=0,i=1;i<=100;++i) { n+=HOD.free[i]; if(OUTPUT) printf("zspace_min> free[%i] = %d\n",i,HOD.free[i]); } wp.ncf=n; a=dvector(1,n); if(POWELL) pp=dmatrix(1,n,1,n); else pp=dmatrix(1,n+1,1,n); yy=dvector(1,n+1); initial_zspace_values(a,pp,yy); if(POWELL) { powell(a,pp,n,FTOL,&niter,&chi2min,func_chi2); chi2min = func_chi2(a); } else amoeba(pp,yy,n,FTOL,func_chi2,&niter); s1=qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt); GALAXY_BIAS=s1/GALAXY_DENSITY; if(!ThisTask) { printf("ZSPACEMIN %e %e ",chi2min,HOD.M_min); for(i=1;i<=n;++i)printf("%e ",a[i]); printf(" %f\n",GALAXY_BIAS); } output_parameter_file(fname); }
double arlCore::ICP::optimisePowell( void ) { unsigned int i; arlCore::OptimiseICP optimizer( *this ); //optimizer.setObserver(true); vnl_powell powell(&optimizer); const arlCore::vnl_rigid_vector V( m_solution ); vnl_vector<double> init(6); for( i=0 ; i<6 ; ++i ) init(i) = V[i]; powell.minimize(init); m_solution.copy(arlCore::vnl_rigid_vector(init)); m_startError = powell.get_start_error(); m_endError = powell.get_end_error(); m_nbIterations = powell.get_num_iterations(); //m_nbIterations = optimizer.getNbIterations(); m_solution.copy(arlCore::vnl_rigid_vector(init)); m_solution.setRMS(m_endError); return m_endError; }
void fit_color_samples() { int n,niter,i,j; double *a,**pp,*yy,FTOL=1.0E-3,chi2min,s1,dlogm,m; FILE *fp; char aa[1000]; mcmc_color_minimization(); fprintf(stderr,"\n\nCHI2 MINIMIZATION OF W_P(R_P) COLOR DATA..........\n"); fprintf(stderr, "--------------------------------------------\n\n"); HOD.blue_fraction = 0.5857; /* <- Millenium fraction (sloan);; SDSS fraction -> 0.565; */ HOD.blue_fraction = 0.6555; /* <- Millenium fraction (B-V>0.8) */ HOD.blue_fraction = 0.565; /* SDSS -19,-20 */ HOD.blue_fraction = 0.492; /* SDSS -20,-21 */ HOD.blue_fraction = 0.379; /* SDSS -21 */ wp_color.ON = 1; if(POWELL) FTOL=1.0E-3; else FTOL=1.0E-5; for(n=0,i=1;i<=7;++i) { n+=HOD.free[i]; if(!OUTPUT)continue; printf("wp_min> free[%i] = %d\n",i,HOD.free[i]); } /* The parameters that govern the blue fraction aren't * listed in the HOD.free array, so add them in. * NB: There are four parameters for these two functions, * one of which is fit by the number densities. */ n+=3; if(OUTPUT)printf("wp_min> Number of free parameters: %d\n",n); wp_color_input(); wp.ncf=n; a=dvector(1,n); if(POWELL) pp=dmatrix(1,n,1,n); else pp=dmatrix(1,n+1,1,n); yy=dvector(1,n+1); initial_color_values(a,pp,yy); if(POWELL) { if(OUTPUT)printf("wp_min> starting powell.\n"); powell(a,pp,n,FTOL,&niter,&chi2min,chi2_wp_color); chi2min = chi2_wp_color(a); } else { if(OUTPUT)printf("wp_min> starting amoeba.\n"); amoeba(pp,yy,n,FTOL,chi2_wp_color,&niter); for(i=1;i<=n;++i)a[i]=pp[1][i]; chi2min = chi2_wp_color(a); } s1=qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt); GALAXY_BIAS=s1/GALAXY_DENSITY; printf("POWELL %e %e %e ",chi2min,HOD.M_min,HOD.fblue0_cen); if(HOD.pdfc==7) printf("%e ",HOD.M_cen_max); for(i=1;i<=n;++i)printf("%e ",a[i]); printf(" %f\n",GALAXY_BIAS); /* Output the fit and the HOD curve. */ sprintf(aa,"%s.fit",Task.root_filename); fp=fopen(aa,"w"); fprintf(fp,"%e %e %e ",chi2min,HOD.M_min,HOD.fblue0_cen); if(HOD.pdfc==7) fprintf(fp,"%e ",HOD.M_cen_max); for(i=1;i<=n;++i)fprintf(fp,"%e ",a[i]); fprintf(fp," %f\n",GALAXY_BIAS); fclose(fp); sprintf(aa,"%s.HOD",Task.root_filename); fp=fopen(aa,"w"); dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; for(i=1;i<=100;++i) { m=exp((i-1)*dlogm)*HOD.M_low; fprintf(fp,"%e %e %e %e\n",m,N_cen(m),N_sat(m),N_avg(m)); } fclose(fp); }
/* Fit the unbounded perceptual model to the perceptual function */ static void init_pmod(prand *s) { int i, ee, e, k, di = s->di; double *sa; double rerr; ubfit uf; uf.s = s; uf.vxs = NULL; uf.nvxs = uf._nvxs = 0; /* Allocate space for parameters */ if ((s->pmod = malloc(di * (1 << di) * sizeof(double))) == NULL) error("Malloc failed for pmod"); if ((sa = malloc(di * (1 << di) * sizeof(double))) == NULL) error("Malloc failed for pmod sa"); /* Create a list of vertex values for the colorspace */ /* Use in gamut vertexes, and compute clipped edges */ for (ee = 0; ee < (1 << di); ee++) { double p[MXTD], ss; for (ss = 0.0, e = 0; e < di; e++) { if (ee & (1 << e)) p[e] = 1.0; else p[e] = 0.0; ss += p[e]; } if (ss < s->ilimit) { /* Within gamut */ if (uf.nvxs >= uf._nvxs) { uf._nvxs = 5 + uf._nvxs * 2; if ((uf.vxs = (vxpt *)realloc(uf.vxs, sizeof(vxpt) * uf._nvxs)) == NULL) error ("Failed to malloc uf.vxs"); } for (k = 0; k < di; k++) uf.vxs[uf.nvxs].p[k] = p[k]; uf.nvxs++; } else if ((ss - 1.0) < s->ilimit) { /* far end of edge out of gamut */ double max = s->ilimit - (ss - 1.0); /* Maximum value of one */ for (e = 0; e < di; e++) { if ((ee & (1 << e)) == 0) continue; p[e] = max; if (uf.nvxs >= uf._nvxs) { uf._nvxs = 5 + uf._nvxs * 2; if ((uf.vxs = (vxpt *)realloc(uf.vxs, sizeof(vxpt) * uf._nvxs)) == NULL) error ("Failed to malloc uf.vxs"); } for (k = 0; k < di; k++) uf.vxs[uf.nvxs].p[k] = p[k]; uf.nvxs++; p[e] = 1.0; /* Restore */ } } /* Else whole edge is out of gamut */ } /* Lookup perceptual values */ for (i = 0; i < uf.nvxs; i++) { s->percept(s->od, uf.vxs[i].v, uf.vxs[i].p); //printf("~1 vtx %d: dev %f %f %f, perc %f %f %f\n",i, uf.vxs[i].p[0], uf.vxs[i].p[1], uf.vxs[i].p[2], uf.vxs[i].v[0], uf.vxs[i].v[1], uf.vxs[i].v[2]); } /* Setup matrix to be closest values initially */ for (e = 0; e < (1 << di); e++) { /* For each colorant combination */ int j, f; double bdif = 1e6; double ov[MXTD]; int bix = -1; /* Search the vertex list to find the one closest to this input combination */ for (i = 0; i < uf.nvxs; i++) { double dif = 0.0; for (j = 0; j < di; j++) { double tt; if (e & (1 << j)) tt = 1.0 - uf.vxs[i].p[j]; else tt = 0.0 - uf.vxs[i].p[j]; dif += tt * tt; } if (dif < bdif) { /* best so far */ bdif = dif; bix = i; if (dif < 0.001) break; /* Don't bother looking further */ } } for (f = 0; f < di; f++) s->pmod[f * (1 << di) + e] = uf.vxs[bix].v[f]; } for (e = 0; e < (di * (1 << di)); e++) sa[e] = 10.0; if (powell(&rerr, di * (1 << di), s->pmod, sa, 0.001, 1000, xfitfunc, (void *)&uf, NULL, NULL) != 0) { warning("Powell failed to converge, residual error = %f",rerr); } #ifdef DEBUG printf("Perceptual model fit residual = %f\n",sqrt(rerr)); #endif s->pmod_init = 1; free(sa); }
/* Might be easier to close it and re-open it ? */ static icxLuBase * set_icxLuMatrix( xicc *xicp, icmLuBase *plu, /* Pointer to Lu we are expanding (ours) */ int flags, /* white/black point flags */ int nodp, /* Number of points */ cow *ipoints, /* Array of input points in XYZ space */ double dispLuminance, /* > 0.0 if display luminance value and is known */ double wpscale, /* > 0.0 if input white point is to be scaled */ int quality /* Quality metric, 0..3 */ ) { icxLuMatrix *p; /* Object being created */ icc *icco = xicp->pp; /* Underlying icc object */ icmLuMatrix *pmlu = (icmLuMatrix *)plu; /* icc matrix lookup object */ int luflags = 0; /* icxLuMatrix alloc clip, merge flags */ int isLinear = 0; /* NZ if pure linear, gamma = 1.0 */ int isGamma = 0; /* NZ if gamma rather than shaper */ int isShTRC = 0; /* NZ if shared TRCs */ int inputChan = 3; /* Must be RGB like */ int outputChan = 3; /* Must be the PCS */ icmHeader *h = icco->header; /* Pointer to icc header */ int rsplflags = 0; /* Flags for scattered data rspl */ int e, f, i, j; int maxits = 200; /* Optimisation stop params */ double stopon = 0.01; /* Absolute delta E change to stop on */ cow *points; /* Copy of ipoints */ mxopt os; /* Optimisation information */ double rerr; #ifdef DEBUG_PLOT #define XRES 100 double xx[XRES]; double y1[XRES]; #endif /* DEBUG_PLOT */ if (flags & ICX_VERBOSE) rsplflags |= RSPL_VERBOSE; luflags = flags; /* Transfer straight though ? */ /* Check out some things about the profile */ { icmCurve *wor, *wog, *wob; wor = pmlu->redCurve; wog = pmlu->greenCurve; wob = pmlu->blueCurve; if (wor == wog) { if (wog != wob) { xicp->errc = 1; sprintf(xicp->err,"icx_set_matrix: TRC sharing is inconsistent"); return NULL; } isShTRC = 1; } if (wor->flag != wog->flag || wog->flag != wob->flag) { xicp->errc = 1; sprintf(xicp->err,"icx_set_matrix: TRC type is inconsistent"); return NULL; } if (wor->flag == icmCurveGamma) { isGamma = 1; } if (flags & ICX_NO_IN_SHP_LUTS) { isLinear = 1; } } /* Do basic icxLu creation and initialisation */ if ((p = alloc_icxLuMatrix(xicp, plu, 0, luflags)) == NULL) return NULL; p->func = icmFwd; /* Assumed by caller */ /* Get the effective spaces of underlying icm, and set icx the same */ plu->spaces(plu, &p->ins, NULL, &p->outs, NULL, NULL, &p->intent, NULL, &p->pcs, NULL); /* For set_icx the effective pcs has to be the same as the native pcs */ /* Sanity check for matrix */ if (p->pcs != icSigXYZData) { p->pp->errc = 1; sprintf(p->pp->err,"Can't create matrix profile with PCS of Lab !"); p->del((icxLuBase *)p); return NULL; } /* In general the native and effective ranges of the icx will be the same as the */ /* underlying icm lookup object. */ p->plu->get_lutranges(p->plu, p->ninmin, p->ninmax, p->noutmin, p->noutmax); p->plu->get_ranges(p->plu, p->inmin, p->inmax, p->outmin, p->outmax); /* If we have a Jab PCS override, reflect this in the effective icx range. */ /* Note that the ab ranges are nominal. They will exceed this range */ /* for colors representable in L*a*b* PCS */ if (p->ins == icxSigJabData) { p->inmin[0] = 0.0; p->inmax[0] = 100.0; p->inmin[1] = -128.0; p->inmax[1] = 128.0; p->inmin[2] = -128.0; p->inmax[2] = 128.0; } else if (p->outs == icxSigJabData) { p->outmin[0] = 0.0; p->outmax[0] = 100.0; p->outmin[1] = -128.0; p->outmax[1] = 128.0; p->outmin[2] = -128.0; p->outmax[2] = 128.0; } /* ------------------------------- */ /* Allocate the array passed to fit_rspl() */ if ((points = (cow *)malloc(sizeof(cow) * nodp)) == NULL) { p->pp->errc = 2; sprintf(p->pp->err,"Allocation of scattered coordinate array failed"); p->del((icxLuBase *)p); return NULL; } /* Setup points ready for optimisation */ for (i = 0; i < nodp; i++) { for (e = 0; e < inputChan; e++) points[i].p[e] = ipoints[i].p[e]; for (f = 0; f < outputChan; f++) points[i].v[f] = ipoints[i].v[f]; points[i].w = ipoints[i].w; /* Make sure its Lab for delta E calculation */ icmXYZ2Lab(&icmD50, points[i].v, points[i].v); } /* Setup for optimising run */ if (flags & ICX_VERBOSE) os.verb = 1; else os.verb = 0; os.points = points; os.nodp = nodp; os.isShTRC = 0; /* Set quality/effort factors */ if (quality >= 3) { /* Ultra high */ os.norders = 20; maxits = 5000; stopon = 0.000001; } else if (quality == 2) { /* High */ os.norders = 15; maxits = 2000; stopon = 0.00001; } else if (quality == 1) { /* Medium */ os.norders = 10; maxits = 1000; stopon = 0.0001; } else { /* Low */ os.norders = 5; maxits = 500; stopon = 0.001; } if (os.norders > MXNORDERS) os.norders = MXNORDERS; /* Set initial optimisation values */ os.v[0] = 0.4; os.v[1] = 0.4; os.v[2] = 0.2; /* Matrix */ os.v[3] = 0.2; os.v[4] = 0.8; os.v[5] = 0.1; os.v[6] = 0.02; os.v[7] = 0.15; os.v[8] = 1.3; if (isLinear) { /* Just gamma curve */ os.isLinear = 1; os.isGamma = 1; os.optdim = 9; os.v[9] = os.v[10] = os.v[11] = 1.0; /* Linear */ } else if (isGamma) { /* Just gamma curve */ os.isLinear = 0; os.isGamma = 1; os.optdim = 12; os.v[9] = os.v[10] = os.v[11] = 2.4; /* Gamma */ } else { /* Creating input curves */ os.isLinear = 0; os.isGamma = 0; os.optdim = 12 + 3 * os.norders; os.v[9] = os.v[10] = os.v[11] = 0.0; /* Offset */ os.v[12] = os.v[13] = os.v[14] = 2.0; /* 0th Harmonic */ for (i = 15; i < os.optdim; i++) os.v[i] = 0.0; /* Higher orders */ } /* Set search area to starting values */ for (j = 0; j < os.optdim; j++) os.sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */ if (isShTRC) { /* Adjust things for shared */ os.isShTRC = 1; if (os.optdim > 9) { /* Pack red paramenters down */ for (i = 9; i < os.optdim; i++) { os.v[i] = os.v[(i - 9) * 3 + 9]; os.sa[i] = os.sa[(i - 9) * 3 + 9]; } os.optdim = ((os.optdim - 9)/3) + 9; } } if (os.verb) { if (os.isLinear) printf("Creating matrix...\n"); else printf("Creating matrix and curves...\n"); } if (powell(&rerr, os.optdim, os.v, os.sa, stopon, maxits, mxoptfunc, (void *)&os, mxprogfunc, (void *)&os) != 0) warning("Powell failed to converge, residual error = %f",rerr); #ifdef NEVER printf("Matrix = %f %f %f\n",os.v[0], os.v[1], os.v[2]); printf(" %f %f %f\n",os.v[3], os.v[4], os.v[5]); printf(" %f %f %f\n",os.v[6], os.v[7], os.v[8]); if (!isLinear) { /* Creating input curves */ if (isGamma) { /* Creating input curves */ if (isShTRC) printf("Gamma = %f\n",os.v[9]); else printf("Gamma = %f %f %f\n",os.v[9], os.v[10], os.v[11]); } else { /* Creating input curves */ if (isShTRC) printf("Offset = %f\n",os.v[9]); else printf("Offset = %f %f %f\n",os.v[9], os.v[10], os.v[11]); for (j = 0; j < os.norders; j++) { if (isShTRC) printf("%d harmonics = %f\n",j, os.v[10 + j]); else printf("%d harmonics = %f %f %f\n",j, os.v[12 + j * 3], os.v[13 + j * 3], os.v[14 + j * 3]); } } } #endif /* NEVER */ /* Deal with white/black points */ if (flags & (ICX_SET_WHITE | ICX_SET_BLACK)) { double wp[3]; /* Absolute White point in XYZ */ double bp[3]; /* Absolute Black point in XYZ */ if (flags & ICX_VERBOSE) printf("Find white & black points\n"); icmXYZ2Ary(wp, icmD50); /* Set a default value - D50 */ icmXYZ2Ary(bp, icmBlack); /* Set a default value - absolute black */ /* Figure out the device values for white */ if (h->deviceClass == icSigInputClass) { double dwhite[MXDI], dblack[MXDI]; /* Device white and black values */ double Lmax = -1e60; double Lmin = 1e60; /* We assume that the input target is well behaved, */ /* and that it includes a white and black point patch, */ /* and that they have the extreme L values */ /* NOTE that this may not be the best approach ! It may be better to average the chromaticity of all the neutral seeming patches, since the whitest patch may have (for instance) a blue tint. */ /* Discover the white and black points */ for (i = 0; i < nodp; i++) { if (points[i].v[0] > Lmax) { Lmax = wp[0] = points[i].v[0]; wp[1] = points[i].v[1]; wp[2] = points[i].v[2]; dwhite[0] = points[i].p[0]; dwhite[1] = points[i].p[1]; dwhite[2] = points[i].p[2]; } if (points[i].v[0] < Lmin) { Lmin = bp[0] = points[i].v[0]; bp[1] = points[i].v[1]; bp[2] = points[i].v[2]; dblack[0] = points[i].p[0]; dblack[1] = points[i].p[1]; dblack[2] = points[i].p[2]; } } /* Lookup device white/black values in model */ mxmfunc(&os, os.v, wp, dwhite); mxmfunc(&os, os.v, bp, dblack); /* If we were given an input white point scale factor, apply it */ if (wpscale >= 0.0) { wp[0] *= wpscale; wp[1] *= wpscale; wp[2] *= wpscale; } } else { /* Assume Monitor class */ switch(h->colorSpace) { case icSigCmyData: { double cmy[3]; /* Lookup white value */ for (e = 0; e < inputChan; e++) cmy[e] = 0.0; mxmfunc(&os, os.v, wp, cmy); if (flags & ICX_VERBOSE) printf("Initial white point = %f %f %f\n",wp[0],wp[1],wp[2]); /* Lookup black value */ for (e = 0; e < inputChan; e++) cmy[e] = 1.0; mxmfunc(&os, os.v, bp, cmy); if (flags & ICX_VERBOSE) printf("Initial black point = %f %f %f\n",bp[0],bp[1],bp[2]); break; } case icSigRgbData: { double rgb[3]; /* Lookup white value */ for (e = 0; e < inputChan; e++) rgb[e] = 1.0; mxmfunc(&os, os.v, wp, rgb); if (flags & ICX_VERBOSE) printf("Initial white point = %f %f %f\n",wp[0],wp[1],wp[2]); /* Lookup black value */ for (e = 0; e < inputChan; e++) rgb[e] = 0.0; mxmfunc(&os, os.v, bp, rgb); if (flags & ICX_VERBOSE) printf("Initial black point = %f %f %f\n",bp[0],bp[1],bp[2]); break; } default: { xicp->errc = 1; sprintf(xicp->err,"set_icxLuMatrix: can't handle color space %s", icm2str(icmColorSpaceSignature, h->colorSpace)); p->del((icxLuBase *)p); return NULL; break; } } } /* If this is a display, adjust the white point to be */ /* exactly Y = 1.0, and compensate the matrix, dispLuminance */ /* and black point accordingly. */ if (h->deviceClass == icSigDisplayClass) { double scale = 1.0/wp[1]; int i; for (i = 0; i < 9; i++) { os.v[i] *= scale; } dispLuminance *= wp[1]; for (i = 0; i < 3; i++) { wp[i] *= scale; bp[i] *= scale; } } /* Absolute luminance tag */ if (flags & ICX_WRITE_WBL && h->deviceClass == icSigDisplayClass && dispLuminance > 0.0) { icmXYZArray *wo; if ((wo = (icmXYZArray *)icco->read_tag( icco, icSigLuminanceTag)) == NULL) { xicp->errc = 1; sprintf(xicp->err,"icx_set_luminance: couldn't find luminance tag"); p->del((icxLuBase *)p); return NULL; } if (wo->ttype != icSigXYZArrayType) { xicp->errc = 1; sprintf(xicp->err,"luminance: tag has wrong type"); p->del((icxLuBase *)p); return NULL; } wo->size = 1; wo->allocate((icmBase *)wo); /* Allocate space */ wo->data[0].X = 0.0; wo->data[0].Y = dispLuminance; wo->data[0].Z = 0.0; if (flags & ICX_VERBOSE) printf("Display Luminance = %f\n", wo->data[0].Y); } /* Write white and black tags */ if ((flags & ICX_WRITE_WBL) && (flags & ICX_SET_WHITE)) { /* White Point Tag: */ icmXYZArray *wo; if ((wo = (icmXYZArray *)icco->read_tag( icco, icSigMediaWhitePointTag)) == NULL) { xicp->errc = 1; sprintf(xicp->err,"icx_set_white_black: couldn't find white tag"); p->del((icxLuBase *)p); return NULL; } if (wo->ttype != icSigXYZArrayType) { xicp->errc = 1; sprintf(xicp->err,"icx_set_white_black: white tag has wrong type"); p->del((icxLuBase *)p); return NULL; } wo->size = 1; wo->allocate((icmBase *)wo); /* Allocate space */ wo->data[0].X = wp[0]; wo->data[0].Y = wp[1]; wo->data[0].Z = wp[2]; if (flags & ICX_VERBOSE) printf("White point XYZ = %f %f %f\n",wp[0],wp[1],wp[2]); } if ((flags & ICX_WRITE_WBL) && (flags & ICX_SET_BLACK)) { /* Black Point Tag: */ icmXYZArray *wo; if ((wo = (icmXYZArray *)icco->read_tag( icco, icSigMediaBlackPointTag)) == NULL) { xicp->errc = 1; sprintf(xicp->err,"icx_set_white_black: couldn't find black tag"); p->del((icxLuBase *)p); return NULL; } if (wo->ttype != icSigXYZArrayType) { xicp->errc = 1; sprintf(xicp->err,"icx_set_white_black: black tag has wrong type"); p->del((icxLuBase *)p); return NULL; } wo->size = 1; wo->allocate((icmBase *)wo); /* Allocate space */ wo->data[0].X = bp[0]; wo->data[0].Y = bp[1]; wo->data[0].Z = bp[2]; if (flags & ICX_VERBOSE) printf("Black point XYZ = %f %f %f\n",bp[0],bp[1],bp[2]); } /* Fix matrix to be relative to D50 white point, rather than absolute */ if (flags & ICX_SET_WHITE) { icmXYZNumber swp; double mat[3][3]; if (flags & ICX_VERBOSE) printf("Fixup matrix for white point\n"); icmAry2XYZ(swp, wp); /* Transfer from parameter to matrix */ mat[0][0] = os.v[0]; mat[0][1] = os.v[1]; mat[0][2] = os.v[2]; mat[1][0] = os.v[3]; mat[1][1] = os.v[4]; mat[1][2] = os.v[5]; mat[2][0] = os.v[6]; mat[2][1] = os.v[7]; mat[2][2] = os.v[8]; /* Adapt matrix */ icmChromAdaptMatrix(ICM_CAM_MULMATRIX | ICM_CAM_BRADFORD, icmD50, swp, mat); /* Transfer back to parameters */ os.v[0] = mat[0][0]; os.v[1] = mat[0][1]; os.v[2] = mat[0][2]; os.v[3] = mat[1][0]; os.v[4] = mat[1][1]; os.v[5] = mat[1][2]; os.v[6] = mat[2][0]; os.v[7] = mat[2][1]; os.v[8] = mat[2][2]; if (flags & ICX_VERBOSE) { printf("After white point adjust:\n"); printf("Matrix = %f %f %f\n",os.v[0], os.v[1], os.v[2]); printf(" %f %f %f\n",os.v[3], os.v[4], os.v[5]); printf(" %f %f %f\n",os.v[6], os.v[7], os.v[8]); } } } if (flags & ICX_VERBOSE) printf("Done gamma/shaper and matrix creation\n"); /* Write the gamma/shaper and matrix to the icc memory structures */ if (!isGamma) { /* Creating input curves */ unsigned int ui; icmCurve *wor, *wog, *wob; wor = pmlu->redCurve; wog = pmlu->greenCurve; wob = pmlu->blueCurve; for (ui = 0; ui < wor->size; ui++) { double in, rgb[3]; for (j = 0; j < 3; j++) { in = (double)ui / (wor->size - 1.0); mxmfunc1(&os, j, os.v, &rgb[j], &in); } wor->data[ui] = rgb[0]; /* Curve values 0.0 - 1.0 */ if (!isShTRC) { wog->data[ui] = rgb[1]; wob->data[ui] = rgb[2]; } } #ifdef DEBUG_PLOT /* Display the result fit */ for (j = 0; j < 3; j++) { for (i = 0; i < XRES; i++) { double x, y; xx[i] = x = i/(double)(XRES-1); mxmfunc1(&os, j, os.v, &y, &x); y1[i] = y; } do_plot(xx,y1,NULL,NULL,XRES); } #endif /* DEBUG_PLOT */ } else { /* Gamma */ icmCurve *wor, *wog, *wob; wor = pmlu->redCurve; wog = pmlu->greenCurve; wob = pmlu->blueCurve; wor->data[0] = os.v[9]; /* Gamma values */ if (!isShTRC) { wog->data[0] = os.v[10]; wob->data[0] = os.v[11]; } } /* Matrix values */ { icmXYZArray *wor, *wog, *wob; wor = pmlu->redColrnt; wog = pmlu->greenColrnt; wob = pmlu->blueColrnt; wor->data[0].X = os.v[0]; wor->data[0].Y = os.v[3]; wor->data[0].Z = os.v[6]; wog->data[0].X = os.v[1]; wog->data[0].Y = os.v[4]; wog->data[0].Z = os.v[7]; wob->data[0].X = os.v[2]; wob->data[0].Y = os.v[5]; wob->data[0].Z = os.v[8]; /* Load into pmlu matrix and inverse ??? */ } /* Free the coordinate lists */ free(points); if (flags & ICX_VERBOSE) printf("Profile done\n"); return (icxLuBase *)p; }
/* return the delta to the target */ double get_ccast_dith(double ipat[DISIZE][DISIZE][3], double val[3]) { double itpat[DISIZE][DISIZE][3], tpat[DISIZE][DISIZE][3]; double irtpat[DISIZE][DISIZE][3], rtpat[DISIZE][DISIZE][3]; /* resulting for tpat */ double berr = 0.0; int n, k; int x, y; int i, j; int ii; struct { int x, y; } order[16] = { // Dispersed: { 3, 1 },{ 1, 3 },{ 1, 1 },{ 3, 0 },{ 3, 3 },{ 1, 2 },{ 3, 2 },{ 2, 0 }, { 1, 0 },{ 0, 3 },{ 0, 1 },{ 2, 1 },{ 2, 2 },{ 0, 0 },{ 0, 2 },{ 2, 3 } // Clustered: // { 0, 0 },{ 0, 1 },{ 1, 1 },{ 1, 0 },{ 2, 0 },{ 3, 0 },{ 3, 1 },{ 2, 1 }, // { 2, 2 },{ 3, 2 },{ 3, 3 },{ 2, 3 },{ 1, 3 },{ 1, 2 },{ 0, 2 },{ 0, 3 } }; int cix = 0; int nsur = 8, ncomb = 4; double sur[8][3]; /* RGB surrounding values to use */ double ressur[8][3]; /* resulting RGB surrounding values */ int bcc[8]; /* Best combination */ double bw[8]; /* Best weight */ int biw[8]; /* Best integer weight/16 */ double dval[3]; /* Dithered value */ double err[3], werr; double errxs; /* Tuning params */ int nitters = 300; /* No itters */ int rand_count = 150; double rand_start = 4.5; /* Ramp with itters */ double rand_end = 0.2; double rand_pow = 1.5; double mxerrxs = 2.5; /* accumulated error reset threshold */ unsigned int randv = 0x1234; /* 32 bit pseudo random sequencer based on XOR feedback */ /* generates number between 1 and 4294967295 */ #define PSRAND32F(S) (((S) & 0x80000000) ? (((S) << 1) ^ 0xa398655d) : ((S) << 1)) /* Locate the 8 surrounding RGB verticies */ for (n = 0; n < 8; n++) { for (k = 0; k < 3; k++) { if (n & (1 << k)) sur[n][k] = ceil(val[k]); else sur[n][k] = floor(val[k]); } //printf("Input sur %d: %f %f %f\n",n,sur[n][0], sur[n][1], sur[n][2], sur[n][3]); /* Figure out what RGB values to use to surround the point, */ /* and what actual RGB values to expect from using them. */ quant_rgb(n, ressur[n], sur[n]); //printf("Quant sur %d: %f %f %f\n",n,sur[n][0], sur[n][1], sur[n][2], sur[n][3]); //printf(" ressur %d: %f %f %f\n",n,ressur[n][0], ressur[n][1], ressur[n][2], ressur[n][3]); // printf("\n"); } /* Reduce this to unique surrounders */ for (nsur = 0, i = 0; i < 8; i++) { /* Check if the i'th entry is already in the list */ for (j = 0; j < nsur; j++) { for (k = 0; k < 3; k++) { if (ressur[i][k] != ressur[j][k]) break; } if (k < 3) continue; /* Unique */ break; /* Duplicate */ } if (j < nsur) /* Duplicate */ continue; /* Copy i'th to nsur */ for (k = 0; k < 3; k++) { sur[nsur][k] = sur[i][k]; ressur[nsur][k] = ressur[i][k]; } nsur++; } #ifdef DIAGNOSTICS if (vv) { printf("There are %d unique surrounders:\n",nsur); for (n = 0; n < nsur; n++) { printf("sur %f %f %f\n",ressur[n][0], ressur[n][1], ressur[n][2]); } } #endif /* Use an optimzer to set the initial values using all the unique */ /* surrounders. */ { double s[8]; optcntx cntx; ncomb = nsur; for (n = 0; n < nsur; n++) { bcc[n] = n; bw[n] = 1.0/nsur; s[n] = 0.1; } cntx.di = nsur-1; cntx.val = val; cntx.ressur = &ressur; powell(NULL, cntx.di, bw, s, 1e-4, 1000, optfunc, &cntx, NULL, NULL); /* Compute baricentric values */ bw[nsur-1] = 0.0; for (n = 0; n < (nsur-1); n++) { if (bw[n] < 0.0) bw[n] = 0.0; else if (bw[n] > 1.0) bw[n] = 1.0; bw[nsur-1] += bw[n]; } if (bw[nsur-1] > 1.0) { /* They summed to over 1.0 */ for (n = 0; n < (nsur-1); n++) bw[n] *= 1.0/bw[nsur-1]; /* Scale them down */ bw[nsur-1] = 1.0; } bw[nsur-1] = 1.0 - bw[nsur-1]; /* Remainder */ } /* Check the result */ #ifdef DIAGNOSTICS if (vv) { double tmp[3], err; /* Compute interpolated result */ for (k = 0; k < 3; k++) tmp[k] = 0.0; for (n = 0; n < ncomb; n++) { for (k = 0; k < 3; k++) tmp[k] += bw[n] * ressur[bcc[n]][k]; } /* Compute error */ err = 0.0; for (k = 0; k < 3; k++) { tmp[k] -= val[k]; err += tmp[k] * tmp[k]; } err = sqrt(err); for (n = 0; n < ncomb; n++) printf("Comb %d weight %f rgb %f %f %f\n",bcc[n],bw[n],ressur[bcc[n]][0],ressur[bcc[n]][1],ressur[bcc[n]][2]); printf("Error %f %f %f rms %f\n",tmp[0], tmp[1], tmp[2], err); printf("\n"); } #endif /* Compute the number of pixels for each surounder value */ { int sw[8], rem; /* Sort the weightings from smallest to largest */ for (n = 0; n < 8; n++) sw[n] = n; for (i = 0; i < (ncomb-1); i++) { for (j = i+1; j < ncomb; j++) { if (bw[sw[j]] < bw[sw[i]]) { int tt = sw[i]; /* Swap them */ sw[i] = sw[j]; sw[j] = tt; } } } /* Compute the nearest integer weighting out of 16 */ rem = 16; for (i = 0; i < (ncomb-1) && rem > 0; i++) { n = sw[i]; biw[n] = (int)(16.0 * bw[n] + 0.5); rem -= biw[n]; if (rem <= 0) rem = 0; } for (; i < ncomb; i++) { n = sw[i]; biw[n] = rem; } #ifdef DIAGNOSTICS if (vv) { for (n = 0; n < ncomb; n++) printf("Comb %d iweight %i rgb %f %f %f\n",bcc[n],biw[n],ressur[bcc[n]][0],ressur[bcc[n]][1],ressur[bcc[n]][2]); } #endif } /* Set the initial pattern according to the integer weighting */ for (cix = 0, n = 0; n < ncomb; n++) { for (i = 0; i < biw[n]; i++) { x = order[cix].x; y = order[cix].y; cix++; for (k = 0; k < 3; k++) { tpat[x][y][k] = itpat[x][y][k] = sur[bcc[n]][k]; rtpat[x][y][k] = irtpat[x][y][k] = ressur[bcc[n]][k]; } } } #ifdef DIAGNOSTICS /* Check initial pattern error */ if (vv) { printf("Input pat:\n"); for (x = 0; x < DISIZE; x++) { for (y = 0; y < DISIZE; y++) { if (y > 0) printf(", "); printf("%3.0f %3.0f %3.0f",rtpat[x][y][0], rtpat[x][y][1], rtpat[x][y][2]); } printf("\n"); } } #endif upsample(dval, rtpat); werr = 0.0; for (k = 0; k < 3; k++) { err[k] = dval[k] - val[k]; if (fabs(err[k]) > werr) werr = fabs(err[k]); } #ifdef DIAGNOSTICS if (vv) { printf("Target %f %f %f -> %f %f %f\n", val[0], val[1], val[2], dval[0], dval[1], dval[2]); printf("Error %f %f %f werr %f\n", err[0], err[1], err[2], werr); } #endif berr = werr; for (x = 0; x < DISIZE; x++) { for (y = 0; y < DISIZE; y++) { for (k = 0; k < 3; k++) ipat[x][y][k] = tpat[x][y][k]; } } /* Improve fit if needed */ /* This is a bit stocastic */ errxs = 0.0; for (ii = 0; ii < nitters; ii++) { /* Until we give up */ double corr[3]; /* Correction direction needed */ double bdot; int bx, by; double wycc, mm; double cell[3]; /* Cell being modified value */ double ccell[3]; /* Corrected cell */ double pcell[3]; /* Proposed new cell value */ for (k = 0; k < 3; k++) corr[k] = val[k] - dval[k]; #ifdef DIAGNOSTICS if (vv) printf("corr needed %f %f %f\n", corr[0], corr[1], corr[2]); #endif /* Scale it and limit it */ for (k = 0; k < 3; k++) { double dd = 16.0 * corr[k]; if (dd >= 1.0) dd = 1.0; else if (dd <= -1.0) dd = -1.0; else dd = 0.0; corr[k] = dd; } if (corr[0] == 0.0 && corr[1] == 0 && corr[2] == 0.0) { #ifdef DIAGNOSTICS if (vv) printf("No correction possible - done\n"); #endif break; } #ifdef DIAGNOSTICS if (vv) printf("scaled corr %f %f %f\n", corr[0], corr[1], corr[2]); #endif /* Search dither cell and surrounder for a combination */ /* that is closest to the change we want to make. */ bdot = 1e6; bx = by = n = 0; for (x = 0; x < DISIZE; x++) { double rlevel = rand_start + (rand_end - rand_start) * pow((ii % rand_count)/rand_count, rand_pow); for (y = 0; y < DISIZE; y++) { for (i = 0; i < ncomb; i++) { double dot = 0.0; for (k = 0; k < 3; k++) dot += (ressur[bcc[i]][k] - rtpat[x][y][k]) * corr[k]; /* Ramp the randomness up */ // dot += d_rand(0.0, 0.1 + (2.5-0.1) * ii/nitters); // dot += d_rand(-rlevel, rlevel); /* use a deterministic random element, so that */ /* the dither patterns are repeatable. */ randv = PSRAND32F(randv); dot += rlevel * 2.0 * ((randv - 1)/4294967294.0 - 0.5); if (dot <= 0.0) dot = 1e7; else { dot = (dot - 1.0) * (dot - 1.0); } //printf("dot %f from sur %f %f %f to pat %f %f %f\n", dot, ressur[bcc[i]][0], ressur[bcc[i]][1], ressur[bcc[i]][2], rtpat[x][y][0], rtpat[x][y][1], rtpat[x][y][2]); if (dot < bdot) { bdot = dot; bx = x; by = y; n = i; } } } } #ifdef DIAGNOSTICS if (vv) { printf("Changing cell [%d][%d] %f %f %f with dot %f\n",bx,by,rtpat[bx][by][0],rtpat[bx][by][1],rtpat[bx][by][2],bdot); printf(" to sur %d: %f %f %f\n",n, ressur[bcc[n]][0], ressur[bcc[n]][1], ressur[bcc[n]][2]); } #endif /* Substitute the best correction for this cell */ for (k = 0; k < 3; k++) { tpat[bx][by][k] = sur[bcc[n]][k]; rtpat[bx][by][k] = ressur[bcc[n]][k]; } #ifdef DIAGNOSTICS if (vv) { printf("Input pat:\n"); for (x = 0; x < DISIZE; x++) { for (y = 0; y < DISIZE; y++) { if (y > 0) printf(", "); printf("%3.0f %3.0f %3.0f",rtpat[x][y][0], rtpat[x][y][1], rtpat[x][y][2]); } printf("\n"); } } #endif upsample(dval, rtpat); werr = 0.0; for (k = 0; k < 3; k++) { err[k] = dval[k] - val[k]; if (fabs(err[k]) > werr) werr = fabs(err[k]); } if (werr > berr) { errxs += werr - berr; } /* New best */ if (werr < berr) { berr = werr; errxs = 0.0; for (x = 0; x < DISIZE; x++) { for (y = 0; y < DISIZE; y++) { for (k = 0; k < 3; k++) { ipat[x][y][k] = tpat[x][y][k]; itpat[x][y][k] = tpat[x][y][k]; irtpat[x][y][k] = rtpat[x][y][k]; } } } } #ifdef DIAGNOSTICS if (vv) { printf("Target %f %f %f -> %f %f %f\n", val[0], val[1], val[2], dval[0], dval[1], dval[2]); printf("Error %f %f %f werr %f\n", err[0], err[1], err[2], werr); } #endif if (berr < 0.11) { #ifdef DIAGNOSTICS if (vv) printf("best error %f < 0.11 - give up\n",berr); #endif break; } /* If we're not making progress, reset to the last best */ if (errxs > mxerrxs) { #ifdef DIAGNOSTICS if (vv) printf("Restarting at ii %d \n",ii); #endif errxs = 0.0; for (x = 0; x < DISIZE; x++) { for (y = 0; y < DISIZE; y++) { for (k = 0; k < 3; k++) { tpat[x][y][k] = itpat[x][y][k]; rtpat[x][y][k] = irtpat[x][y][k]; } } } } } #ifdef DIAGNOSTICS if (vv) { printf("Returning best error %f pat:\n",berr); for (y = 0; y < DISIZE; y++) { for (x = 0; x < DISIZE; x++) { if (x > 0) printf(", "); printf("%3.0f %3.0f %3.0f",ipat[x][y][0], ipat[x][y][1], ipat[x][y][2]); } printf("\n"); } } #endif return berr; }
JNIEXPORT jdouble JNICALL Java_com_jiminger_util_Minimizer_dominimize (JNIEnv * env, jclass, jobject jfunc, jdoubleArray p, jobjectArray xi, jdouble jftol, jdoubleArray minVal) { int n = (int)env->GetArrayLength(p); jdouble* pd = new jdouble[n]; jdouble* xirowjd = new jdouble[n]; env->GetDoubleArrayRegion(p,0,(jsize)n,pd); float* pf = vector(1,n); float** xif = matrix(1,n,1,n); for (int i = 0; i < n; i++) { pf[i + 1] = (float)pd[i]; jdoubleArray tmpDoubleArray = (jdoubleArray)env->GetObjectArrayElement(xi,i); env->GetDoubleArrayRegion(tmpDoubleArray,0,n,xirowjd); for (int j = 0; j < n; j++) xif[i + 1][j + 1] = (float)xirowjd[j]; } float ftol = (float)jftol; int iter; float fret; // set side affect globals gjfunc = jfunc; genv = env; gFuncClass = env->GetObjectClass(jfunc); gFuncMeth = env->GetMethodID(gFuncClass,"func","([D)D"); start = 1; end = n; gjvArray = genv->NewDoubleArray(n); exceptionHappens = false; /// now i have xif, pf, ftol, powell(pf, xif, n, ftol, &iter, &fret, bridgefunc); // if (nrIsError()) // { // JNU_ThrowByName(env,"com/jiminger/util/MinimizerException",nrGetErrorMessage()); // return -1.0; // } // print_vector("p:",pf,1,n); // print_matix("xi:",xif,1,n,1,n); // copy pf (the result) back into pd for (int i = 1; i <= n; i++) pd[i - 1] = (jdouble)pf[i]; // now set minVal for the return env->SetDoubleArrayRegion(minVal,0,n,pd); // clear side affect globals env->DeleteLocalRef(gjvArray); gjvArray = NULL; gjfunc = NULL; genv = NULL; gFuncClass = NULL; gFuncMeth = NULL; start=0; end=0; free_matrix(xif,1,n,1,n); free_vector(pf,1,n); delete [] xirowjd; delete [] pd; return (jdouble)fret; }
/* Create a ccmx from measurements. return nz on error. */ static int create_ccmx(ccmx *p, char *desc, /* General description (optional) */ char *inst, /* Instrument description to copy from */ char *disp, /* Display make and model (optional) */ disptech dtech, /* Display technology enum */ int refrmode, /* Display refresh mode, -1 = unknown, 0 = n, 1 = yes */ int cbid, /* Display type calibration base index, 0 = unknown */ char *sel, /* UI selector characters - NULL for none */ char *refd, /* Reference spectrometer description (optional) */ int oem, /* NZ if OEM source */ int npat, /* Number of samples in following arrays */ double (*refs)[3], /* Array of XYZ values from spectrometer */ double (*cols)[3] /* Array of XYZ values from colorimeter */ ) { int i, mxix; double maxy = -1e6; cntx cx; double cp[9], sa[9]; if ((p->desc = desc) != NULL && (p->desc = strdup(desc)) == NULL) { sprintf(p->err, "create_ccmx: malloc failed"); return 2; } if ((p->inst = inst) != NULL && (p->inst = strdup(inst)) == NULL) { sprintf(p->err, "create_ccmx: malloc failed"); return 2; } if ((p->disp = disp) != NULL && (p->disp = strdup(disp)) == NULL) { sprintf(p->err, "create_ccmx: malloc failed"); return 2; } p->dtech = dtech; p->refrmode = refrmode; p->cc_cbid = cbid; if (sel != NULL) { if ((p->sel = strdup(sel)) == NULL) { sprintf(p->err, "create_ccmx: malloc sel failed"); return 2; } } if ((p->ref = refd) != NULL && (p->ref = strdup(refd)) == NULL) { sprintf(p->err, "create_ccmx: malloc failed"); return 2; } p->oem = oem; /* Find the white patch */ cx.npat = npat; cx.refs = refs; cx.cols = cols; for (i = 0; i < npat; i++) { if (refs[i][1] > maxy) { maxy = refs[i][1]; cx.wix = i; } } #ifdef DEBUG printf("white = %f %f %f\n",refs[cx.wix][0],refs[cx.wix][1],refs[cx.wix][1]); #endif cx.wh.X = refs[cx.wix][0]; cx.wh.Y = refs[cx.wix][1]; cx.wh.Z = refs[cx.wix][2]; /* Starting matrix */ cp[0] = 1.0; cp[1] = 0.0; cp[2] = 0.0; cp[3] = 0.0; cp[4] = 1.0; cp[5] = 0.0; cp[6] = 0.0; cp[7] = 0.0; cp[8] = 1.0; for (i = 0; i < 9; i++) sa[i] = 0.1; if (powell(NULL, 9, cp, sa, 1e-6, 2000, optf, &cx, NULL, NULL) < 0.0) { sprintf(p->err, "create_ccmx: powell() failed"); return 1; } p->matrix[0][0] = cp[0]; p->matrix[0][1] = cp[1]; p->matrix[0][2] = cp[2]; p->matrix[1][0] = cp[3]; p->matrix[1][1] = cp[4]; p->matrix[1][2] = cp[5]; p->matrix[2][0] = cp[6]; p->matrix[2][1] = cp[7]; p->matrix[2][2] = cp[8]; /* Compute the average and max errors */ p->av_err = p->mx_err = 0.0; for (i = 0; i < npat; i++) { double tlab[3], xyz[3], lab[3], de; icmXYZ2Lab(&cx.wh, tlab, cx.refs[i]); icmMulBy3x3(xyz, p->matrix, cx.cols[i]); icmXYZ2Lab(&cx.wh, lab, xyz); de = icmCIE94(tlab, lab); p->av_err += de; if (de > p->mx_err) { p->mx_err = de; mxix = i; } //printf("~1 %d: de %f, tlab %f %f %f, lab %f %f %f\n",i,de,tlab[0], tlab[1], tlab[2], lab[0], lab[1], lab[2]); } p->av_err /= (double)npat; //printf("~1 max error is index %d\n",mxix); #ifdef DEBUG printf("Average error %f, max %f\n",p->av_err,p->mx_err); printf("Correction matrix is:\n"); printf(" %f %f %f\n", cp[0], cp[1], cp[2]); printf(" %f %f %f\n", cp[3], cp[4], cp[5]); printf(" %f %f %f\n", cp[6], cp[7], cp[8]); #endif return 0; }
/* Fit the curve to the given points */ static void mcv_fit(mcv *p, int verb, /* Vebosity level, 0 = none */ int order, /* Number of curve orders, 1..MCV_MAXORDER */ mcvco *d, /* Array holding scattered initialisation data */ int ndp, /* Number of data points */ double smooth /* Degree of smoothing, 1.0 = normal */ ) { int i; double *sa; /* Search area */ double *pms; /* Parameters to optimise */ double min, max; p->verb = verb; p->smooth = smooth; p->luord = order+2; /* Add two for offset and scale */ if (p->pms != NULL) free(p->pms); if ((p->pms = (double *)calloc(p->luord, sizeof(double))) == NULL) error ("Malloc failed"); if ((pms = (double *)calloc(p->luord, sizeof(double))) == NULL) error ("Malloc failed"); if ((sa = (double *)calloc(p->luord, sizeof(double))) == NULL) error ("Malloc failed"); if ((p->dv = (double *)calloc(p->luord, sizeof(double))) == NULL) error ("Malloc failed"); #ifdef DEBUG printf("mcv_fit with %d points (noos = %d)\n",ndp,p->noos); #endif /* Establish the range of data values */ min = 1e38; /* Locate min, and make that offset */ max = -1e38; /* Locate max */ for (i = 0; i < ndp; i++) { if (d[i].v < min) min = d[i].v; if (d[i].v > max) max = d[i].v; #ifdef DEBUG printf("point %d is %f %f\n",i,d[i].p,d[i].v); #endif } if (p->noos) { p->pms[0] = min = 0.0; p->pms[1] = max = 1.0; } else { /* Set offset and scale to reasonable values */ p->pms[0] = min; p->pms[1] = max - min; } p->dra = max - min; if (p->dra <= 1e-12) error("Mcv max - min %e too small",p->dra); /* Use powell to minimise the sum of the squares of the */ /* input points to the curvem, plus a parameter damping factor. */ p->d = d; p->ndp = ndp; for (i = 0; i < p->luord; i++) sa[i] = 0.2; #ifdef NEVER if (powell(&p->resid, p->luord-p->noos, p->pms+p->noos, sa+p->noos, POWTOL, MAXITS, mcv_opt_func, (void *)p, NULL, NULL) != 0) error ("Mcv fit powell failed"); #else if (conjgrad(&p->resid, p->luord-p->noos, p->pms+p->noos, sa+p->noos, POWTOL, MAXITS, mcv_opt_func, mcv_dopt_func, (void *)p, NULL, NULL) != 0) { #ifndef NEVER fprintf(stderr,"Mcv fit conjgrad failed with %d points:\n",ndp); for (i = 0; i < ndp; i++) { fprintf(stderr," %d: %f -> %f\n",i,d->p, d->v); } #endif error ("Mcv fit conjgrad failed"); } #endif free(p->dv); p->dv = NULL; free(sa); free(pms); }
/* Do a reverse lookup on the mpp */ static void mpp_rev( mpp *mppo, double limit, /* Ink limit */ double *out, /* Device value */ double *in /* Lab target */ ) { int i, j; inkmask imask; /* Device Ink mask */ int inn; revlus rs; /* Reverse lookup structure */ double sr[MAX_CHAN]; /* Search radius */ double tt; /* !!! This needs to be cached elsewhere !!!! */ static saent *start = NULL; /* Start array */ static int nisay = 0; /* Number in start array */ mppo->get_info(mppo, &imask, &inn, NULL, NULL, NULL, NULL, NULL); rs.di = inn; /* Number of device channels */ rs.Lab[0] = in[0]; /* Target PCS value */ rs.Lab[1] = in[1]; rs.Lab[2] = in[2]; rs.dev2lab = mppo->lookup; /* Dev->PCS Lookup function and context */ rs.d2lcntx = (void *)mppo; rs.ilimit = limit; /* Total ink limit */ { double Labw[3]; /* Lab value of white */ double Lab[MAX_CHAN][3]; /* Lab value of device primaries */ double min, max; /* Lookup the L value of all the device primaries */ for (j = 0; j < inn; j++) out[j] = 0.0; mppo->lookup(mppo, Labw, out); for (i = 0; i < inn; i++) { double tt; double de; out[i] = 1.0; mppo->lookup(mppo, Lab[i], out); /* Use DE measure heavily weighted towards L only */ tt = L_WEIGHT * (Labw[0] - Lab[i][0]); de = tt * tt; tt = 0.4 * (Labw[1] - Lab[i][1]); de += tt * tt; tt = 0.2 * (Labw[2] - Lab[i][2]); de += tt * tt; rs.oweight[i] = sqrt(de); out[i] = 0.0; } /* Normalise weights from 0 .. 1.0 */ min = 1e6, max = 0.0; for (j = 0; j < inn; j++) { if (rs.oweight[j] < min) min = rs.oweight[j]; if (rs.oweight[j] > max) max = rs.oweight[j]; } for (j = 0; j < inn; j++) rs.oweight[j] = (rs.oweight[j] - min)/(max - min); { for (j = 0; j < inn; j++) rs.sord[j] = j; for (i = 0; i < (inn-1); i++) { for (j = i+1; j < inn; j++) { if (rs.oweight[rs.sord[i]] > rs.oweight[rs.sord[j]]) { int xx; xx = rs.sord[i]; rs.sord[i] = rs.sord[j]; rs.sord[j] = xx; } } } } for (j = 0; j < inn; j++) printf("~1 oweight[%d] = %f\n",j,rs.oweight[j]); for (j = 0; j < inn; j++) printf("~1 sorted oweight[%d] = %f\n",j,rs.oweight[rs.sord[j]]); } /* Initialise the start point array */ if (start == NULL) { int mxstart; int steps = 4; DCOUNT(dix, MAX_CHAN, inn, 0, 0, steps); printf("~1 initing start point array\n"); for (mxstart = 1, j = 0; j < inn; j++) /* Compute maximum entries */ mxstart *= steps; printf("~1 mxstart = %d\n",mxstart); if ((start = malloc(sizeof(saent) * mxstart)) == NULL) error("mpp_rev malloc of start array failed\n"); nisay = 0; DC_INIT(dix); while(!DC_DONE(dix)) { double sum = 0.0; /* Figure device values */ for (j = 0; j < inn; j++) { sum += start[nisay].dev[j] = dix[j]/(steps-1.0); } if (sum <= limit) { /* Within ink limit */ double oerr; double tot; /* Compute Lab */ mppo->lookup(mppo, start[nisay].Lab, start[nisay].dev); /* Compute order error */ /* Skip first 3 colorants */ oerr = tot = 0.0; for (j = 3; j < inn; j++) { int ix = rs.sord[j]; /* Sorted order index */ double vv = start[nisay].dev[ix]; double we = (double)j - 2.0; /* Increasing weight */ if (vv > 0.0001) { oerr += tot + we * vv; } tot += we; } oerr /= tot; start[nisay].oerr = oerr; nisay++; } DC_INC(dix); } printf("~1 start point array done, %d out of %d valid\n",nisay,mxstart); } /* Search the start array for closest matching point */ { double bde = 1e38; int bix = 0; for (i = 0; i < nisay; i++) { double de; /* Compute delta E */ for (de = 0.0, j = 0; j < 3; j++) { double tt = rs.Lab[j] - start[i].Lab[j]; de += tt * tt; } de += 0.0 * start[i].oerr; if (de < bde) { bde = de; bix = i; } } printf("Start point at index %d, bde = %f, dev = ",bix,bde); for (j = 0; j < inn; j++) { printf("%f",start[bix].dev[j]); if (j < (inn-1)) printf(" "); } printf("\n"); for (j = 0; j < inn; j++) { out[j] = start[bix].dev[j]; sr[j] = 0.1; } } #ifdef NEVER out[0] = 0.0; out[1] = 0.0; out[2] = 0.45; out[3] = 0.0; out[4] = 0.0; out[5] = 0.0; out[6] = 0.6; out[7] = 1.0; #endif #ifdef NEVER out[0] = 1.0; out[1] = 0.0; out[2] = 0.0; out[3] = 0.0; out[4] = 0.0; out[5] = 0.0; out[6] = 0.0; out[7] = 0.0; #endif #ifdef NEVER rs.pass = 0; if (powell(&tt, inn, out, sr, 0.001, 5000, revoptfunc, (void *)&rs) != 0) { error("Powell failed inside mpp_rev()"); } printf("\n\n\n\n\n\n#############################################\n"); printf("~1 after first pass got "); for (j = 0; j < inn; j++) { printf("%f",out[j]); if (j < (inn-1)) printf(" "); } printf("\n"); printf("#############################################\n\n\n\n\n\n\n\n"); #endif #ifndef NEVER out[0] = 0.0; out[1] = 0.0; out[2] = 0.0; out[3] = 0.0; out[4] = 0.0; out[5] = 1.0; out[6] = 0.0; out[7] = 0.0; #endif #ifndef NEVER rs.pass = 1; if (powell(&tt, inn, out, sr, 0.00001, 5000, revoptfunc, (void *)&rs, NULL, NULL) != 0) { error("Powell failed inside mpp_rev()"); } #endif snap2gamut(&rs, out); }
int main(int argc, char *argv[]) { int i,j,k; int fa,nfa; /* current argument we're looking at */ int verb = 0; static char inname[200] = { 0 }; /* Input cgats file base name */ static char outname[200] = { 0 }; /* Output cgats file base name */ cgats *icg; /* input cgats structure */ cgats *ocg; /* output cgats structure */ time_t clk = time(0); struct tm *tsp = localtime(&clk); char *atm = asctime(tsp); /* Ascii time */ int ti; /* Temporary index */ edatas ed; /* Optimising function data structure */ double resid[4]; double presid,dresid; double sarea; error_program = argv[0]; if (argc <= 1) usage(); /* Process the arguments */ for(fa = 1;fa < argc;fa++) { nfa = fa; /* skip to nfa if next argument is used */ if (argv[fa][0] == '-') /* Look for any flags */ { char *na = NULL; /* next argument after flag, null if none */ if (argv[fa][2] != '\000') na = &argv[fa][2]; /* next is directly after flag */ else { if ((fa+1) < argc) { if (argv[fa+1][0] != '-') { nfa = fa + 1; na = argv[nfa]; /* next is seperate non-flag argument */ } } } if (argv[fa][1] == '?') usage(); else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') verb = 1; else usage(); } else break; } /* Get the file name argument */ if (fa >= argc || argv[fa][0] == '-') usage(); strcpy(inname,argv[fa]); strcat(inname,".ti3"); strcpy(outname,argv[fa]); strcat(outname,".pr1"); icg = new_cgats(); /* Create a CGATS structure */ icg->add_other(icg, "CTI3"); /* our special input type is Calibration Target Information 3 */ if (icg->read_name(icg, inname)) error("CGATS file read error : %s",icg->err); if (icg->ntables == 0 || icg->t[0].tt != tt_other || icg->t[0].oi != 0) error ("Input file isn't a CTI3 format file"); if (icg->ntables != 1) error ("Input file doesn't contain exactly one table"); if ((ed.npat = icg->t[0].nsets) <= 0) error ("No sets of data"); if (verb) { printf("No of test patches = %d\n",ed.npat); } if ((ed.cols = (col *)malloc(sizeof(col) * ed.npat)) == NULL) error("Malloc failed!"); /* Setup output cgats file */ /* This is a simple interpolation CMYK -> XYZ device profile */ ocg = new_cgats(); /* Create a CGATS structure */ ocg->add_other(ocg, "PROF1"); /* our special type is Profile type 1 */ ocg->add_table(ocg, tt_other, 0); /* Start the first table */ ocg->add_kword(ocg, 0, "DESCRIPTOR", "Argyll Calibration Device Profile Type 1",NULL); ocg->add_kword(ocg, 0, "ORIGINATOR", "Argyll sprof", NULL); atm[strlen(atm)-1] = '\000'; /* Remove \n from end */ ocg->add_kword(ocg, 0, "CREATED",atm, NULL); /* Figure out the color space */ if ((ti = icg->find_kword(icg, 0, "COLOR_REP")) < 0) error ("Input file doesn't contain keyword COLOR_REPS"); if (strcmp(icg->t[0].kdata[ti],"CMYK_XYZ") == 0) { int ci, mi, yi, ki; int Xi, Yi, Zi; if ((ci = icg->find_field(icg, 0, "CMYK_C")) < 0) error ("Input file doesn't contain field CMYK_C"); if (icg->t[0].ftype[ci] != r_t) error ("Field CMYK_C is wrong type"); if ((mi = icg->find_field(icg, 0, "CMYK_M")) < 0) error ("Input file doesn't contain field CMYK_M"); if (icg->t[0].ftype[mi] != r_t) error ("Field CMYK_M is wrong type"); if ((yi = icg->find_field(icg, 0, "CMYK_Y")) < 0) error ("Input file doesn't contain field CMYK_Y"); if (icg->t[0].ftype[yi] != r_t) error ("Field CMYK_Y is wrong type"); if ((ki = icg->find_field(icg, 0, "CMYK_K")) < 0) error ("Input file doesn't contain field CMYK_K"); if (icg->t[0].ftype[ki] != r_t) error ("Field CMYK_K is wrong type"); if ((Xi = icg->find_field(icg, 0, "XYZ_X")) < 0) error ("Input file doesn't contain field XYZ_X"); if (icg->t[0].ftype[Xi] != r_t) error ("Field XYZ_X is wrong type"); if ((Yi = icg->find_field(icg, 0, "XYZ_Y")) < 0) error ("Input file doesn't contain field XYZ_Y"); if (icg->t[0].ftype[Yi] != r_t) error ("Field XYZ_Y is wrong type"); if ((Zi = icg->find_field(icg, 0, "XYZ_Z")) < 0) error ("Input file doesn't contain field XYZ_Z"); if (icg->t[0].ftype[Zi] != r_t) error ("Field XYZ_Z is wrong type"); for (i = 0; i < ed.npat; i++) { double XYZ[3]; ed.cols[i].c = *((double *)icg->t[0].fdata[i][ci]) / 100.0; ed.cols[i].m = *((double *)icg->t[0].fdata[i][mi]) / 100.0; ed.cols[i].y = *((double *)icg->t[0].fdata[i][yi]) / 100.0; ed.cols[i].k = *((double *)icg->t[0].fdata[i][ki]) / 100.0; XYZ[0] = *((double *)icg->t[0].fdata[i][Xi]) / 100.0; XYZ[1] = *((double *)icg->t[0].fdata[i][Yi]) / 100.0; XYZ[2] = *((double *)icg->t[0].fdata[i][Zi]) / 100.0; icmXYZ2Lab(&icmD50, ed.cols[i].Lab, XYZ); } /* Initialise the model */ ed.gam[0] = 1.0; /* First four are CMYK gamma values */ ed.gam[1] = 1.0; ed.gam[2] = 1.0; ed.gam[3] = 1.0; /* Initialise interpolation end points for each combination of primary, */ /* with all combinations close to black being represented by param[7]. */ ed.k[0][0] = .82; ed.k[1][0] = .83; ed.k[2][0] = .75; /* White */ ed.k[0][1] = .66; ed.k[1][1] = .72; ed.k[2][1] = .05; /* Y */ ed.k[0][2] = .27; ed.k[1][2] = .12; ed.k[2][2] = .06; /* M */ ed.k[0][3] = .27; ed.k[1][3] = .12; ed.k[2][3] = .00; /* MY */ ed.k[0][4] = .09; ed.k[1][4] = .13; ed.k[2][4] = .44; /* C */ ed.k[0][5] = .03; ed.k[1][5] = .10; ed.k[2][5] = .04; /* C Y */ ed.k[0][6] = .02; ed.k[1][6] = .01; ed.k[2][6] = .05; /* CM */ ed.k[0][7] = .01; ed.k[1][7] = .01; ed.k[2][7] = .01; /* Black */ sarea = 0.3; presid = dresid = 100.0; for (k=0; /* dresid > 0.0001 && */ k < 40; k++) { /* Untill we're done */ double sresid; double sr[8]; double p[8]; /* Adjust the gamma */ for (i = 0; i < 4; i++) sr[i] = 0.1; /* Device space search radius */ if (powell(&resid[3], 4, &ed.gam[0], sr, 0.1, 1000, efunc1, (void *)&ed, NULL, NULL) != 0) error ("Powell failed"); /* Adjust the primaries */ calc_bc(&ed); /* Calculate blend coefficients */ for (i = 0; i < 8; i++) sr[i] = 0.2; /* Device space search radius */ sresid = 99.0; for (j = 0; j < 3; j++) { /* For each of X, Y and Z */ ed.xyzi = j; for (i = 0; i < 8; i++) p[i] = ed.k[j][i]; printf("##############\n"); printf("XYZ = %d\n",j); if (powell(&resid[j], 8, p, sr, 0.1, 1000, efunc2, (void *)&ed, NULL, NULL) != 0) error ("Powell failed"); for (i = 0; i < 8; i++) ed.k[j][i] = p[i]; if (sresid > resid[j]) sresid = resid[j]; } dresid = presid - sresid; if (dresid < 0.0) dresid = 100.0; presid = sresid; printf("~1 presid = %f, sresid = %f, dresid = %f\n",presid, sresid, dresid); } /* Fields we want */ ocg->add_kword(ocg, 0, "DSPACE","CMYK", NULL); ocg->add_kword(ocg, 0, "DTYPE","PRINTER", NULL); ocg->add_field(ocg, 0, "PARAM_ID", i_t); ocg->add_field(ocg, 0, "PARAM", r_t); /* Output model parameters */ for (j = 0; j < 4; j++) ocg->add_set(ocg, 0, j, ed.gam[j]); for (j = 0; j < 3; j++) { for (i = 0; i < 8; i++) ocg->add_set(ocg, 0, 10 * (j + 1) + i, 100.0 * ed.k[j][i]); } if (verb) { double aver = 0.0; double maxer = 0.0; for (i = 0; i < ed.npat; i++) { double err = sqrt(ed.cols[i].err); if (err > maxer) maxer = err; aver += err; } aver = aver/((double)i); printf("Average fit error = %f, maximum = %f\n",aver,maxer); } } else if (strcmp(icg->t[0].kdata[ti],"RGB") == 0) { error ("We can't handle RGB !"); } else if (strcmp(icg->t[0].kdata[ti],"W") == 0) { error ("We can't handle Grey !"); } else error ("Input file keyword COLOR_REPS has unknown value"); if (ocg->write_name(ocg, outname)) error("Write error : %s",ocg->err); free(ed.cols); ocg->del(ocg); /* Clean up */ icg->del(icg); /* Clean up */ return 0; }
int main(int argc, char* argv[]) { double *params, **xi, **pxi, mlk; double *y; long n, iter, i, j, nfunk; char* fileName = "armasq.dat"; xobs = loadmat(fileName, &nn, &mm); nn *= mm; if(argc < 3) { printf("Need to specify p an q\n"); exit(0); } else { p = atoi(argv[1]); q= atoi(argv[2]); // printf("%d %d\n", p, q); } n = p + q; if(argc > 5) { fileName = argv[4]; } if (argc < 4) { printf( "need to specify the minimization method:\n\tarma p\tfor Powell\n\tarma n\tfor Nelder and Mead\n"); exit(0); } else if (argv[3][0] == 'p') { printf("Using Powell method\n"); params = vector(n); xi = (double**) malloc(n * sizeof(double*)); //intialize the initial point and directions for (i = 0; i < n; i++) { params[i] = 0.0; xi[i] = vector(n); for (j = 0; j < n; j++) { if (i == j) xi[i][j] = .1; else xi[i][j] = 0; } } powell(params, xi, n, TOLERANCE, &iter, &mlk, armalk_wrapper); printf("Maximum LK %E\t after %ld iterations with parameters:\n", 1/mlk, iter); for (i = 0; i < n; i++) { printf("%E\n", params[i]); } free_vector(params); for (i = 0; i < n; i++) { free_vector(xi[i]); } free(xi); } else if (argv[3][0] == 'n') { printf("Using Nelder & Mead method\n"); y = vector(n+1); xi = (double**) malloc((n + 1) * sizeof(double*)); //intialize the initial points for (i = 0; i < n + 1; i++) { xi[i] = vector(n); for (j = 0; j < n; j++) { if (i == j) xi[i][j] = .1; else xi[i][j] = 0; } y[i] = armalk_wrapper(xi[i]); } amoeba(xi, y, n, TOLERANCE, armalk_wrapper, &nfunk); printf("After %ld function evaluations, the converged new points are:\n", nfunk); for (i = 0; i < n+1; i++) { printf("\tPoint %ld: MLK = %E, parameters:", i, 1/y[i]); for (j = 0; j < n; j++) printf(" %E ", xi[i][j]); printf("\n"); } free_vector(y); for (i = 0; i < n + 1; i++) { free_vector(xi[i]); } free(xi); } free(xobs); return 1; }