mirror of
https://github.com/eddyem/astrovideoguide_v3.git
synced 2026-03-22 01:31:25 +03:00
LocCorr - pre-alpha version of INASAN corrector
This commit is contained in:
189
LocCorr/improc.c
189
LocCorr/improc.c
@@ -25,22 +25,28 @@
|
||||
|
||||
#include "binmorph.h"
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "draw.h"
|
||||
#include "grasshopper.h"
|
||||
#include "fits.h"
|
||||
#include "improc.h"
|
||||
#include "inotify.h"
|
||||
#include "median.h"
|
||||
|
||||
// how many frames will be averaged to count image deviation
|
||||
#define AVERAGING_ARRAY_SIZE (5)
|
||||
// tolerance of deviations by X and Y axis
|
||||
#define XY_TOLERANCE (1.)
|
||||
#include "pusirobo.h"
|
||||
|
||||
static FILE *fXYlog = NULL;
|
||||
|
||||
static double Xtarget = -1., Ytarget = -1.; // target coordinates
|
||||
static double tstart = 0.; // time of logging start
|
||||
int stopwork = 0;
|
||||
|
||||
// function to process calculated corrections
|
||||
static void (*proc_corr)(double, double, int) = NULL;
|
||||
// function to get stepper server status
|
||||
char *(*stepstatus)(char *buf, int buflen) = NULL;
|
||||
// set new status
|
||||
char *(*setstepstatus)(const char *newstatus, char *buf, int buflen) = NULL;
|
||||
// move focus
|
||||
char *(*movefocus)(const char *newstatus, char *buf, int buflen) = NULL;
|
||||
|
||||
typedef struct{
|
||||
uint32_t area; // object area in pixels
|
||||
@@ -52,19 +58,20 @@ typedef struct{
|
||||
double ysigma;
|
||||
} object;
|
||||
|
||||
typedef enum{
|
||||
PROCESS_NONE,
|
||||
PROCESS_PUSIROBO
|
||||
} postproc_type;
|
||||
|
||||
static postproc_type postprocess = PROCESS_NONE;
|
||||
|
||||
static bool save_fits(Image *I, const char *name){
|
||||
uint8_t *outp = NULL;
|
||||
if(GP->equalize)
|
||||
outp = equalize(I, 1, GP->throwpart);
|
||||
else
|
||||
outp = linear(I, 1);
|
||||
char fname[PATH_MAX];
|
||||
char *flname = strdup(name);
|
||||
char *pt = strrchr(flname, '.');
|
||||
snprintf(fname, PATH_MAX, name);
|
||||
char *pt = strrchr(fname, '.');
|
||||
if(pt) *pt = 0;
|
||||
snprintf(fname, PATH_MAX, "%s.jpg", flname);
|
||||
stbi_write_jpg(fname, I->width, I->height, 1, outp, 95);
|
||||
FREE(outp);
|
||||
strncat(fname, ".jpg", PATH_MAX);
|
||||
Image_write_jpg(I, fname, theconf.equalize);
|
||||
unlink(name);
|
||||
return FITS_write(name, I);
|
||||
}
|
||||
@@ -77,22 +84,37 @@ static void savebin(uint8_t *b, int W, int H, const char *name){
|
||||
}
|
||||
}
|
||||
|
||||
// function for Qsort
|
||||
static int compObjs(const void *a, const void *b){
|
||||
// functions for Qsort
|
||||
static int compIntens(const void *a, const void *b){ // compare by intensity
|
||||
const object *oa = (const object*)a;
|
||||
const object *ob = (const object*)b;
|
||||
double idiff = (oa->Isum - ob->Isum)/(oa->Isum + ob->Isum);
|
||||
if(fabs(idiff) > GP->intensthres) return (idiff > 0) ? -1:1;
|
||||
if(fabs(idiff) > theconf.intensthres) return (idiff > 0) ? -1:1;
|
||||
double r2a = oa->xc * oa->xc + oa->yc * oa->yc;
|
||||
double r2b = ob->xc * ob->xc + ob->yc * ob->yc;
|
||||
return (r2a < r2b) ? -1 : 1;
|
||||
}
|
||||
static int compDist(const void *a, const void *b){ // compare by distanse from target
|
||||
const object *oa = (const object*)a;
|
||||
const object *ob = (const object*)b;
|
||||
double xa = oa->xc - theconf.xtarget, xb = ob->xc - theconf.xtarget,
|
||||
ya = oa->yc - theconf.ytarget, yb = ob->yc - theconf.ytarget;
|
||||
double r2a = xa*xa + ya*ya;
|
||||
double r2b = xb*xb + yb*yb;
|
||||
return (r2a < r2b) ? -1 : 1;
|
||||
}
|
||||
|
||||
static void XYnewline(){
|
||||
if(!fXYlog) return;
|
||||
fprintf(fXYlog, "\n");
|
||||
fflush(fXYlog);
|
||||
}
|
||||
|
||||
static void getDeviation(object *curobj){
|
||||
if(Xtarget < 0. || Ytarget < 0.){ // init from user parameters
|
||||
Xtarget = GP->xtarget; Ytarget = GP->ytarget;
|
||||
}
|
||||
static double Xc[AVERAGING_ARRAY_SIZE], Yc[AVERAGING_ARRAY_SIZE];
|
||||
int averflag = 0;
|
||||
static double Xc[MAX_AVERAGING_ARRAY_SIZE], Yc[MAX_AVERAGING_ARRAY_SIZE];
|
||||
double xx = curobj->xc, yy = curobj->yc, xsum2 = 0., ysum2 = 0.;
|
||||
double Sx = 0., Sy = 0.;
|
||||
static int counter = 0;
|
||||
Xc[counter] = curobj->xc; Yc[counter] = curobj->yc;
|
||||
if(fXYlog){ // make log record
|
||||
@@ -100,31 +122,32 @@ static void getDeviation(object *curobj){
|
||||
dtime() - tstart, curobj->xc, curobj->yc,
|
||||
curobj->xsigma, curobj->ysigma, curobj->WdivH);
|
||||
}
|
||||
if(++counter != AVERAGING_ARRAY_SIZE){
|
||||
if(fXYlog) fprintf(fXYlog, "\n");
|
||||
return;
|
||||
DBG("counter = %d", counter);
|
||||
if(++counter != theconf.naverage){
|
||||
goto process_corrections;
|
||||
}
|
||||
// it's time to calculate average deviations
|
||||
counter = 0;
|
||||
double xdev = 0., ydev = 0., xsum2 = 0., ysum2 = 0.;
|
||||
for(int i = 0; i < AVERAGING_ARRAY_SIZE; ++i){
|
||||
double dx = Xc[i] - Xtarget, dy = Yc[i] - Ytarget;
|
||||
xdev += dx; ydev += dy;
|
||||
xsum2 += dx*dx; ysum2 += dy*dy;
|
||||
counter = 0; xx = 0.; yy = 0.;
|
||||
for(int i = 0; i < theconf.naverage; ++i){
|
||||
double x = Xc[i], y = Yc[i];
|
||||
xx += x; yy += y;
|
||||
xsum2 += x*x; ysum2 += y*y;
|
||||
}
|
||||
xdev /= AVERAGING_ARRAY_SIZE; ydev /= AVERAGING_ARRAY_SIZE;
|
||||
double Sx = sqrt(xsum2/AVERAGING_ARRAY_SIZE - xdev*xdev);
|
||||
double Sy = sqrt(ysum2/AVERAGING_ARRAY_SIZE - ydev*ydev);
|
||||
DBG("xtag=%g, ytag=%g", Xtarget, Ytarget);
|
||||
green("\n\n\n Deviations: dX=%g (+-%g), dY=%g (+-%g)\n", xdev, Sx, ydev, Sy);
|
||||
if(Xtarget < 0. || Ytarget < 0. || fabs(xdev) < XY_TOLERANCE || fabs(ydev) < XY_TOLERANCE){
|
||||
DBG("Target coordinates not defined or correction too small");
|
||||
if(fXYlog) fprintf(fXYlog, "\n");
|
||||
return;
|
||||
}
|
||||
if(fXYlog){
|
||||
fprintf(fXYlog, "%.1f\t%.1f\t%.1f\t%.1f\n", xdev, ydev, Sx, Sy);
|
||||
xx /= theconf.naverage; yy /= theconf.naverage;
|
||||
Sx = sqrt(xsum2/theconf.naverage - xx*xx);
|
||||
Sy = sqrt(ysum2/theconf.naverage - yy*yy);
|
||||
green("\n\n\n Average centroid: X=%g (+-%g), Y=%g (+-%g)\n", xx, Sx, yy, Sy);
|
||||
LOGDBG("getDeviation(): Average centroid: X=%g (+-%g), Y=%g (+-%g)", xx, Sx, yy, Sy);
|
||||
averflag = 1;
|
||||
if(fXYlog) fprintf(fXYlog, "%.1f\t%.1f\t%.1f\t%.1f", xx, yy, Sx, Sy);
|
||||
process_corrections:
|
||||
if(proc_corr){
|
||||
if(Sx > 1. || Sy > 1.){
|
||||
LOGDBG("Bad value - not process"); // don't run processing for bad data
|
||||
}else
|
||||
proc_corr(xx, yy, averflag);
|
||||
}
|
||||
XYnewline();
|
||||
}
|
||||
|
||||
void process_file(Image *I){
|
||||
@@ -135,7 +158,6 @@ void process_file(Image *I){
|
||||
#define DELTA(x)
|
||||
#endif
|
||||
// I - original image
|
||||
// M - median filtering
|
||||
// mean - local mean
|
||||
// std - local STD
|
||||
/**** read original image ****/
|
||||
@@ -148,15 +170,6 @@ void process_file(Image *I){
|
||||
if(!I->dtype) I->dtype = FLOAT_IMG;
|
||||
save_fits(I, "fitsout.fits");
|
||||
DELTA("Save original");
|
||||
/*
|
||||
uint8_t *outp = NULL;
|
||||
if(GP->equalize)
|
||||
outp = equalize(I, 1, GP->throwpart);
|
||||
else
|
||||
outp = linear(I, 1);
|
||||
stbi_write_jpg("jpegout.jpg", I->width, I->height, 3, outp, 95);
|
||||
FREE(outp);
|
||||
*/
|
||||
Imtype bk;
|
||||
if(calc_background(I, &bk)){
|
||||
DBG("backgr = %g", bk);
|
||||
@@ -166,12 +179,12 @@ void process_file(Image *I){
|
||||
if(ibin){
|
||||
savebin(ibin, W, H, "binary.fits");
|
||||
DELTA("save binary.fits");
|
||||
uint8_t *er = erosionN(ibin, W, H, GP->nerosions);
|
||||
uint8_t *er = erosionN(ibin, W, H, theconf.Nerosions);
|
||||
FREE(ibin);
|
||||
DELTA("Erosion");
|
||||
savebin(er, W, H, "erosion.fits");
|
||||
DELTA("Save erosion");
|
||||
uint8_t *opn = dilationN(er, W, H, GP->ndilations);
|
||||
uint8_t *opn = dilationN(er, W, H, theconf.Ndilations);
|
||||
FREE(er);
|
||||
DELTA("Opening");
|
||||
savebin(opn, W, H, "opening.fits");
|
||||
@@ -187,8 +200,8 @@ void process_file(Image *I){
|
||||
double wh = ((double)b->xmax - b->xmin)/(b->ymax - b->ymin);
|
||||
//DBG("Obj# %zd: wh=%g, area=%d", i, wh, b->area);
|
||||
// TODO: change magick numbers to parameters
|
||||
if(wh < 0.2 || wh > 5.) continue;
|
||||
if((int)b->area < GP->minarea) continue;
|
||||
if(wh < MINWH || wh > MAXWH) continue;
|
||||
if((int)b->area < theconf.minarea || (int)b->area > theconf.maxarea) continue;
|
||||
double xc = 0., yc = 0.;
|
||||
double x2c = 0., y2c = 0., Isum = 0.;
|
||||
for(size_t y = b->ymin; y <= b->ymax; ++y){
|
||||
@@ -218,7 +231,12 @@ void process_file(Image *I){
|
||||
}
|
||||
DELTA("Labeling");
|
||||
printf("T%zd, N=%d\n", time(NULL), objctr);
|
||||
qsort(Objects, objctr, sizeof(object), compObjs);
|
||||
if(objctr > 1){
|
||||
if(theconf.starssort)
|
||||
qsort(Objects, objctr, sizeof(object), compIntens);
|
||||
else
|
||||
qsort(Objects, objctr, sizeof(object), compDist);
|
||||
}
|
||||
object *o = Objects;
|
||||
green("%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\n",
|
||||
"N", "Area", "Mv", "W/H", "Xc", "Yc", "Sx", "Sy");
|
||||
@@ -228,20 +246,23 @@ void process_file(Image *I){
|
||||
i, o->area, 20.-1.0857*log(o->Isum), o->WdivH, o->xc, o->yc, o->xsigma, o->ysigma);
|
||||
}
|
||||
getDeviation(Objects);
|
||||
if(objctr){ // draw crosses @ objects' centers
|
||||
{ // prepare image
|
||||
uint8_t *outp = NULL;
|
||||
if(GP->equalize)
|
||||
outp = equalize(I, 3, GP->throwpart);
|
||||
if(theconf.equalize)
|
||||
outp = equalize(I, 3, theconf.throwpart);
|
||||
else
|
||||
outp = linear(I, 3);
|
||||
Pattern *cross = Pattern_cross(33, 33);
|
||||
int H = I->height;
|
||||
Img3 i3 = {.data = outp, .w = I->width, .h = H};
|
||||
Pattern_draw3(&i3, cross, Objects[0].xc, H-Objects[0].yc, C_G);
|
||||
for(int i = 1; i < objctr; ++i)
|
||||
Pattern_draw3(&i3, cross, Objects[i].xc, H-Objects[i].yc, C_R);
|
||||
Pattern_free(&cross);
|
||||
stbi_write_jpg("outpWcrosses.jpg", I->width, I->height, 3, outp, 95);
|
||||
if(objctr){ // draw crosses @ objects' centers
|
||||
static Pattern *cross = NULL;
|
||||
if(!cross) cross = Pattern_cross(33, 33);
|
||||
int H = I->height;
|
||||
Img3 i3 = {.data = outp, .w = I->width, .h = H};
|
||||
Pattern_draw3(&i3, cross, Objects[0].xc, H-Objects[0].yc, C_G);
|
||||
for(int i = 1; i < objctr; ++i)
|
||||
Pattern_draw3(&i3, cross, Objects[i].xc, H-Objects[i].yc, C_R);
|
||||
// Pattern_free(&cross); don't free - static variable!
|
||||
}
|
||||
stbi_write_jpg(GP->outputjpg, I->width, I->height, 3, outp, 95);
|
||||
FREE(outp);
|
||||
}
|
||||
FREE(cc);
|
||||
@@ -273,6 +294,7 @@ void process_file(Image *I){
|
||||
}
|
||||
|
||||
int process_input(InputType tp, char *name){
|
||||
DBG("process_input(%d, %s)", tp, name);
|
||||
if(tp == T_DIRECTORY) return watch_directory(name, process_file);
|
||||
else if(tp == T_CAPT_GRASSHOPPER) return capture_grasshopper(process_file);
|
||||
return watch_file(name, process_file);
|
||||
@@ -293,7 +315,8 @@ void openXYlog(const char *name){
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
fprintf(fXYlog, "# Start at: %s", ctime(&t));
|
||||
fprintf(fXYlog, "# time,s\tXc\tYc\t\tSx\tSy\tW/H\tcorrX\tcorrY\tSXcorr\tSYcorr\n");
|
||||
fprintf(fXYlog, "# time Xc\tYc\t\tSx\tSy\tW/H\taverX\taverY\tSX\tSY\n");
|
||||
fflush(fXYlog);
|
||||
tstart = dtime();
|
||||
}
|
||||
void closeXYlog(){
|
||||
@@ -301,3 +324,27 @@ void closeXYlog(){
|
||||
fclose(fXYlog);
|
||||
fXYlog = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setpostprocess - set postprocessing name (what to do with deviations data)
|
||||
* @param name - "pusirobo" for pusirobot drives
|
||||
*/
|
||||
void setpostprocess(const char *name){
|
||||
if(!name) return;
|
||||
if(strncasecmp(name, PUSIROBO_POSTPROC, sizeof(PUSIROBO_POSTPROC) - 1) == 0){
|
||||
postprocess = PROCESS_PUSIROBO;
|
||||
DBG("Postprocess: pusirobot drives");
|
||||
LOGMSG("Postprocess: pusirobot drives");
|
||||
if(!pusi_connect()){
|
||||
WARNX("Pusiserver unavailable, will check later");
|
||||
LOGWARN("Pusiserver unavailable, will check later");
|
||||
}
|
||||
proc_corr = pusi_process_corrections;
|
||||
stepstatus = pusi_status;
|
||||
setstepstatus = set_pusistatus;
|
||||
movefocus = set_pfocus;
|
||||
}else{
|
||||
WARNX("Unknown postprocess \"%s\"", name);
|
||||
LOGERR("Unknown postprocess \"%s\"", name);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user