forgotten fixes

This commit is contained in:
Edward Emelianov 2025-06-12 14:31:51 +03:00
parent 3f7b5081ea
commit b9084907a3
14 changed files with 180 additions and 155 deletions

View File

@ -21,7 +21,7 @@ option(GRASSHOPPER "Add GrassHopper cameras support" OFF)
option(HIKROBOT "Add HikRobot cameras support" OFF) option(HIKROBOT "Add HikRobot cameras support" OFF)
# default flags # default flags
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -Wextra") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -Wextra -std=c17")
set(CMAKE_COLOR_MAKEFILE ON) set(CMAKE_COLOR_MAKEFILE ON)
# cmake -DDEBUG=yes -> debugging # cmake -DDEBUG=yes -> debugging
@ -94,7 +94,7 @@ target_include_directories(${PROJ} PUBLIC ${MODULES_INCLUDE_DIRS} ${FLYCAP_INCLU
target_link_directories(${PROJ} PUBLIC ${MODULES_LIBRARY_DIRS} ${FLYCAP_LIBRARY_DIRS} ${BASLER_LIBRARY_DIRS} ${MVS_LIBRARY_DIRS}) target_link_directories(${PROJ} PUBLIC ${MODULES_LIBRARY_DIRS} ${FLYCAP_LIBRARY_DIRS} ${BASLER_LIBRARY_DIRS} ${MVS_LIBRARY_DIRS})
message("MOD: ${MODULES_LIBRARY_DIRS}, FC: ${FLYCAP_LIBRARY_DIRS}, MVS: ${MVS_LIBRARY_DIRS}") message("MOD: ${MODULES_LIBRARY_DIRS}, FC: ${FLYCAP_LIBRARY_DIRS}, MVS: ${MVS_LIBRARY_DIRS}")
# -D # -D
add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\" add_definitions(${CFLAGS} -D_XOPEN_SOURCE=666 -D_POSIX_C_SOURCE=600700 -D_DEFAULT_SOURCE -DLOCALEDIR=\"${LOCALEDIR}\"
-DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\" -DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\"
-DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\" -DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\"
-DMAJOR_VERSION=\"${MAJOR_VERSION}\" -DTHREAD_NUMBER=${PROCESSOR_COUNT}) -DMAJOR_VERSION=\"${MAJOR_VERSION}\" -DTHREAD_NUMBER=${PROCESSOR_COUNT})

View File

@ -1,3 +1,3 @@
Mon Apr 28 13:05:48 MSK 2025 Mon Apr 28 13:05:48 MSK 2025
Move to libusefull_macros v0.3.2. Move to libusefull_macros v0.3.2.
Fixed some troubles with `inotifying` log files. Fixed some troubles with `inotifying` log files.

View File

@ -436,30 +436,30 @@ size_t *il_cclabel4(uint8_t *Img, int W, int H, il_ConnComps **CC){
l_boxes[i].ymin = H; l_boxes[i].ymin = H;
} }
#pragma omp for nowait #pragma omp for nowait
for(int y = 0; y < H; ++y){ for(int y = 0; y < H; ++y){
size_t *lptr = &labels[y*W]; size_t *lptr = &labels[y*W];
for(int x = 0; x < W; ++x, ++lptr){ for(int x = 0; x < W; ++x, ++lptr){
if(!*lptr) continue; if(!*lptr) continue;
register size_t mark = indexes[*lptr]; register size_t mark = indexes[*lptr];
*lptr = mark; *lptr = mark;
il_Box *b = &l_boxes[mark]; il_Box *b = &l_boxes[mark];
++b->area; ++b->area;
if(b->xmax < x) b->xmax = x; if(b->xmax < x) b->xmax = x;
if(b->xmin > x) b->xmin = x; if(b->xmin > x) b->xmin = x;
if(b->ymax < y) b->ymax = y; if(b->ymax < y) b->ymax = y;
if(b->ymin > y) b->ymin = y; if(b->ymin > y) b->ymin = y;
} }
} }
#pragma omp critical #pragma omp critical
for(size_t i = 1; i < cidx; ++i){ for(size_t i = 1; i < cidx; ++i){
il_Box *ob = &boxes[i], *ib = &l_boxes[i]; il_Box *ob = &boxes[i], *ib = &l_boxes[i];
if(ob->xmax < ib->xmax) ob->xmax = ib->xmax; if(ob->xmax < ib->xmax) ob->xmax = ib->xmax;
if(ob->xmin > ib->xmin) ob->xmin = ib->xmin; if(ob->xmin > ib->xmin) ob->xmin = ib->xmin;
if(ob->ymax < ib->ymax) ob->ymax = ib->ymax; if(ob->ymax < ib->ymax) ob->ymax = ib->ymax;
if(ob->ymin > ib->ymin) ob->ymin = ib->ymin; if(ob->ymin > ib->ymin) ob->ymin = ib->ymin;
ob->area += ib->area; ob->area += ib->area;
} }
FREE(l_boxes); FREE(l_boxes);
} }
FREE(assoc); FREE(assoc);
FREE(indexes); FREE(indexes);

View File

@ -35,7 +35,7 @@
static camera *theCam = NULL; static camera *theCam = NULL;
static float gain = 0., gainmax = 0.; static float gain = 0., gainmax = 0.;
static float exptime = 100.; static float exptime = -1.;
static float brightness = 0.; static float brightness = 0.;
static int connected = FALSE; static int connected = FALSE;
@ -241,10 +241,10 @@ static void *procthread(void* v){
double t0 = sl_dtime(); double t0 = sl_dtime();
#endif #endif
while(!stopwork){ while(!stopwork){
DBG("===== iCaptured=%d", iCaptured);
pthread_mutex_lock(&capt_mutex); pthread_mutex_lock(&capt_mutex);
//DBG("===== iCaptured=%d", iCaptured);
if(Icap[iCaptured]){ if(Icap[iCaptured]){
DBG("===== got image #%d @ %g", iCaptured, sl_dtime() - t0); DBG("===== got image iCaptured=#%d @ %g", iCaptured, sl_dtime() - t0);
Image *oIma = Icap[iCaptured]; // take image here and free buffer Image *oIma = Icap[iCaptured]; // take image here and free buffer
Icap[iCaptured] = NULL; Icap[iCaptured] = NULL;
pthread_mutex_unlock(&capt_mutex); pthread_mutex_unlock(&capt_mutex);
@ -252,14 +252,11 @@ static void *procthread(void* v){
if(theconf.medfilt){ if(theconf.medfilt){
Image *X = get_median(oIma, theconf.medseed); Image *X = get_median(oIma, theconf.medseed);
if(X){ if(X){
FREE(oIma->data); Image_free(&oIma);
FREE(oIma);
oIma = X; oIma = X;
} }
} }
DBG("===== process");
process(oIma); process(oIma);
DBG("===== done");
lastimdata.avg = oIma->avg_intensity; lastimdata.avg = oIma->avg_intensity;
lastimdata.bkg = oIma->background; lastimdata.bkg = oIma->background;
lastimdata.minval = oIma->minval; lastimdata.minval = oIma->minval;
@ -268,12 +265,10 @@ static void *procthread(void* v){
getcenter(&lastimdata.xc, &lastimdata.yc); getcenter(&lastimdata.xc, &lastimdata.yc);
} }
if(theconf.expmethod == EXPAUTO){ if(theconf.expmethod == EXPAUTO){
DBG("test");
if(needs_exposure_adjustment(oIma, lastimdata.xc, lastimdata.yc)) recalcexp(oIma); if(needs_exposure_adjustment(oIma, lastimdata.xc, lastimdata.yc)) recalcexp(oIma);
DBG("done");
}else{ }else{
if(fabs(theconf.fixedexp - exptime) > FLT_EPSILON) if(fabs(theconf.exptime - exptime) > FLT_EPSILON)
exptime = theconf.fixedexp; exptime = theconf.exptime;
if(fabs(theconf.gain - gain) > FLT_EPSILON) if(fabs(theconf.gain - gain) > FLT_EPSILON)
gain = theconf.gain; gain = theconf.gain;
if(fabs(theconf.brightness - brightness) > FLT_EPSILON) if(fabs(theconf.brightness - brightness) > FLT_EPSILON)
@ -281,14 +276,13 @@ static void *procthread(void* v){
} }
//Icap[iCaptured] = NULL; //Icap[iCaptured] = NULL;
//pthread_mutex_unlock(&capt_mutex); //pthread_mutex_unlock(&capt_mutex);
FREE(oIma->data); Image_free(&oIma);
FREE(oIma); DBG("===== cleared image data @ %g", sl_dtime() - t0);
DBG("---- cleared image data @ %g", sl_dtime() - t0);
}else{ }else{
DBG("NO image data"); //DBG("===== NO image data");
pthread_mutex_unlock(&capt_mutex); pthread_mutex_unlock(&capt_mutex);
} }
DBG("NEXT!"); //DBG("===== NEXT!");
usleep(1000); usleep(1000);
} }
return NULL; return NULL;
@ -305,6 +299,7 @@ int camcapture(void (*process)(Image*)){
LOGERR("pthread_create() for image processing failed"); LOGERR("pthread_create() for image processing failed");
ERR("pthread_create()"); ERR("pthread_create()");
} }
exptime = theconf.exptime;
while(1){ while(1){
double t0 = sl_dtime(); double t0 = sl_dtime();
if(stopwork){ if(stopwork){
@ -339,6 +334,7 @@ int camcapture(void (*process)(Image*)){
DBG("Change exptime to %.2fms\n", exptime); DBG("Change exptime to %.2fms\n", exptime);
if(theCam->setexp(exptime)){ if(theCam->setexp(exptime)){
oldexptime = exptime; oldexptime = exptime;
theconf.exptime = exptime;
}else{ }else{
WARNX("Can't change exposition time to %gms", exptime); WARNX("Can't change exposition time to %gms", exptime);
} }
@ -350,6 +346,7 @@ int camcapture(void (*process)(Image*)){
LOGDBG("Change gain to %g", gain); LOGDBG("Change gain to %g", gain);
if(theCam->setgain(gain)){ if(theCam->setgain(gain)){
oldgain = gain; oldgain = gain;
theconf.gain = gain;
}else{ }else{
WARNX("Can't change gain to %g", gain); WARNX("Can't change gain to %g", gain);
LOGWARN("Can't change gain to %g", gain); LOGWARN("Can't change gain to %g", gain);
@ -364,7 +361,7 @@ int camcapture(void (*process)(Image*)){
DBG("Try to grab (T=%g)", sl_dtime() - t0); DBG("Try to grab (T=%g)", sl_dtime() - t0);
static int errctr = 0; static int errctr = 0;
if(!(oIma = theCam->capture())){ if(!(oIma = theCam->capture())){
WARNX("Can't grab image"); WARNX("---- Can't grab image");
if(++errctr > MAX_CAPT_ERRORS){ if(++errctr > MAX_CAPT_ERRORS){
LOGERR("camcapture(): too much capture errors; reconnect camera"); LOGERR("camcapture(): too much capture errors; reconnect camera");
camdisconnect(); camdisconnect();
@ -372,12 +369,12 @@ int camcapture(void (*process)(Image*)){
} }
continue; continue;
}else errctr = 0; }else errctr = 0;
DBG("Grabbed @ %g", sl_dtime() - t0); DBG("---- Grabbed @ %g", sl_dtime() - t0);
pthread_mutex_lock(&capt_mutex); pthread_mutex_lock(&capt_mutex);
if(iCaptured < 0) iCaptured = 0; if(iCaptured < 0) iCaptured = 0;
else iCaptured = !iCaptured; else iCaptured = !iCaptured;
if(Icap[iCaptured]){ // try current value if previous is still busy if(Icap[iCaptured]){ // try current value if previous is still busy
DBG("iCap=%d busy!", iCaptured); DBG("---- iCap=%d busy!", iCaptured);
iCaptured = !iCaptured; iCaptured = !iCaptured;
} }
if(!Icap[iCaptured]){ // previous buffer is free if(!Icap[iCaptured]){ // previous buffer is free
@ -386,22 +383,15 @@ int camcapture(void (*process)(Image*)){
oIma = NULL; oIma = NULL;
}else{ // clear our image - there's no empty buffers }else{ // clear our image - there's no empty buffers
DBG("---- no free buffers for iCap=%d", iCaptured); DBG("---- no free buffers for iCap=%d", iCaptured);
FREE(oIma->data); Image_free(&oIma);
FREE(oIma);
} }
pthread_mutex_unlock(&capt_mutex); pthread_mutex_unlock(&capt_mutex);
DBG("unlocked, T=%g", sl_dtime() - t0); DBG("unlocked, T=%g", sl_dtime() - t0);
} }
pthread_cancel(proc_thread); pthread_cancel(proc_thread);
if(oIma){ if(oIma) Image_free(&oIma);
FREE(oIma->data);
FREE(oIma);
}
for(int i = 0; i < 2; ++i){ for(int i = 0; i < 2; ++i){
if(Icap[i]){ if(Icap[i]) Image_free(&Icap[i]);
FREE(Icap[i]->data);
FREE(Icap[i]);
}
} }
camdisconnect(); camdisconnect();
DBG("CAMCAPTURE: out"); DBG("CAMCAPTURE: out");
@ -430,7 +420,7 @@ char *camstatus(const char *messageid, char *buf, int buflen){
float xc, yc; float xc, yc;
getcenter(&xc, &yc); getcenter(&xc, &yc);
snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"%sconnected\", \"impath\": \"%s\", \"imctr\": %llu, " snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"%sconnected\", \"impath\": \"%s\", \"imctr\": %llu, "
"\"fps\": %.3f, \"expmethod\": \"%s\", \"exposition\": %g, \"gain\": %g, \"maxgain\": %g, \"brightness\": %g, " "\"fps\": %.3f, \"expmethod\": \"%s\", \"exptime\": %g, \"gain\": %g, \"maxgain\": %g, \"brightness\": %g, "
"\"xcenter\": %.1f, \"ycenter\": %.1f , \"minval\": %d, \"maxval\": %d, \"background\": %d, " "\"xcenter\": %.1f, \"ycenter\": %.1f , \"minval\": %d, \"maxval\": %d, \"background\": %d, "
"\"average\": %.1f, \"xc\": %.1f, \"yc\": %.1f, \"xsigma\": %.1f, \"ysigma\": %.1f, \"area\": %d }\n", "\"average\": %.1f, \"xc\": %.1f, \"yc\": %.1f, \"xsigma\": %.1f, \"ysigma\": %.1f, \"area\": %d }\n",
MESSAGEID, messageid, connected ? "" : "dis", impath, ImNumber, getFramesPerS(), MESSAGEID, messageid, connected ? "" : "dis", impath, ImNumber, getFramesPerS(),

View File

@ -62,7 +62,7 @@ configuration theconf = {
.throwpart=DEFAULT_THROWPART, .throwpart=DEFAULT_THROWPART,
.maxexp=EXPOS_MAX - 1., .maxexp=EXPOS_MAX - 1.,
.minexp=EXPOS_MIN, .minexp=EXPOS_MIN,
.fixedexp=EXPOS_MIN*2, .exptime=EXPOS_MIN*2,
.gain=20., .gain=20.,
.intensthres=DEFAULT_INTENSTHRES, .intensthres=DEFAULT_INTENSTHRES,
.medseed=MIN_MEDIAN_SEED, .medseed=MIN_MEDIAN_SEED,
@ -74,6 +74,7 @@ static int compConfVals(const void *_1st, const void *_2nd){
return strcmp(a->name, b->name); return strcmp(a->name, b->name);
} }
// could be in unsorted order as whould be sorted at first help call
// {"", PAR_DOUBLE, (void*)&theconf., 0}, // {"", PAR_DOUBLE, (void*)&theconf., 0},
static confparam parvals[] = { static confparam parvals[] = {
{"maxarea", PAR_INT, (void*)&theconf.maxarea, 0, MINAREA, MAXAREA, {"maxarea", PAR_INT, (void*)&theconf.maxarea, 0, MINAREA, MAXAREA,
@ -99,7 +100,7 @@ static confparam parvals[] = {
{"equalize", PAR_INT, (void*)&theconf.equalize, 0, 0., 1., {"equalize", PAR_INT, (void*)&theconf.equalize, 0, 0., 1.,
"make histogram equalization"}, "make histogram equalization"},
{"expmethod", PAR_INT, (void*)&theconf.expmethod, 0, 0., 1., {"expmethod", PAR_INT, (void*)&theconf.expmethod, 0, 0., 1.,
"exposition method: 0 - auto, 1 - fixed"}, "0 - automatic calculation of gain and exptime, 1 - use fixed values"},
{"naverage", PAR_INT, (void*)&theconf.naverage, 0, 1., NAVER_MAX, {"naverage", PAR_INT, (void*)&theconf.naverage, 0, 1., NAVER_MAX,
"calculate mean position by N images"}, "calculate mean position by N images"},
{"umax", PAR_INT, (void*)&theconf.maxUpos, 0, -MAXSTEPS, MAXSTEPS, {"umax", PAR_INT, (void*)&theconf.maxUpos, 0, -MAXSTEPS, MAXSTEPS,
@ -146,8 +147,8 @@ static confparam parvals[] = {
"minimal exposition time"}, "minimal exposition time"},
{"maxexp", PAR_DOUBLE, (void*)&theconf.maxexp, 0, 0., EXPOS_MAX, {"maxexp", PAR_DOUBLE, (void*)&theconf.maxexp, 0, 0., EXPOS_MAX,
"maximal exposition time"}, "maximal exposition time"},
{"fixedexp", PAR_DOUBLE, (void*)&theconf.fixedexp, 0, EXPOS_MIN, EXPOS_MAX, {"exptime", PAR_DOUBLE, (void*)&theconf.exptime, 0, EXPOS_MIN, EXPOS_MAX,
"fixed (in manual mode) exposition time"}, "exposition time (you can change it only when expmethod==1)"},
{"intensthres", PAR_DOUBLE, (void*)&theconf.intensthres, 0, 0., 1., {"intensthres", PAR_DOUBLE, (void*)&theconf.intensthres, 0, 0., 1.,
"threshold by total object intensity when sorting = |I1-I2|/(I1+I2)"}, "threshold by total object intensity when sorting = |I1-I2|/(I1+I2)"},
{"gain", PAR_DOUBLE, (void*)&theconf.gain, 0, GAIN_MIN, GAIN_MAX, {"gain", PAR_DOUBLE, (void*)&theconf.gain, 0, GAIN_MIN, GAIN_MAX,
@ -162,8 +163,10 @@ static confparam parvals[] = {
"median filter radius"}, "median filter radius"},
{"fixedbg", PAR_INT, (void*)&theconf.fixedbkg, 0, 0., 1., {"fixedbg", PAR_INT, (void*)&theconf.fixedbkg, 0, 0., 1.,
"don't calculate background, use fixed value instead"}, "don't calculate background, use fixed value instead"},
{"fbglevel", PAR_INT, (void*)&theconf.fixedbkgval, 0, FIXED_BK_MIN, FIXED_BK_MAX, {"background", PAR_INT, (void*)&theconf.background, 0, FIXED_BK_MIN, FIXED_BK_MAX,
"fixed background level"}, "fixed background level"},
{"writedi", PAR_INT, (void*)&theconf.writedebugimgs, 0, 0., 1.,
"write debug images (binary/erosion/opening)"},
{NULL, 0, NULL, 0, 0., 0., NULL} {NULL, 0, NULL, 0, 0., 0., NULL}
}; };

View File

@ -34,7 +34,7 @@
#define MAX_THROWPART (0.9) #define MAX_THROWPART (0.9)
#define MAX_OFFSET (10000) #define MAX_OFFSET (10000)
// min/max exposition in ms // min/max exposition in ms
#define EXPOS_MIN (0.01) #define EXPOS_MIN (1e-9)
#define EXPOS_MAX (4001.) #define EXPOS_MAX (4001.)
#define GAIN_MIN (0.) #define GAIN_MIN (0.)
#define GAIN_MAX (256.) #define GAIN_MAX (256.)
@ -99,7 +99,8 @@ typedef struct{
int medfilt; // == 1 to make median filter before calculations int medfilt; // == 1 to make median filter before calculations
int medseed; // median seed int medseed; // median seed
int fixedbkg; // don't calculate background, use fixed value instead int fixedbkg; // don't calculate background, use fixed value instead
int fixedbkgval; // value of bk int background; // value of background
int writedebugimgs; // write debugging images: binary/erosion/opening
// dU = Kxu*dX + Kyu*dY; dV = Kxv*dX + Kyv*dY // dU = Kxu*dX + Kyu*dY; dV = Kxv*dX + Kyv*dY
double Kxu; double Kyu; double Kxu; double Kyu;
double Kxv; double Kyv; double Kxv; double Kyv;
@ -109,7 +110,7 @@ typedef struct{
double throwpart; // part of values to throw avay @ histogram equalisation double throwpart; // part of values to throw avay @ histogram equalisation
double maxexp; // minimal and maximal exposition (in ms) double maxexp; // minimal and maximal exposition (in ms)
double minexp; double minexp;
double fixedexp; // exptime in manual mode double exptime; // exposure time
double gain; // gain value in manual mode double gain; // gain value in manual mode
double brightness; // brightness @camera double brightness; // brightness @camera
double intensthres; // threshold for stars intensity comparison: fabs(Ia-Ib)/(Ia+Ib) > thres -> stars differs double intensthres; // threshold for stars intensity comparison: fabs(Ia-Ib)/(Ia+Ib) > thres -> stars differs

View File

@ -47,11 +47,6 @@ do{ fitsstatus = 0; \
if(status) fits_report_error(stderr, status);\ if(status) fits_report_error(stderr, status);\
}while(0) }while(0)
void Image_free(Image **img){
FREE((*img)->data);
FREE(*img);
}
// I->data should be allocated!!! // I->data should be allocated!!!
static inline void convflt2ima(float *f, Image *I){ static inline void convflt2ima(float *f, Image *I){
if(!I || !I->data || !f) return; if(!I || !I->data || !f) return;

View File

@ -26,7 +26,6 @@
#include "imagefile.h" #include "imagefile.h"
void Image_free(Image **ima);
bool FITS_read(const char *filename, Image **fits); bool FITS_read(const char *filename, Image **fits);
#endif // FITS_H__ #endif // FITS_H__

View File

@ -279,7 +279,7 @@ static int cam_connect(){
WARNX("Can't turn off triggered mode"); WARNX("Can't turn off triggered mode");
return FALSE; return FALSE;
} }
if(!changeenum("AcquisitionMode", MV_ACQ_MODE_SINGLE)){ if(!changeenum("AcquisitionMode", /*MV_ACQ_MODE_SINGLE*/ MV_ACQ_MODE_CONTINUOUS)){
WARNX("Can't set acquisition mode to single"); WARNX("Can't set acquisition mode to single");
return FALSE; return FALSE;
} }
@ -356,50 +356,69 @@ static int changeformat(frameformat *f){
return TRUE; return TRUE;
} }
// exptime - in milliseconds!
static int setexp(float e){ static int setexp(float e){
if(!handle) return FALSE; if(!handle){
float eS = e / 1e3; WARNX("NO HANDLE");
if(eS > extrvalues.maxexp || eS < extrvalues.minexp){ return FALSE;
WARNX("Wrong exposure time: %fs (should be [%fs..%fs])", eS, }
if(e > extrvalues.maxexp || e < extrvalues.minexp){
WARNX("Wrong exposure time: %fs (should be [%fs..%fs])", e,
extrvalues.minexp, extrvalues.maxexp); extrvalues.minexp, extrvalues.maxexp);
return FALSE; return FALSE;
} }
if(!changefloat("ExposureTime", e * 1e3)) return FALSE; if(!changefloat("ExposureTime", e * 1e6)){
exptime = eS; WARNX("Can't set exptime %g", e);
return FALSE;
}
exptime = e;
return TRUE; return TRUE;
} }
static int cam_startexp(){ static int cam_startexp(){
if(!handle || !pdata) return FALSE; if(!handle || !pdata) return FALSE;
DBG("Start exposition for %gs", exptime); DBG("+++++ Start exposition for %gs", exptime);
MV_CC_StopGrabbing(handle); MV_CC_StopGrabbing(handle);
TRY(StartGrabbing); TRY(StartGrabbing);
ONERR() return FALSE; ONERR(){
DBG("+++++ Ooops! Can't start grabbing: try another time!");
MV_CC_StopGrabbing(handle);
TRY(StartGrabbing);
ONERR(){
DBG("+++++ ERR!");
return FALSE;
}
}
DBG("+++++ OK, started");
return TRUE; return TRUE;
} }
static Image* capture(){ static Image* capture(){
double starttime = sl_dtime(); double starttime = sl_dtime();
if(!cam_startexp()) return NULL; static int isstarted = 0;
if(!isstarted){
if(!cam_startexp()) return NULL;
isstarted = 1;
}
MV_FRAME_OUT_INFO_EX stImageInfo = {0}; // last image info MV_FRAME_OUT_INFO_EX stImageInfo = {0}; // last image info
DBG("Started capt @ %g", sl_dtime() - starttime); DBG("^^^^^^^^^^^^^^^^^^^^ Started capt @ %g", sl_dtime() - starttime);
do{ do{
usleep(100); usleep(100);
double diff = exptime - (sl_dtime() - starttime); double diff = exptime - (sl_dtime() - starttime);
if(diff > 0.) continue; // wait until exposure ends if(diff > 0.) continue; // wait until exposure ends
DBG("diff = %g", diff); DBG("diff = %g", diff);
if(diff < -MAX_READOUT_TM){ // wait much longer than exp lasts if(diff < -MAX_READOUT_TM){ // wait much longer than exp lasts
DBG("OOps, time limit"); DBG("^^^^^^^^^^^^^^^^^^^^ OOps, time limit");
MV_CC_StopGrabbing(handle); MV_CC_StopGrabbing(handle);
DBG("Restart grabbing");
if(!cam_startexp()) isstarted = 0;
return NULL; return NULL;
} }
TRY(GetOneFrameTimeout, pdata, pdatasz, &stImageInfo, 10); TRY(GetOneFrameTimeout, pdata, pdatasz, &stImageInfo, 100);
ONOK() break; ONOK() break;
}while(1); }while(1);
DBG("Tcapt=%g, exptime=%g", sl_dtime() - starttime, exptime); DBG("^^^^^^^^^^^^^^^^^^^^ Tcapt=%g, exptime=%g", sl_dtime() - starttime, exptime);
Image *captIma = u8toImage(pdata, stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nWidth); Image *captIma = u8toImage(pdata, stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nWidth);
DBG("return @ %g", sl_dtime() - starttime); DBG("^^^^^^^^^^^^^^^^^^^^ return @ %g", sl_dtime() - starttime);
return captIma; return captIma;
} }

View File

@ -24,10 +24,10 @@
#define HIKROBOT_CAPT_NAME "hikrobot" #define HIKROBOT_CAPT_NAME "hikrobot"
// maximal readout time, seconds // maximal readout time, seconds
#define MAX_READOUT_TM (6.) #define MAX_READOUT_TM (0.3)
// tolerance of float values // tolerance of float values
#define HR_FLOAT_TOLERANCE (0.005) #define HR_FLOAT_TOLERANCE (1.1)
extern camera Hikrobot; extern camera Hikrobot;
#endif #endif

View File

@ -204,14 +204,24 @@ Image *Image_read(const char *name){
* @return data allocated here * @return data allocated here
*/ */
Image *Image_new(int w, int h){ Image *Image_new(int w, int h){
static uint64_t cnt = 0;
if(w < 1 || h < 1) return NULL; if(w < 1 || h < 1) return NULL;
DBGLOG("Image_new(%d, #%u)", w*h, cnt);
Image *outp = MALLOC(Image, 1); Image *outp = MALLOC(Image, 1);
outp->width = w; outp->width = w;
outp->height = h; outp->height = h;
outp->counter = cnt++;
outp->data = MALLOC(Imtype, w*h); outp->data = MALLOC(Imtype, w*h);
return outp; return outp;
} }
void Image_free(Image **I){
if(!I || !*I) return;
DBGLOG("Image_free(%d, #%d)", (*I)->height * (*I)->width, (*I)->counter);
FREE((*I)->data);
FREE(*I);
}
/** /**
* @brief Image_sim - allocate memory for new empty Image with similar size & data type * @brief Image_sim - allocate memory for new empty Image with similar size & data type
* @param i - sample image * @param i - sample image
@ -267,7 +277,7 @@ int calc_background(Image *img){
WARNX("Image values too small"); WARNX("Image values too small");
return FALSE; return FALSE;
} }
img->background = theconf.fixedbkgval; img->background = theconf.background;
return TRUE; return TRUE;
} }
size_t histogram[HISTOSZ]; size_t histogram[HISTOSZ];

View File

@ -46,6 +46,7 @@ typedef struct{
float avg_intensity; float avg_intensity;
Imtype background; // background value Imtype background; // background value
ptstat_t stat; // image statistics ptstat_t stat; // image statistics
uint64_t counter; // image counter
} Image; } Image;
// input file/directory type // input file/directory type

View File

@ -203,8 +203,6 @@ void process_file(Image *I){
static int prev_x = -1, prev_y = -1; static int prev_x = -1, prev_y = -1;
static object *Objects = NULL; static object *Objects = NULL;
static size_t Nallocated = 0; static size_t Nallocated = 0;
il_ConnComps *cc = NULL;
size_t *S = NULL;
#ifdef EBUG #ifdef EBUG
double t0 = sl_dtime(), tlast = t0; double t0 = sl_dtime(), tlast = t0;
#define DELTA(p) do{double t = sl_dtime(); DBG("---> %s @ %gms (delta: %gms)", p, (t-t0)*1e3, (t-tlast)*1e3); tlast = t;}while(0) #define DELTA(p) do{double t = sl_dtime(); DBG("---> %s @ %gms (delta: %gms)", p, (t-t0)*1e3, (t-tlast)*1e3); tlast = t;}while(0)
@ -225,6 +223,7 @@ void process_file(Image *I){
//DELTA("Save original"); //DELTA("Save original");
if(calc_background(I)){ if(calc_background(I)){
DBG("backgr = %d", I->background); DBG("backgr = %d", I->background);
theconf.background = I->background;
DELTA("Got background"); DELTA("Got background");
int objctr = 0; int objctr = 0;
if(prev_x > 0 && prev_y > 0){ if(prev_x > 0 && prev_y > 0){
@ -273,25 +272,32 @@ void process_file(Image *I){
uint8_t *ibin = Im2bin(I, I->background); uint8_t *ibin = Im2bin(I, I->background);
DELTA("Made binary"); DELTA("Made binary");
if(ibin){ if(ibin){
Image *Itmp = bin2Im(ibin, I->width, I->height); if(theconf.writedebugimgs){
Image *Itmp = bin2Im(ibin, I->width, I->height);
Image_write_jpg(Itmp, "binary.jpg", 1); Image_write_jpg(Itmp, "binary.jpg", 1);
Image_free(&Itmp); Image_free(&Itmp);
DELTA("save binary"); DELTA("save binary");
}
uint8_t *er = il_erosionN(ibin, W, H, theconf.Nerosions); uint8_t *er = il_erosionN(ibin, W, H, theconf.Nerosions);
FREE(ibin); FREE(ibin);
DELTA("Erosion"); DELTA("Erosion");
Itmp = bin2Im(er, I->width, I->height); if(theconf.writedebugimgs){
Image *Itmp = bin2Im(er, I->width, I->height);
Image_write_jpg(Itmp, "erosion.jpg", 1); Image_write_jpg(Itmp, "erosion.jpg", 1);
Image_free(&Itmp); Image_free(&Itmp);
DELTA("Save erosion"); DELTA("Save erosion");
}
uint8_t *opn = il_dilationN(er, W, H, theconf.Ndilations); uint8_t *opn = il_dilationN(er, W, H, theconf.Ndilations);
FREE(er); FREE(er);
DELTA("Opening"); DELTA("Opening");
Itmp = bin2Im(opn, I->width, I->height); if(theconf.writedebugimgs){
Image *Itmp = bin2Im(opn, I->width, I->height);
Image_write_jpg(Itmp, "opening.jpg", 1); Image_write_jpg(Itmp, "opening.jpg", 1);
Image_free(&Itmp); Image_free(&Itmp);
DELTA("Save opening"); DELTA("Save opening");
S = il_cclabel4(opn, W, H, &cc); }
il_ConnComps *cc = NULL;
size_t *S = il_cclabel4(opn, W, H, &cc);
FREE(opn); FREE(opn);
if(S && cc) DBG("Nobj=%zd", cc->Nobj-1); if(S && cc) DBG("Nobj=%zd", cc->Nobj-1);
if(S && cc && cc->Nobj > 1){ // Nobj = amount of objects + 1 if(S && cc && cc->Nobj > 1){ // Nobj = amount of objects + 1
@ -329,68 +335,68 @@ void process_file(Image *I){
else else
qsort(Objects, objctr, sizeof(object), compDist); qsort(Objects, objctr, sizeof(object), compDist);
} }
SKIP_FULL_PROCESS:
DBGLOG("T%.2f, N=%d\n", sl_dtime(), objctr);
DELTA("Calculate deviations");
if(objctr){
#ifdef EBUG
object *o = Objects;
green("%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%8s\n",
"N", "Area", "Mv", "W/H", "Xc", "Yc", "Sx", "Sy", "Area/r^2");
for(int i = 0; i < objctr; ++i, ++o){
// 1.0857 = 2.5/ln(10)
printf("%6d\t%6d\t%6.1f\t%6.1f\t%6.1f\t%6.1f\t%6.1f\t%6.1f\t%8.1f\n",
i, o->area, 20.-1.0857*log(o->Isum), o->WdivH, o->xc, o->yc,
o->xsigma, o->ysigma, o->area/o->xsigma/o->ysigma);
}
#endif
getDeviation(Objects); // calculate dX/dY and process corrections
}
DELTA("prepare image");
{ // prepare image and save jpeg
uint8_t *outp = NULL;
if(theconf.equalize)
outp = equalize(I, 3, theconf.throwpart);
else
outp = linear(I, 3);
static il_Pattern *cross = NULL, *crossL = NULL;
if(!cross) cross = il_Pattern_xcross(33, 33);
if(!crossL) crossL = il_Pattern_xcross(51, 51);
il_Img3 i3 = {.data = outp, .w = I->width, .h = H};
DELTA("Draw crosses");
// draw fiber center position
il_Pattern_draw3(&i3, crossL, theconf.xtarget-theconf.xoff, H-(theconf.ytarget-theconf.yoff), C_R);
if(objctr){ // draw crosses @ objects' centers
int H = I->height;
// draw current star centroid
il_Pattern_draw3(&i3, cross, Objects[0].xc, H-Objects[0].yc, C_G);
// add offset to show in target system
xc = Objects[0].xc + theconf.xoff;
yc = Objects[0].yc + theconf.yoff;
// draw other centroids
for(int i = 1; i < objctr; ++i)
il_Pattern_draw3(&i3, cross, Objects[i].xc, H-Objects[i].yc, C_B);
}else{xc = -1.; yc = -1.;}
char tmpnm[FILENAME_MAX+5];
sprintf(tmpnm, "%s-tmp", GP->outputjpg);
if(stbi_write_jpg(tmpnm, I->width, I->height, 3, outp, 95)){
if(rename(tmpnm, GP->outputjpg)){
WARN("rename()");
LOGWARN("can't save %s", GP->outputjpg);
}
}
DELTA("Written");
FREE(outp);
}
}else{
xc = -1.; yc = -1.;
Image_write_jpg(I, GP->outputjpg, theconf.equalize);
} }
DBGLOG("Image saved");
FREE(S); FREE(S);
FREE(cc); FREE(cc);
} }
}else Image_write_jpg(I, GP->outputjpg, theconf.equalize); SKIP_FULL_PROCESS:
DBGLOG("T%.2f, N=%d\n", sl_dtime(), objctr);
DELTA("Calculate deviations");
if(objctr){
#ifdef EBUG
object *o = Objects;
green("%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%8s\n",
"N", "Area", "Mv", "W/H", "Xc", "Yc", "Sx", "Sy", "Area/r^2");
for(int i = 0; i < objctr; ++i, ++o){
// 1.0857 = 2.5/ln(10)
printf("%6d\t%6d\t%6.1f\t%6.1f\t%6.1f\t%6.1f\t%6.1f\t%6.1f\t%8.1f\n",
i, o->area, 20.-1.0857*log(o->Isum), o->WdivH, o->xc, o->yc,
o->xsigma, o->ysigma, o->area/o->xsigma/o->ysigma);
}
#endif
getDeviation(Objects); // calculate dX/dY and process corrections
}
DELTA("prepare image");
{ // prepare image and save jpeg
uint8_t *outp = NULL;
if(theconf.equalize)
outp = equalize(I, 3, theconf.throwpart);
else
outp = linear(I, 3);
static il_Pattern *cross = NULL, *crossL = NULL;
if(!cross) cross = il_Pattern_xcross(33, 33);
if(!crossL) crossL = il_Pattern_xcross(51, 51);
il_Img3 i3 = {.data = outp, .w = I->width, .h = H};
DELTA("Draw crosses");
// draw fiber center position
il_Pattern_draw3(&i3, crossL, theconf.xtarget-theconf.xoff, H-(theconf.ytarget-theconf.yoff), C_R);
if(objctr){ // draw crosses @ objects' centers
int H = I->height;
// draw current star centroid
il_Pattern_draw3(&i3, cross, Objects[0].xc, H-Objects[0].yc, C_G);
// add offset to show in target system
xc = Objects[0].xc + theconf.xoff;
yc = Objects[0].yc + theconf.yoff;
// draw other centroids
for(int i = 1; i < objctr; ++i)
il_Pattern_draw3(&i3, cross, Objects[i].xc, H-Objects[i].yc, C_B);
}else{xc = -1.; yc = -1.;}
char tmpnm[FILENAME_MAX+5];
sprintf(tmpnm, "%s-tmp", GP->outputjpg);
if(stbi_write_jpg(tmpnm, I->width, I->height, 3, outp, 95)){
if(rename(tmpnm, GP->outputjpg)){
WARN("rename()");
LOGWARN("can't save %s", GP->outputjpg);
}
}
DELTA("Written");
FREE(outp);
}
}else{
xc = -1.; yc = -1.;
Image_write_jpg(I, GP->outputjpg, theconf.equalize);
}
DBGLOG("Image saved");
++ImNumber; ++ImNumber;
if(lastTproc > 1.) FPS = 1. / (sl_dtime() - lastTproc); if(lastTproc > 1.) FPS = 1. / (sl_dtime() - lastTproc);
lastTproc = sl_dtime(); lastTproc = sl_dtime();

View File

@ -67,6 +67,7 @@ typedef struct{
static char *helpmsg(const char *messageid, char *buf, int buflen); static char *helpmsg(const char *messageid, char *buf, int buflen);
static char *stepperstatus(const char *messageid, char *buf, int buflen); static char *stepperstatus(const char *messageid, char *buf, int buflen);
static char *getimagedata(const char *messageid, char *buf, int buflen); static char *getimagedata(const char *messageid, char *buf, int buflen);
// should be in sorted order
static getter getterHandlers[] = { static getter getterHandlers[] = {
{"help", helpmsg, "List avaiable commands"}, {"help", helpmsg, "List avaiable commands"},
{"imdata", getimagedata, "Get image data (status, path, FPS, counter)"}, {"imdata", getimagedata, "Get image data (status, path, FPS, counter)"},
@ -80,7 +81,7 @@ static char *setfocusstate(const char *state, char *buf, int buflen);
static char *moveU(const char *val, char *buf, int buflen); static char *moveU(const char *val, char *buf, int buflen);
static char *moveV(const char *val, char *buf, int buflen); static char *moveV(const char *val, char *buf, int buflen);
static char *addcmnt(const char *cmnt, char *buf, int buflen); static char *addcmnt(const char *cmnt, char *buf, int buflen);
// should be in sorted order
static setter setterHandlers[] = { static setter setterHandlers[] = {
{"comment", addcmnt, "Add comment to XY log file"}, {"comment", addcmnt, "Add comment to XY log file"},
{"focus", setfocusstate, "Move focus to given value"}, {"focus", setfocusstate, "Move focus to given value"},