mirror of https://github.com/XEphem/XEphem.git
192 lines
4.0 KiB
C
192 lines
4.0 KiB
C
/* basic pixel statistics */
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#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);
|
|
}
|
|
|
|
/* For RCS Only -- Do Not Edit */
|
|
static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: stats.c,v $ $Date: 2004/05/20 06:02:24 $ $Revision: 1.6 $ $Name: $"};
|