/* basic pixel statistics */ #include #include #include #include "ip.h" /* given an image and a region within, return some basic stats. * N.B. we do /not/ check that the region has finite area and lies within image. */ void regionStats (ImRegion *rp, ImStats *sp) { CamPix *im = &rp->im[rp->ry*rp->iw + rp->rx]; int rn = rp->rw * rp->rh; int wrap = rp->iw - rp->rw; double sum, sum2; int hist[NCAMPIX]; int min, max; double v; int x, y; int i, n; /* scan region gathering stats */ memset (hist, 0, sizeof(hist)); min = max = im[0]; sp->maxatx = rp->rx; sp->maxaty = rp->ry; sum = sum2 = 0; for (y = 0; y < rp->rh; y++) { for (x = 0; x < rp->rw; x++) { int p = (int)(*im++); hist[p]++; sum += (double)p; sum2 += (double)p*p; if (p > max) { max = p; sp->maxatx = rp->rx+x; sp->maxaty = rp->ry+y; } if (p < min) min = p; } im += wrap; } sp->min = min; sp->max = max; if (rn > 1) { sp->mean = sum/rn; v = (sum2 - sum*sp->mean)/(rn-1); sp->std = v <= 0.0 ? 0.0 : sqrt (v); } else { sp->mean = (sp->min+sp->max)/2; sp->std = (sp->max-sp->min)/3; } /* scan 25..75 percentile for central stats */ n = 0; sum = sum2 = 0; min = max = -1; /* min = p@25%, max = p@50% */ x = 0; /* pixels in center half */ for (i = 0; n <= 3*rn/4; i++) { n += hist[i]; if (max < 0 && n >= rn/2) max = i; if (min < 0 && n >= rn/4) min = i; if (min >= 0) { sum += (double)i*hist[i]; sum2 += (double)i*i*hist[i]; x += hist[i]; } } /* med is 50 percentile */ sp->median = max; /* compute central mean/std */ if (x > 1) { sp->cmean = sum/x; v = (sum2 - sum*sp->cmean)/(x-1); sp->cstd = v <= 0.0 ? 0.0 : sqrt (v); } else { sp->cmean = (min+max)/2; sp->cstd = (max-min)/3; } } /* return min, max and median of ring of radius [r..r+1) centered at ip. * imw is width of host image. any return pointers may be NULL if unwanted. * N.B. we do no range checking. */ void ringStats (CamPix *ip, int imw, int r, int *minp, int *maxp, int *medp) { CamPix ring[1000]; int r2min = r*r; int r2max = (r+1)*(r+1); int rmin = MAXCAMPIX; int rmax = 0; int nr = 0; int rx, ry; for (ry = -r; ry <= r; ry++) { CamPix *iprow = &ip[ry*imw - r]; int d2, ry2 = ry*ry; for (rx = -r; rx <= r; rx++) { CamPix p1 = (*iprow++); d2 = rx*rx + ry2; if (d2 >= r2min && d2 < r2max) { ring[nr++] = p1; if (p1 < rmin) rmin = p1; if (p1 > rmax) rmax = p1; } } } if (minp) *minp = rmin; if (maxp) *maxp = rmax; if (medp) *medp = cmedian (ring, nr); } /* return position and (optional) "mass" of circular region [0..r] centered * at ip, assumed to be from host image of width imw. * N.B. we do no range checking. */ void starCentroid (CamPix *ip, int imw, int r, int sky, double *dxp, double *dyp, int *massp) { int sx = 0, sy = 0, sm = 0; int r2 = r*r; int rx, ry; for (ry = -r; ry <= r; ry++) { CamPix *iprow = &ip[ry*imw - r]; int ry2 = ry*ry; for (rx = -r; rx <= r; rx++) { int p1 = (int)(*iprow++) - sky; if (p1 > 0 && rx*rx + ry2 <= r2) { sx += rx*p1; sy += ry*p1; sm += p1; } } } *dxp = (double)sx/sm; *dyp = (double)sy/sm; if (massp) *massp = sm; } /* check and fix the given region so as to be all within the image. * return 0 if successful, -1 if region is _completely_ outside the image */ int clampRegion (ImRegion *rp) { if (rp->rx < 0) { rp->rw += rp->rx; rp->rx = 0; } else if (rp->rx + rp->rw > rp->iw) { rp->rw = rp->iw - rp->rx; } if (rp->rw <= 0) return (-1); if (rp->ry < 0) { rp->rh += rp->ry; rp->ry = 0; } else if (rp->ry + rp->rh > rp->ih) { rp->rh = rp->ih - rp->ry; } if (rp->rh <= 0) return (-1); return (0); }