mirror of
https://github.com/eddyem/astrovideoguide_v3.git
synced 2025-12-06 02:35:11 +03:00
some bugs fixed
This commit is contained in:
parent
81c94bcd1e
commit
68449bef89
@ -5,11 +5,10 @@ set(MID_VERSION "0")
|
||||
set(MAJOR_VERSION "0")
|
||||
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||
|
||||
project(${PROJ} VERSION ${PROJ_VERSION} LANGUAGES C)
|
||||
project(${PROJ} VERSION ${VERSION} LANGUAGES C)
|
||||
|
||||
# default flags
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -std=gnu99 -march=native -fdata-sections -ffunction-sections")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
|
||||
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
@ -20,10 +19,12 @@ set(CMAKE_VERBOSE_MAKEFILE "ON")
|
||||
|
||||
# cmake -DEBUG=1 -> debugging
|
||||
if(DEFINED EBUG AND EBUG EQUAL 1)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra -Wall -Werror -W")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Og -ggdb -fno-builtin-strlen -Wextra -Wall -Werror -W")
|
||||
set(CMAKE_BUILD_TYPE DEBUG)
|
||||
add_definitions(-DEBUG)
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -march=native -fdata-sections -ffunction-sections")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections")
|
||||
set(CMAKE_BUILD_TYPE RELEASE)
|
||||
endif()
|
||||
|
||||
@ -69,7 +70,7 @@ link_directories(${${PROJ}_LIBRARY_DIRS} ${FLYCAP_LIBRARY_DIRS} ${BASLER_LIBRARY
|
||||
add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\"
|
||||
-DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\"
|
||||
-DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\"
|
||||
-DMAJOR_VERSION=\"${MAJOR_VESION}\" -DTHREAD_NUMBER=${PROCESSOR_COUNT})
|
||||
-DMAJOR_VERSION=\"${MAJOR_VERSION}\" -DTHREAD_NUMBER=${PROCESSOR_COUNT})
|
||||
|
||||
# -l
|
||||
target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES} ${FLYCAP_LIBRARIES} ${BASLER_LIBRARIES} -lm)
|
||||
|
||||
9
LocCorr/DEBUG.log.analyze
Executable file
9
LocCorr/DEBUG.log.analyze
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
ALLOC=$(grep ALLOCSZ DEBUG.log)
|
||||
FREE=$(grep FREESZ DEBUG.log)
|
||||
|
||||
echo "Total: $(echo "$ALLOC" | wc -l) allocations and $(echo "$FREE" | wc -l) frees"
|
||||
AL=$(echo "$ALLOC" | sed 's/ALLOCSZ(\([[:digit:]]*\))/\1/' | awk 'BEGIN{x=0;} {x=x+$1;} END{print x;}')
|
||||
FR=$(echo "$FREE" | sed 's/FREESZ(\([[:digit:]]*\))/\1/' | awk 'BEGIN{x=0;} {x=x+$1;} END{print x;}')
|
||||
echo "Allocated: $AL bytes, Freed: $FR bytes, difference: $((AL - FR)) bytes"
|
||||
@ -16,10 +16,10 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <usefull_macros.h>
|
||||
#include <pylonc/PylonC.h>
|
||||
|
||||
#include "basler.h"
|
||||
#include "debug.h"
|
||||
#include "imagefile.h"
|
||||
|
||||
static PYLON_DEVICE_HANDLE hDev;
|
||||
@ -74,7 +74,6 @@ static void disconnect(){
|
||||
isopened = FALSE;
|
||||
}
|
||||
|
||||
// get node & check it for read/write
|
||||
/**
|
||||
* @brief chkNode - get node & check it for read/write
|
||||
* @param phNode (io) - pointer to node
|
||||
@ -144,6 +143,7 @@ static int setBoolean(char *featureName, _Bool val){
|
||||
NODE_HANDLE hNode;
|
||||
if(!chkNode(&hNode, featureName, BooleanNode, TRUE)) return FALSE;
|
||||
PYLONFN(GenApiBooleanSetValue, hNode, val);
|
||||
return TRUE;
|
||||
}
|
||||
static int setInt(char *featureName, int64_t val){
|
||||
if(!isopened || !featureName) return FALSE;
|
||||
@ -222,6 +222,7 @@ static Image *capture(){
|
||||
float_values f;
|
||||
if(!getFloat("DeviceTemperature", &f)) WARNX("Can't get temperature");
|
||||
else{
|
||||
LOGDBG("Basler temperature: %.1f", f.val);
|
||||
DBG("Temperature: %.1f", f.val);
|
||||
if(f.val > 80.){
|
||||
WARNX("Device too hot");
|
||||
@ -230,7 +231,7 @@ static Image *capture(){
|
||||
toohot = TRUE;
|
||||
}
|
||||
}else if(toohot && f.val < 75.){
|
||||
LOGMSG("Device temperature is normal");
|
||||
LOGDBG("Device temperature is normal");
|
||||
toohot = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,8 +24,9 @@
|
||||
#include <string.h> // memcpy
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "binmorph.h"
|
||||
#include "debug.h"
|
||||
#include "imagefile.h"
|
||||
|
||||
// global arrays for erosion/dilation masks
|
||||
@ -67,7 +68,7 @@ uint8_t *filter4(uint8_t *image, int W, int H){
|
||||
uint8_t *ret = MALLOC(uint8_t, W*H);
|
||||
int W0 = (W + 7) / 8; // width in bytes
|
||||
int w = W0-1, h = H-1;
|
||||
{int y = 0;
|
||||
{
|
||||
// top of image, y = 0
|
||||
#define IM_UP
|
||||
#include "fc_filter.h"
|
||||
@ -79,7 +80,6 @@ uint8_t *filter4(uint8_t *image, int W, int H){
|
||||
}
|
||||
{
|
||||
// image bottom, y = h
|
||||
int y = h;
|
||||
#define IM_DOWN
|
||||
#include "fc_filter.h"
|
||||
#undef IM_DOWN
|
||||
@ -99,7 +99,7 @@ uint8_t *filter8(uint8_t *image, int W, int H){
|
||||
uint8_t *ret = MALLOC(uint8_t, W*H);
|
||||
int W0 = (W + 7) / 8; // width in bytes
|
||||
int w = W0-1, h = H-1;
|
||||
{int y = 0;
|
||||
{
|
||||
#define IM_UP
|
||||
#include "ec_filter.h"
|
||||
#undef IM_UP
|
||||
@ -108,7 +108,6 @@ uint8_t *filter8(uint8_t *image, int W, int H){
|
||||
#include "ec_filter.h"
|
||||
}
|
||||
{
|
||||
int y = h;
|
||||
#define IM_DOWN
|
||||
#include "ec_filter.h"
|
||||
#undef IM_DOWN
|
||||
@ -130,7 +129,7 @@ uint8_t *dilation(uint8_t *image, int W, int H){
|
||||
uint8_t lastmask = ~(1<<rest);
|
||||
if(!DIL) morph_init();
|
||||
uint8_t *ret = MALLOC(uint8_t, W0*H);
|
||||
{int y = 0;
|
||||
{
|
||||
// top of image, y = 0
|
||||
#define IM_UP
|
||||
#include "dilation.h"
|
||||
@ -140,7 +139,7 @@ uint8_t *dilation(uint8_t *image, int W, int H){
|
||||
// mid of image, y = 1..h-1
|
||||
#include "dilation.h"
|
||||
}
|
||||
{int y = h;
|
||||
{
|
||||
// image bottom, y = h
|
||||
#define IM_DOWN
|
||||
#include "dilation.h"
|
||||
@ -329,19 +328,8 @@ uint8_t *substim(uint8_t *im1, uint8_t *im2, int W, int H){
|
||||
#define TEST(...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* label 4-connected components on image
|
||||
* (slow algorythm, but easy to parallel)
|
||||
*
|
||||
* @param I (i) - image ("packed")
|
||||
* @param W,H - size of the image (W - width in pixels)
|
||||
* @param CC (o) - connected components boxes
|
||||
* @return an array of labeled components
|
||||
*/
|
||||
size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC){
|
||||
size_t *assoc;
|
||||
// check table and rename all "oldval" into "newval"
|
||||
inline void remark(size_t newval, size_t oldval){
|
||||
static inline void remark(size_t newval, size_t oldval, size_t *assoc){
|
||||
TEST("\tnew = %zd, old=%zd; ", newval, oldval);
|
||||
// find the least values
|
||||
do{newval = assoc[newval];}while(assoc[newval] != newval);
|
||||
@ -356,6 +344,18 @@ size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC){
|
||||
TEST("change %zd to %zd\n", oldval, newval);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* label 4-connected components on image
|
||||
* (slow algorythm, but easy to parallel)
|
||||
*
|
||||
* @param I (i) - image ("packed")
|
||||
* @param W,H - size of the image (W - width in pixels)
|
||||
* @param CC (o) - connected components boxes
|
||||
* @return an array of labeled components
|
||||
*/
|
||||
size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC){
|
||||
size_t *assoc;
|
||||
if(W < MINWIDTH || H < MINHEIGHT) return NULL;
|
||||
uint8_t *f = filter4(Img, W, H); // remove all non 4-connected pixels
|
||||
//DBG("convert to size_t");
|
||||
@ -375,7 +375,7 @@ size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC){
|
||||
if(found){ // there's a pixel to the left
|
||||
if(U && U != curmark){ // meet old mark -> remark one of them in assoc[]
|
||||
TEST("(%d, %d): remark %zd --> %zd\n", x, y, U, curmark);
|
||||
remark(U, curmark);
|
||||
remark(U, curmark, assoc);
|
||||
curmark = U; // change curmark to upper mark (to reduce further checks)
|
||||
}
|
||||
}else{ // new mark -> change curmark
|
||||
@ -428,23 +428,6 @@ size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC){
|
||||
boxes[i].xmin = W;
|
||||
boxes[i].ymin = H;
|
||||
}
|
||||
//nonOMP: 36.5ms
|
||||
/* linear:
|
||||
for(int y = 0; y < H; ++y){
|
||||
size_t *lptr = &labels[y*W];
|
||||
for(int x = 0; x < W; ++x, ++lptr){
|
||||
if(!*lptr) continue;
|
||||
register size_t mark = indexes[*lptr];
|
||||
*lptr = mark;
|
||||
Box *b = &boxes[mark];
|
||||
++b->area;
|
||||
if(b->xmax < x) b->xmax = x;
|
||||
if(b->xmin > x) b->xmin = x;
|
||||
if(b->ymax < y) b->ymax = y;
|
||||
if(b->ymin > y) b->ymin = y;
|
||||
}
|
||||
}*/
|
||||
// parallel:
|
||||
#pragma omp parallel shared(boxes)
|
||||
{
|
||||
Box *l_boxes = MALLOC(Box, cidx);
|
||||
@ -507,60 +490,6 @@ size_t *cclabel8(size_t *labels, int W, int H, size_t *Nobj){
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Make connection-component labeling
|
||||
* output image vould have uint16_t data
|
||||
* @param img (i) - input image
|
||||
* @param threshold (i) - threshold level in value of dynamic range (0,1)
|
||||
* @param Nobj (o) - amount of object found (or NULL if not needed)
|
||||
*/
|
||||
IMAGE *cclabel4(IMAGE *img, double threshold, size_t *Nobj){
|
||||
/*if(N != 4 || N != 8){
|
||||
ERRX(_("Can work only for 4- or 8-connected components"));
|
||||
}*/
|
||||
double thrval;
|
||||
uint16_t *binary = binarize(img, threshold, &thrval);
|
||||
if(!binary) return NULL;
|
||||
int W_0;
|
||||
uint8_t *Ima = u16tochar(binary, img->width, img->height, &W_0);
|
||||
FREE(binary);
|
||||
size_t N;
|
||||
uint16_t *dat = _cclabel4(Ima, img->width, img->height, W_0, &N);
|
||||
if(Nobj) *Nobj = N;
|
||||
FREE(Ima);
|
||||
IMAGE *ret = buildFITSfromdat(img->height, img->width, SHORT_IMG, (uint8_t*)dat);
|
||||
FREE(dat);
|
||||
char buf[80];
|
||||
snprintf(buf, 80, "COMMENT found %zd 4-connected components, threshold value %g",
|
||||
N, (double)thrval);
|
||||
list_add_record(&ret->keylist, buf);
|
||||
snprintf(buf, 80, "COMMENT (%g%% fromdata range%s)", fabs(threshold)*100.,
|
||||
(threshold < 0.) ? ", inverted" : "");
|
||||
list_add_record(&ret->keylist, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IMAGE *cclabel8(IMAGE *img, double threshold, size_t *Nobj){
|
||||
double thrval;
|
||||
uint16_t *binary = binarize(img, threshold, &thrval);
|
||||
if(!binary) return NULL;
|
||||
size_t N;
|
||||
_cclabel8(binary, img->width, img->height, &N);
|
||||
if(Nobj) *Nobj = N;
|
||||
IMAGE *ret = buildFITSfromdat(img->height, img->width, SHORT_IMG, (uint8_t*)binary);
|
||||
FREE(binary);
|
||||
char buf[80];
|
||||
snprintf(buf, 80, "COMMENT found %zd 8-connected components, threshold value %g",
|
||||
N, (double)thrval);
|
||||
list_add_record(&ret->keylist, buf);
|
||||
snprintf(buf, 80, "COMMENT (%g%% fromdata range%s)", fabs(threshold)*100.,
|
||||
(threshold < 0.) ? ", inverted" : "");
|
||||
list_add_record(&ret->keylist, buf);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* <=================== CONNECTED COMPONENTS LABELING ===================
|
||||
*/
|
||||
|
||||
@ -60,26 +60,12 @@ uint8_t *filter4(uint8_t *image, int W, int H);
|
||||
uint8_t *filter8(uint8_t *image, int W, int H);
|
||||
|
||||
size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC);
|
||||
size_t *cclabel8(uint8_t *Img, int W, int H, size_t *Nobj);
|
||||
|
||||
#if 0
|
||||
size_t *cclabel8(uint8_t *Img, int W, int H, size_t *Nobj);
|
||||
// logical operations
|
||||
uint8_t *imand(uint8_t *im1, uint8_t *im2, int W, int H);
|
||||
uint8_t *substim(uint8_t *im1, uint8_t *im2, int W, int H);
|
||||
/*
|
||||
// conncomp
|
||||
// this is a box structure containing one object; data is aligned by original image bytes!
|
||||
typedef struct {
|
||||
uint8_t *data; // pattern data in "packed" format
|
||||
int x, // x coordinate of LU-pixel of box in "unpacked" image (by pixels)
|
||||
y, // y -//-
|
||||
x_0; // x coordinate in "packed" image (morph operations should work with it)
|
||||
size_t N;// number of component, starting from 1
|
||||
} CCbox;
|
||||
*/
|
||||
|
||||
IMAGE *cclabel4(IMAGE *I, double threshold, size_t *Nobj);
|
||||
IMAGE *cclabel8(IMAGE *I, double threshold, size_t *Nobj);
|
||||
#endif
|
||||
|
||||
#endif // BINMORPH_H__
|
||||
|
||||
@ -20,10 +20,10 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "fits.h"
|
||||
#include "grasshopper.h"
|
||||
#include "imagefile.h"
|
||||
@ -132,31 +132,19 @@ static void recalcexp(Image *I){
|
||||
exptime = theconf.maxexp;
|
||||
return;
|
||||
}
|
||||
if(I->minval < 0. || I->maxval > 255.1){
|
||||
DBG("Bad image data: min=%g, max=%g", I->minval, I->maxval);
|
||||
size_t *histogram = get_histogram(I);
|
||||
if(!histogram){
|
||||
WARNX("Can't calculate histogram");
|
||||
return;
|
||||
}
|
||||
int wh = I->width * I->height;
|
||||
int histogram[256] = {0};
|
||||
// algorythm works only with 8bit images!
|
||||
#pragma omp parallel
|
||||
{
|
||||
int histogram_private[256] = {0};
|
||||
#pragma omp for nowait
|
||||
for(int i = 0; i < wh; ++i){
|
||||
++histogram_private[(int)I->data[i]];
|
||||
}
|
||||
#pragma omp critical
|
||||
{
|
||||
for(int i=0; i<256; ++i) histogram[i] += histogram_private[i];
|
||||
}
|
||||
}
|
||||
int idx100, sum100 = 0;
|
||||
int idx100;
|
||||
size_t sum100 = 0;
|
||||
for(idx100 = 255; idx100 >= 0; --idx100){
|
||||
sum100 += histogram[idx100];
|
||||
if(sum100 > 100) break;
|
||||
}
|
||||
DBG("Sum100=%d, idx100=%d", sum100, idx100);
|
||||
FREE(histogram);
|
||||
DBG("Sum100=%zd, idx100=%d", sum100, idx100);
|
||||
if(idx100 > 230 && idx100 < 253) return; // good values
|
||||
if(idx100 > 253){ // exposure too long
|
||||
calcexpgain(0.7*exptime);
|
||||
@ -248,13 +236,25 @@ int camcapture(void (*process)(Image*)){
|
||||
FREE(oIma->data);
|
||||
FREE(oIma);
|
||||
}
|
||||
if(oIma){
|
||||
FREE(oIma->data);
|
||||
FREE(oIma);
|
||||
}
|
||||
camdisconnect();
|
||||
DBG("CAMCAPTURE: out");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// return JSON with image status
|
||||
/**
|
||||
* @brief camstatus - return JSON with image status
|
||||
* @param messageid - value of "messageid"
|
||||
* @param buf - buffer for string
|
||||
* @param buflen - length of `buf`
|
||||
* @return buf
|
||||
*/
|
||||
char *camstatus(const char *messageid, char *buf, int buflen){
|
||||
if(!buf || buflen < 2) return NULL;
|
||||
if(!messageid) messageid = "unknown";
|
||||
static char *impath = NULL;
|
||||
if(!impath){
|
||||
if(!(impath = realpath(GP->outputjpg, impath))){
|
||||
@ -263,9 +263,13 @@ char *camstatus(const char *messageid, char *buf, int buflen){
|
||||
}
|
||||
DBG("path: %s", impath);
|
||||
}
|
||||
float xc, yc;
|
||||
getcenter(&xc, &yc);
|
||||
snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"%sconnected\", \"impath\": \"%s\", \"imctr\": %llu, "
|
||||
"\"fps\": %.3f, \"expmethod\": \"%s\", \"exposition\": %g, \"gain\": %g, \"brightness\": %g }\n",
|
||||
"\"fps\": %.3f, \"expmethod\": \"%s\", \"exposition\": %g, \"gain\": %g, \"brightness\": %g, "
|
||||
"\"xcenter\": %.1f, \"ycenter\": %.1f }\n",
|
||||
MESSAGEID, messageid, connected ? "" : "dis", impath, ImNumber, getFramesPerS(),
|
||||
(theconf.expmethod == EXPAUTO) ? "auto" : "manual", exptime, gain, brightness);
|
||||
(theconf.expmethod == EXPAUTO) ? "auto" : "manual", exptime, gain, brightness,
|
||||
xc, yc);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -15,11 +15,12 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef CAMERACAPTURE_H__
|
||||
#define CAMERACAPTURE_H__
|
||||
#include "fits.h" // Image*
|
||||
|
||||
#include "imagefile.h" // Image
|
||||
|
||||
|
||||
// format of single frame
|
||||
typedef struct{
|
||||
|
||||
@ -23,10 +23,10 @@
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <math.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "improc.h"
|
||||
|
||||
/*
|
||||
@ -69,7 +69,7 @@ static myoption cmdlnopts[] = {
|
||||
{"logfile", NEED_ARG, NULL, 'l', arg_string, APTR(&G.logfile), _("file to save logs (default: none)")},
|
||||
{"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfile), _("pidfile (default: " DEFAULT_PIDFILE ")")},
|
||||
{"verbose", NO_ARGS, NULL, 'v', arg_none, APTR(&G.verb), _("increase verbosity level of log file (each -v increased by 1)")},
|
||||
{"input", NEED_ARG, NULL, 'i', arg_string, APTR(&G.inputname), _("file or directory name for monitoring (or grasshopper for capturing)")},
|
||||
{"input", NEED_ARG, NULL, 'i', arg_string, APTR(&G.inputname), _("file or directory name for monitoring (or grasshopper/basler for capturing)")},
|
||||
{"blackp", NEED_ARG, NULL, 'b', arg_double, APTR(&G.throwpart), _("fraction of black pixels to throw away when make histogram eq")},
|
||||
// {"radius", NEED_ARG, NULL, 'r', arg_int, APTR(&G.medradius), _("radius of median filter (r=1 -> 3x3, r=2 -> 5x5 etc.)")},
|
||||
{"equalize", NO_ARGS, NULL, 'e', arg_int, APTR(&G.equalize), _("make historam equalization of saved jpeg")},
|
||||
|
||||
@ -19,10 +19,10 @@
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
|
||||
static char *conffile = NULL; // configuration file name
|
||||
|
||||
@ -192,12 +192,12 @@ static char *read_key(FILE *file, char value[128]){
|
||||
char *line = NULL;
|
||||
size_t n = 0;
|
||||
int got = getline(&line, &n, file);
|
||||
if(!line) return NULL;
|
||||
if(got < 0){
|
||||
FREE(line);
|
||||
free(line);
|
||||
return NULL;
|
||||
}
|
||||
char *kv = get_keyval(line, value);
|
||||
FREE(line);
|
||||
return kv;
|
||||
}
|
||||
|
||||
@ -267,7 +267,7 @@ confparam *chk_keyval(const char *key, const char *val, key_value *result){
|
||||
*/
|
||||
int chkconfig(const char *confname){
|
||||
DBG("Config name: %s", confname);
|
||||
FREE(conffile);
|
||||
if(conffile){ free(conffile); conffile = NULL; }
|
||||
conffile = strdup(confname);
|
||||
FILE *f = fopen(confname, "r");
|
||||
int ret = TRUE;
|
||||
@ -283,7 +283,8 @@ int chkconfig(const char *confname){
|
||||
}
|
||||
while((key = read_key(f, val))){
|
||||
if(*key == '#'){
|
||||
FREE(key);
|
||||
free(key);
|
||||
key = NULL;
|
||||
continue; // comment
|
||||
}
|
||||
//DBG("key: %s", key);
|
||||
@ -291,7 +292,8 @@ int chkconfig(const char *confname){
|
||||
par = chk_keyval(key, val, &kv);
|
||||
if(!par){
|
||||
WARNX("Parameter '%s' is wrong or out of range", key);
|
||||
FREE(key);
|
||||
free(key);
|
||||
key = NULL;
|
||||
continue;
|
||||
}
|
||||
switch(par->type){
|
||||
@ -303,7 +305,8 @@ int chkconfig(const char *confname){
|
||||
break;
|
||||
}
|
||||
++par->got;
|
||||
FREE(key);
|
||||
free(key);
|
||||
key = NULL;
|
||||
}
|
||||
fclose(f);
|
||||
int found = 0;
|
||||
@ -321,34 +324,6 @@ int chkconfig(const char *confname){
|
||||
}
|
||||
++found; ++par;
|
||||
}
|
||||
#if 0
|
||||
int Nchecked = 0;
|
||||
if(theconf.maxUsteps >= MINSTEPS && theconf.maxUsteps <= MAXSTEPS) ++Nchecked;
|
||||
if(theconf.maxVsteps >= MINSTEPS && theconf.maxVsteps <= MAXSTEPS) ++Nchecked;
|
||||
if(theconf.cosXU >= -1. && theconf.cosXU <= 1.) ++Nchecked;
|
||||
if(theconf.sinXU >= -1. && theconf.sinXU <= 1.) ++Nchecked;
|
||||
if(theconf.cosXV >= -1. && theconf.cosXV <= 1.) ++Nchecked;
|
||||
if(theconf.sinXV >= -1. && theconf.sinXV <= 1.) ++Nchecked;
|
||||
if(theconf.KU >= COEFMIN && theconf.KU <= COEFMAX) ++Nchecked;
|
||||
if(theconf.KV >= COEFMIN && theconf.KV <= COEFMAX) ++Nchecked;
|
||||
if(theconf.maxarea <= MAXAREA && theconf.maxarea >= MINAREA) ++Nchecked;
|
||||
if(theconf.minarea <= MAXAREA && theconf.minarea >= MINAREA) ++Nchecked;
|
||||
if(theconf.Nerosions > 0 && theconf.Nerosions <= MAX_NEROS) ++Nchecked;
|
||||
if(theconf.Ndilations > 0 && theconf.Ndilations <= MAX_NDILAT) ++Nchecked;
|
||||
if(theconf.xtarget > 1.) ++Nchecked;
|
||||
if(theconf.ytarget > 1.) ++Nchecked;
|
||||
if(theconf.throwpart > -DBL_EPSILON && theconf.throwpart < MAX_THROWPART+DBL_EPSILON) ++Nchecked;
|
||||
if(theconf.xoff > 0 && theconf.xoff < MAX_OFFSET) ++Nchecked;
|
||||
if(theconf.yoff > 0 && theconf.yoff < MAX_OFFSET) ++Nchecked;
|
||||
if(theconf.width > 0 && theconf.width < MAX_OFFSET) ++Nchecked;
|
||||
if(theconf.height > 0 && theconf.height < MAX_OFFSET) ++Nchecked;
|
||||
if(theconf.minexp > 0. && theconf.minexp < EXPOS_MAX) ++Nchecked;
|
||||
if(theconf.maxexp > theconf.minexp) ++Nchecked;
|
||||
if(theconf.equalize > -1) ++Nchecked;
|
||||
if(theconf.intensthres > DBL_EPSILON && theconf.intensthres < 1.) ++Nchecked;
|
||||
if(theconf.naverage > 1 && theconf.naverage <= NAVER_MAX) ++Nchecked;
|
||||
if(theconf.stpserverport > 0 && theconf.stpserverport < 65536) ++Nchecked;
|
||||
#endif
|
||||
DBG("chkconfig(): found %d", found);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -42,12 +42,12 @@
|
||||
#define BRIGHT_MIN (0.)
|
||||
#define BRIGHT_MAX (10.)
|
||||
// max average images counter
|
||||
#define NAVER_MAX (50)
|
||||
#define NAVER_MAX (25)
|
||||
// coefficients to convert dx,dy to du,dv
|
||||
#define KUVMIN (-5000.)
|
||||
#define KUVMAX (5000.)
|
||||
// default coefficient for corrections (move to Kdu, Kdv instead of du, dv)
|
||||
#define KCORR (0.97)
|
||||
#define KCORR (0.90)
|
||||
// min/max median seed
|
||||
#define MIN_MEDIAN_SEED (1)
|
||||
#define MAX_MEDIAN_SEED (7)
|
||||
|
||||
57
LocCorr/debug.c
Normal file
57
LocCorr/debug.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of the loccorr project.
|
||||
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef EBUG
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#define DEBUGLOG "DEBUG.log"
|
||||
|
||||
sl_log *debuglog = NULL;
|
||||
|
||||
void makedebuglog(){
|
||||
unlink(DEBUGLOG);
|
||||
debuglog = sl_createlog(DEBUGLOG, LOGLEVEL_ANY, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief my_malloc - memory allocator for logger
|
||||
* @param N - number of elements to allocate
|
||||
* @param S - size of single element (typically sizeof)
|
||||
* @return pointer to allocated memory area
|
||||
*/
|
||||
void *my_malloc(size_t N, size_t S){
|
||||
size_t NS = N*S + sizeof(size_t);
|
||||
sl_putlogt(0, debuglog, LOGLEVEL_ERR, "ALLOCSZ(%zd)", N*S);
|
||||
void *p = malloc(NS);
|
||||
if(!p) ERR("malloc");
|
||||
memset(p, 0, NS);
|
||||
*((size_t*)p) = N*S;
|
||||
return (p + sizeof(size_t));
|
||||
}
|
||||
|
||||
void my_free(void *ptr){
|
||||
void *orig = ptr - sizeof(size_t);
|
||||
sl_putlogt(0, debuglog, LOGLEVEL_ERR, "FREESZ(%zd)", *(size_t*)orig);
|
||||
free(orig);
|
||||
}
|
||||
|
||||
#endif
|
||||
53
LocCorr/debug.h
Normal file
53
LocCorr/debug.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of the loccorr project.
|
||||
* Copyright 2021 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef DEBUG_H__
|
||||
#define DEBUG_H__
|
||||
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#ifdef EBUG
|
||||
|
||||
extern sl_log *debuglog;
|
||||
void makedebuglog();
|
||||
void *my_malloc(size_t N, size_t S);
|
||||
void my_free(void *ptr);
|
||||
|
||||
#undef FNAME
|
||||
#undef ALLOC
|
||||
#undef MALLOC
|
||||
#undef FREE
|
||||
#define _LOG(...) do{if(!debuglog) makedebuglog(); sl_putlogt(1, debuglog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
|
||||
#define DBGLOG(...) do{_LOG("%s (%s, line %d)", __func__, __FILE__, __LINE__); \
|
||||
sl_putlogt(0, debuglog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
|
||||
#define FNAME() _LOG("%s (%s, line %d)", __func__, __FILE__, __LINE__)
|
||||
|
||||
#define _str(x) #x
|
||||
#define ALLOC(type, var, size) DBGLOG("%s *%s = ALLOC(%d)", _str(type), _str(var), size*sizeof(type)); \
|
||||
type * var = ((type *)my_malloc(size, sizeof(type)))
|
||||
#define MALLOC(type, size) ((type *)my_malloc(size, sizeof(type))); DBGLOG("ALLOC()")
|
||||
#define FREE(ptr) do{if(ptr){DBGLOG("FREE(%s)", _str(ptr)); my_free(ptr); ptr = NULL;}}while(0);
|
||||
|
||||
#else
|
||||
|
||||
#define DBGLOG(...)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // DEBUG_H__
|
||||
@ -33,6 +33,12 @@ OMP_FOR()
|
||||
for(int y = 1; y < h; y++)
|
||||
#endif
|
||||
{
|
||||
#ifdef IM_UP
|
||||
int y = 0;
|
||||
#endif
|
||||
#ifdef IM_DOWN
|
||||
int y = h;
|
||||
#endif
|
||||
uint8_t *iptr = &image[W0*y];
|
||||
uint8_t *optr = &ret[W0*y];
|
||||
uint8_t p = DIL[*iptr]
|
||||
|
||||
@ -16,11 +16,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// simplest interface to draw lines & ellipsis
|
||||
// simplest interface to draw lines & ellipses
|
||||
#include "debug.h"
|
||||
#include "draw.h"
|
||||
#include "fits.h"
|
||||
|
||||
#include <usefull_macros.h>
|
||||
|
||||
// base colors:
|
||||
const uint8_t
|
||||
@ -46,13 +46,35 @@ void Pattern_free(Pattern **p){
|
||||
Pattern *Pattern_cross(int h, int w){
|
||||
int s = h*w, hmid = h/2, wmid = w/2;
|
||||
uint8_t *data = MALLOC(uint8_t, s);
|
||||
Pattern *p = MALLOC(Pattern, 1);
|
||||
p->data = data;
|
||||
p->h = h; p->w = w;
|
||||
uint8_t *ptr = &data[wmid];
|
||||
for(int y = 0; y < h; ++y, ptr += w) *ptr = 255;
|
||||
ptr = &data[hmid*w];
|
||||
for(int x = 0; x < w; ++x, ++ptr) *ptr = 255;
|
||||
return p;
|
||||
}
|
||||
|
||||
// complicated cross
|
||||
Pattern *Pattern_xcross(int h, int w){
|
||||
int s = h*w, hmid = h/2, wmid = w/2;
|
||||
uint8_t *data = MALLOC(uint8_t, s);
|
||||
Pattern *p = MALLOC(Pattern, 1);
|
||||
p->data = data;
|
||||
p->h = h; p->w = w;
|
||||
data[hmid*w + wmid] = 255; // point @ center
|
||||
if(h < 7 || w < 7) return p;
|
||||
int idxy1 = (hmid-3)*w, idxy2 = (hmid+3)*w;
|
||||
int idxx1 = wmid-3, idxx2 = wmid+3;
|
||||
for(int i = 0; i < wmid - 3; ++i){
|
||||
data[idxy1+i] = data[idxy1+w-1-i] = 255;
|
||||
data[idxy2+i] = data[idxy2+w-1-i] = 255;
|
||||
}
|
||||
for(int i = 0; i < hmid - 3; ++i){
|
||||
data[idxx1 + i*w] = data[idxx1 + (h-1-i)*w] = 255;
|
||||
data[idxx2 + i*w] = data[idxx2 + (h-1-i)*w] = 255;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
@ -63,7 +85,8 @@ Pattern *Pattern_cross(int h, int w){
|
||||
* @param xc, yc - coordinates of pattern center @ image
|
||||
* @param colr - color to draw pattern (when opaque == 255)
|
||||
*/
|
||||
void Pattern_draw3(Img3 *img, Pattern *p, int xc, int yc, const uint8_t colr[]){
|
||||
void Pattern_draw3(Img3 *img, const Pattern *p, int xc, int yc, const uint8_t colr[]){
|
||||
if(!img || !p) return;
|
||||
int xul = xc - p->w/2, yul = yc - p->h/2;
|
||||
int xdr = xul+p->w-1, ydr = yul+p->h-1;
|
||||
int R = img->w, D = img->h; // right and down border coordinates + 1
|
||||
@ -96,7 +119,7 @@ void Pattern_draw3(Img3 *img, Pattern *p, int xc, int yc, const uint8_t colr[]){
|
||||
uint8_t *in = &p->data[(iylow+y-oylow)*p->w + ixlow]; // opaque component
|
||||
uint8_t *out = &img->data[(y*img->w + oxlow)*3]; // 3-colours
|
||||
for(int x = oxlow; x < oxhigh; ++x, ++in, out += 3){
|
||||
float opaque = *in/255.;
|
||||
float opaque = ((float)*in)/255.;
|
||||
for(int c = 0; c < 3; ++c){
|
||||
out[c] = (uint8_t)(colr[c] * opaque + out[c]*(1.-opaque));
|
||||
}
|
||||
|
||||
@ -28,17 +28,6 @@ typedef struct{
|
||||
int h; // height
|
||||
} Img3;
|
||||
|
||||
/*
|
||||
// box (coordinates from upper left corner)
|
||||
typedef struct{
|
||||
int xul; // coordinates of upper left box corner
|
||||
int yul;
|
||||
int w; // width and height
|
||||
int h;
|
||||
uint8_t pattern[3]; // pattern for figure filling
|
||||
} BBox;
|
||||
*/
|
||||
|
||||
// opaque pattern for drawing
|
||||
typedef struct{
|
||||
uint8_t *data;
|
||||
@ -50,7 +39,8 @@ typedef struct{
|
||||
extern const uint8_t C_R[], C_G[], C_B[], C_K[], C_W[];
|
||||
|
||||
void Pattern_free(Pattern **p);
|
||||
void Pattern_draw3(Img3 *img, Pattern *p, int xc, int yc, const uint8_t colr[]);
|
||||
void Pattern_draw3(Img3 *img, const Pattern *p, int xc, int yc, const uint8_t colr[]);
|
||||
Pattern *Pattern_cross(int h, int w);
|
||||
Pattern *Pattern_xcross(int h, int w);
|
||||
|
||||
#endif // DRAW_H__
|
||||
|
||||
@ -23,6 +23,12 @@ OMP_FOR()
|
||||
for(int y = 1; y < h; y++)
|
||||
#endif
|
||||
{
|
||||
#ifdef IM_UP
|
||||
int y = 0;
|
||||
#endif
|
||||
#ifdef IM_DOWN
|
||||
int y = h;
|
||||
#endif
|
||||
uint8_t *iptr = &image[W0*y];
|
||||
uint8_t *optr = &ret[W0*y];
|
||||
// x=0
|
||||
|
||||
@ -23,6 +23,12 @@ OMP_FOR()
|
||||
for(int y = 1; y < h; y++)
|
||||
#endif
|
||||
{
|
||||
#ifdef IM_UP
|
||||
int y = 0;
|
||||
#endif
|
||||
#ifdef IM_DOWN
|
||||
int y = h;
|
||||
#endif
|
||||
uint8_t *iptr = &image[W0*y];
|
||||
uint8_t *optr = &ret[W0*y];
|
||||
// x=0
|
||||
|
||||
116
LocCorr/fits.c
116
LocCorr/fits.c
@ -18,9 +18,9 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <usefull_macros.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "fits.h"
|
||||
|
||||
static int fitsstatus = 0;
|
||||
@ -56,12 +56,40 @@ void Image_free(Image **img){
|
||||
FREE(*img);
|
||||
}
|
||||
|
||||
// I->data should be allocated!!!
|
||||
static inline void convflt2ima(float *f, Image *I){
|
||||
if(!I || !I->data || !f) return;
|
||||
float min = *f, max = min;
|
||||
int wh = I->height * I->width;
|
||||
#pragma omp parallel shared(min, max)
|
||||
{
|
||||
float min_p = min, max_p = min;
|
||||
#pragma omp for nowait
|
||||
for(int i = 0; i < wh; ++i){
|
||||
if(f[i] < min_p) min_p = f[i];
|
||||
else if(f[i] > max_p) max_p = f[i];
|
||||
}
|
||||
#pragma omp critical
|
||||
{
|
||||
if(min > min_p) min = min_p;
|
||||
if(max < max_p) max = max_p;
|
||||
}
|
||||
}
|
||||
float W = 255./(max - min);
|
||||
#pragma omp for
|
||||
for(int i = 0; i < wh; ++i){
|
||||
I->data[i] = (Imtype)(W*(f[i] - min));
|
||||
}
|
||||
I->maxval = 255;
|
||||
I->minval = 0;
|
||||
}
|
||||
|
||||
bool FITS_read(const char *filename, Image **fits){
|
||||
FNAME();
|
||||
bool ret = TRUE;
|
||||
fitsfile *fp;
|
||||
int i, j, hdunum, hdutype, nkeys, keypos;
|
||||
int naxis;
|
||||
int naxis, dtype;
|
||||
long naxes[2];
|
||||
char card[FLEN_CARD];
|
||||
Image *img = MALLOC(Image, 1);
|
||||
@ -75,7 +103,7 @@ bool FITS_read(const char *filename, Image **fits){
|
||||
goto returning;
|
||||
}
|
||||
// get image dimensions
|
||||
TRYFITS(fits_get_img_param, fp, 2, &img->dtype, &naxis, naxes);
|
||||
TRYFITS(fits_get_img_param, fp, 2, &dtype, &naxis, naxes);
|
||||
DBG("Image have %d axis", naxis);
|
||||
if(naxis > 2){
|
||||
WARNX(_("Images with > 2 dimensions are not supported"));
|
||||
@ -84,7 +112,7 @@ bool FITS_read(const char *filename, Image **fits){
|
||||
}
|
||||
img->width = naxes[0];
|
||||
img->height = naxes[1];
|
||||
DBG("got image %ldx%ld pix, bitpix=%d", naxes[0], naxes[1], img->dtype);
|
||||
DBG("got image %ldx%ld pix, bitpix=%d", naxes[0], naxes[1], dtype);
|
||||
// loop through all HDUs
|
||||
for(i = 1; !(fits_movabs_hdu(fp, i, &hdutype, &fitsstatus)); ++i){
|
||||
TRYFITS(fits_get_hdrpos, fp, &nkeys, &keypos);
|
||||
@ -114,25 +142,19 @@ bool FITS_read(const char *filename, Image **fits){
|
||||
}
|
||||
size_t sz = naxes[0] * naxes[1];
|
||||
img->data = MALLOC(Imtype, sz);
|
||||
float *targ = MALLOC(float, sz);
|
||||
int stat = 0;
|
||||
TRYFITS(fits_read_img, fp, FITSDATATYPE, 1, sz, NULL, img->data, &stat);
|
||||
Imtype *d = img->data, min = *d, max = *d;
|
||||
for(size_t x = 0; x < sz; ++x){
|
||||
if(d[x] > max) max = d[x];
|
||||
else if(d[x] < min) min = d[x];
|
||||
}
|
||||
img->maxval = max;
|
||||
img->minval = min;
|
||||
DBG("FITS stat: min=%g, max=%g", min, max);
|
||||
TRYFITS(fits_read_img, fp, TFLOAT, 1, sz, NULL, targ, &stat);
|
||||
if(stat) WARNX(_("Found %d pixels with undefined value"), stat);
|
||||
convflt2ima(targ, img);
|
||||
FREE(targ);
|
||||
DBG("ready");
|
||||
|
||||
returning:
|
||||
FITSFUN(fits_close_file, fp);
|
||||
if(!ret){
|
||||
if(!ret || !fits){
|
||||
Image_free(&img);
|
||||
}
|
||||
if(fits) *fits = img;
|
||||
}else *fits = img;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -143,63 +165,8 @@ bool FITS_write(const char *filename, const Image *fits){
|
||||
fitsfile *fp;
|
||||
|
||||
TRYFITS(fits_create_file, &fp, filename);
|
||||
TRYFITS(fits_create_img, fp, fits->dtype, 2, naxes);
|
||||
Imtype *outp = fits->data;
|
||||
bool need2free = FALSE;
|
||||
if(fits->dtype > 0){ // convert floating data into integer
|
||||
Imtype maxval;
|
||||
Imtype minval;
|
||||
switch(fits->dtype){
|
||||
case SBYTE_IMG: // there's a bug in cfitsio, it can't save float->sbyte
|
||||
maxval = (Imtype)INT8_MAX;
|
||||
minval = (Imtype)INT8_MIN;
|
||||
break;
|
||||
case SHORT_IMG:
|
||||
maxval = (Imtype)INT16_MAX;
|
||||
minval = (Imtype)INT16_MIN;
|
||||
break;
|
||||
case USHORT_IMG:
|
||||
maxval = (Imtype)UINT16_MAX;
|
||||
minval = (Imtype)0;
|
||||
break;
|
||||
case LONG_IMG:
|
||||
maxval = (Imtype)INT32_MAX;
|
||||
minval = (Imtype)INT32_MIN;
|
||||
break;
|
||||
case ULONG_IMG:
|
||||
maxval = (Imtype)UINT32_MAX;
|
||||
minval = (Imtype)0;
|
||||
break;
|
||||
case ULONGLONG_IMG:
|
||||
maxval = (Imtype)UINT64_MAX;
|
||||
minval = (Imtype)0;
|
||||
break;
|
||||
case LONGLONG_IMG:
|
||||
maxval = (Imtype)INT64_MAX;
|
||||
minval = (Imtype)INT64_MIN;
|
||||
break;
|
||||
case BYTE_IMG:
|
||||
default: // byte
|
||||
maxval = (Imtype)UINT8_MAX;
|
||||
minval = (Imtype)0;
|
||||
}
|
||||
DBG("maxval = %g, minval = %g", maxval, minval);
|
||||
int w = fits->width, h = fits->height;
|
||||
Imtype min = fits->minval, max = fits->maxval, W = (maxval - minval)/(max - min);
|
||||
outp = MALLOC(Imtype, w*h);
|
||||
OMP_FOR()
|
||||
for(int y = 0; y < h; ++y){
|
||||
Imtype *o = &outp[y*w], *i = &fits->data[y*w];
|
||||
for(int x = 0; x < w; ++x, ++o, ++i){
|
||||
*o = W*((*i) - min) + minval;
|
||||
//if(*o < minval || *o > maxval) red("o: %g\n", *o);
|
||||
//if(*o < minval) *o = minval;
|
||||
//else if(*o > maxval) *o = maxval;
|
||||
}
|
||||
}
|
||||
need2free = TRUE;
|
||||
DBG("converted");
|
||||
}
|
||||
TRYFITS(fits_create_img, fp, SHORT_IMG, 2, naxes);
|
||||
|
||||
if(keys){ // there's keys
|
||||
size_t i;
|
||||
char **records = fits->keylist;
|
||||
@ -216,8 +183,7 @@ bool FITS_write(const char *filename, const Image *fits){
|
||||
}
|
||||
FITSFUN(fits_write_record, fp, "COMMENT modified by loccorr");
|
||||
fitsstatus = 0;
|
||||
fits_write_img(fp, FITSDATATYPE, 1, sz, outp, &fitsstatus);
|
||||
if(need2free) FREE(outp);
|
||||
fits_write_img(fp, TBYTE, 1, sz, fits->data, &fitsstatus);
|
||||
if(fitsstatus){
|
||||
fits_report_error(stderr, fitsstatus);
|
||||
return FALSE;
|
||||
|
||||
@ -22,31 +22,9 @@
|
||||
|
||||
#include <fitsio.h>
|
||||
#include <omp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define Stringify(x) #x
|
||||
#define OMP_FOR(x) _Pragma(Stringify(omp parallel for x))
|
||||
|
||||
|
||||
typedef float Imtype; // maybe float or double only
|
||||
// this is TFLOAT or TDOUBLE depending on Imtype
|
||||
#define FITSDATATYPE TFLOAT
|
||||
/*
|
||||
typedef double Imtype;
|
||||
#define FITSDATATYPE TDOUBLE
|
||||
*/
|
||||
|
||||
typedef struct{
|
||||
int width; // width
|
||||
int height; // height
|
||||
int dtype; // data type for image storage
|
||||
Imtype *data; // picture data
|
||||
Imtype minval; // extremal data values
|
||||
Imtype maxval;
|
||||
char **keylist; // list of options for each key
|
||||
size_t keynum; // full number of keys (size of *keylist)
|
||||
} Image;
|
||||
#include "imagefile.h"
|
||||
|
||||
void Image_free(Image **ima);
|
||||
bool FITS_read(const char *filename, Image **fits);
|
||||
|
||||
@ -22,9 +22,9 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "grasshopper.h"
|
||||
#include "imagefile.h"
|
||||
|
||||
@ -32,8 +32,12 @@ static fc2Context context;
|
||||
static fc2PGRGuid guid;
|
||||
static fc2Error err = FC2_ERROR_OK;
|
||||
|
||||
#ifndef Stringify
|
||||
#define Stringify(x) #x
|
||||
#endif
|
||||
|
||||
#define FC2FN(fn, ...) do{err = FC2_ERROR_OK; if(FC2_ERROR_OK != (err=fn(context __VA_OPT__(,) __VA_ARGS__))){ \
|
||||
WARNX(#fn "(): %s", fc2ErrorToDescription(err)); return FALSE;}}while(0)
|
||||
WARNX(Stringify(fn) "(): %s", fc2ErrorToDescription(err)); return FALSE;}}while(0)
|
||||
|
||||
static void disconnect(){
|
||||
fc2DestroyContext(context);
|
||||
@ -146,6 +150,7 @@ static int geometrylimits(frameformat *max, frameformat *step){
|
||||
}
|
||||
|
||||
static int getformat(frameformat *fmt){
|
||||
if(!fmt) return FALSE;
|
||||
unsigned int packsz; float pc;
|
||||
fc2Format7ImageSettings f7;
|
||||
FC2FN(fc2GetFormat7Configuration, &f7, &packsz, &pc);
|
||||
@ -155,7 +160,7 @@ static int getformat(frameformat *fmt){
|
||||
}
|
||||
|
||||
static int changeformat(frameformat *fmt){
|
||||
FNAME();
|
||||
if(!fmt) return FALSE;
|
||||
BOOL b;
|
||||
fc2Format7ImageSettings f7;
|
||||
f7.mode = FC2_MODE_0;
|
||||
@ -203,7 +208,7 @@ static int connect(){
|
||||
}
|
||||
|
||||
static int GrabImage(fc2Image *convertedImage){
|
||||
//FNAME();
|
||||
if(!convertedImage) return FALSE;
|
||||
int ret = FALSE;
|
||||
fc2Image rawImage;
|
||||
// start capture
|
||||
@ -211,7 +216,8 @@ static int GrabImage(fc2Image *convertedImage){
|
||||
err = fc2CreateImage(&rawImage);
|
||||
if(err != FC2_ERROR_OK){
|
||||
WARNX("Error in fc2CreateImage: %s", fc2ErrorToDescription(err));
|
||||
goto rtn;
|
||||
fc2StopCapture(context);
|
||||
return FALSE;
|
||||
}
|
||||
// Retrieve the image
|
||||
err = fc2RetrieveBuffer(context, &rawImage);
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include <stb/stb_image.h>
|
||||
#include <stb/stb_image_write.h>
|
||||
@ -31,7 +30,9 @@
|
||||
#include "cameracapture.h"
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "draw.h"
|
||||
#include "fits.h"
|
||||
#include "grasshopper.h"
|
||||
#include "imagefile.h"
|
||||
#include "median.h"
|
||||
@ -68,6 +69,11 @@ static char *hexdmp(const char sig[8]){
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief imtype - check image type of given file
|
||||
* @param f - opened image file structure
|
||||
* @return image type or T_WRONG
|
||||
*/
|
||||
static InputType imtype(FILE *f){
|
||||
char signature[8];
|
||||
int x = fread(signature, 1, 7, f);
|
||||
@ -122,37 +128,22 @@ InputType chkinput(const char *name){
|
||||
return tp;
|
||||
}
|
||||
|
||||
Image *u8toImage(uint8_t *data, int width, int height, int stride){
|
||||
FNAME();
|
||||
Image *outp = MALLOC(Image, 1);
|
||||
outp->width = width;
|
||||
outp->height = height;
|
||||
outp->dtype = FLOAT_IMG;
|
||||
/*
|
||||
int histogram[256] = {0};
|
||||
int wh = width*height;
|
||||
#pragma omp parallel
|
||||
{
|
||||
int histogram_private[256] = {0};
|
||||
#pragma omp for nowait
|
||||
for(int i = 0; i < wh; ++i){
|
||||
++histogram_private[data[i]];
|
||||
}
|
||||
#pragma omp critical
|
||||
{
|
||||
for(int i=0; i<256; ++i) histogram[i] += histogram_private[i];
|
||||
}
|
||||
}
|
||||
red("HISTO:\n");
|
||||
for(int i = 0; i < 256; ++i) printf("%d:\t%d\n", i, histogram[i]);
|
||||
/**
|
||||
* @brief u8toImage - convert uint8_t data to Image structure (flipping upside down for FITS coordinates)
|
||||
* @param data - original image data
|
||||
* @param width - image width
|
||||
* @param height - image height
|
||||
* @param stride - image width with alignment
|
||||
* @return Image structure (fully allocated, you can FREE(data) after it)
|
||||
*/
|
||||
|
||||
outp->data = MALLOC(Imtype, width*height);
|
||||
Image *u8toImage(const uint8_t *data, int width, int height, int stride){
|
||||
FNAME();
|
||||
Image *outp = Image_new(width, height);
|
||||
// flip image updown for FITS coordinate system
|
||||
OMP_FOR()
|
||||
for(int y = 0; y < height; ++y){
|
||||
Imtype *Out = &outp->data[(height-1-y)*width];
|
||||
uint8_t *In = &data[y*stride];
|
||||
const uint8_t *In = &data[y*stride];
|
||||
for(int x = 0; x < width; ++x){
|
||||
*Out++ = (Imtype)(*In++);
|
||||
}
|
||||
@ -161,15 +152,21 @@ Image *u8toImage(uint8_t *data, int width, int height, int stride){
|
||||
return outp;
|
||||
}
|
||||
|
||||
// load other image file
|
||||
static Image *im_load(const char *name){
|
||||
/**
|
||||
* @brief im_load - load image file
|
||||
* @param name - filename
|
||||
* @return Image structure or NULL
|
||||
*/
|
||||
static inline Image *im_load(const char *name){
|
||||
int width, height, channels;
|
||||
uint8_t *img = stbi_load(name, &width, &height, &channels, 1);
|
||||
if(!img){
|
||||
WARNX("Error in loading the image %s\n", name);
|
||||
return NULL;
|
||||
}
|
||||
return u8toImage(img, width, height, width);
|
||||
Image *I = u8toImage(img, width, height, width);
|
||||
free(img);
|
||||
return I;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,6 +196,7 @@ Image *Image_read(const char *name){
|
||||
* @return data allocated here
|
||||
*/
|
||||
Image *Image_new(int w, int h){
|
||||
if(w < 1 || h < 1) return NULL;
|
||||
Image *outp = MALLOC(Image, 1);
|
||||
outp->width = w;
|
||||
outp->height = h;
|
||||
@ -213,24 +211,99 @@ Image *Image_new(int w, int h){
|
||||
*/
|
||||
Image *Image_sim(const Image *i){
|
||||
if(!i) return NULL;
|
||||
if((i->width * i->height) < 1) return NULL;
|
||||
Image *outp = Image_new(i->width, i->height);
|
||||
outp->dtype = i->dtype;
|
||||
return outp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief linear - linear transform (mirror image upside down!)
|
||||
* @brief get_histogram - calculate image histogram
|
||||
* @param I - orig
|
||||
* @return
|
||||
*/
|
||||
size_t *get_histogram(const Image *I){
|
||||
if(!I || !I->data) return NULL;
|
||||
size_t *histogram = MALLOC(size_t, 256);
|
||||
int wh = I->width * I->height;
|
||||
#pragma omp parallel
|
||||
{
|
||||
size_t histogram_private[256] = {0};
|
||||
#pragma omp for nowait
|
||||
for(int i = 0; i < wh; ++i){
|
||||
++histogram_private[I->data[i]];
|
||||
}
|
||||
#pragma omp critical
|
||||
{
|
||||
for(int i = 0; i < 256; ++i) histogram[i] += histogram_private[i];
|
||||
}
|
||||
}
|
||||
return histogram;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief calc_background - Simple background calculation by histogram
|
||||
* @param img (i) - input image (here will be modified its top2proc field)
|
||||
* @param bk (o) - background value
|
||||
* @return 0 if error
|
||||
*/
|
||||
int calc_background(const Image *img, Imtype *bk){
|
||||
if(!img || !img->data || !bk) return FALSE;
|
||||
if(img->maxval == img->minval){
|
||||
WARNX("Zero or overilluminated image!");
|
||||
return FALSE;
|
||||
}
|
||||
if(theconf.fixedbkg){
|
||||
if(theconf.fixedbkg > img->minval){
|
||||
WARNX("Image values too small");
|
||||
return FALSE;
|
||||
}
|
||||
*bk = theconf.fixedbkg;
|
||||
return TRUE;
|
||||
}
|
||||
size_t *histogram = get_histogram(img);
|
||||
|
||||
size_t modeidx = 0, modeval = 0;
|
||||
for(int i = 0; i < 256; ++i)
|
||||
if(modeval < histogram[i]){
|
||||
modeval = histogram[i];
|
||||
modeidx = i;
|
||||
}
|
||||
//DBG("Mode=%g @ idx%d (N=%d)", ((Imtype)modeidx / 255.)*ampl, modeidx, modeval);
|
||||
ssize_t diff2[256] = {0};
|
||||
for(int i = 2; i < 254; ++i) diff2[i] = (histogram[i+2]+histogram[i-2]-2*histogram[i])/4;
|
||||
//green("HISTO:\n");
|
||||
//for(int i = 0; i < 256; ++i) printf("%d:\t%d\t%d\n", i, histogram[i], diff2[i]);
|
||||
FREE(histogram);
|
||||
if(modeidx < 2) modeidx = 2;
|
||||
if(modeidx > 253){
|
||||
WARNX("Overilluminated image");
|
||||
return FALSE; // very bad image: overilluminated
|
||||
}
|
||||
size_t borderidx = modeidx;
|
||||
for(int i = modeidx; i < 254; ++i){ // search bend-point by second derivate
|
||||
if(diff2[i] <= 0 && diff2[i+1] <= 0){
|
||||
borderidx = i; break;
|
||||
}
|
||||
}
|
||||
//DBG("borderidx=%d -> %d", borderidx, (borderidx+modeidx)/2);
|
||||
//*bk = (borderidx + modeidx) / 2;
|
||||
*bk = borderidx;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief linear - linear transform for preparing file to save as JPEG or other type (mirror image upside down!)
|
||||
* @param I - input image
|
||||
* @param nchannels - 1 or 3 colour channels
|
||||
* @return allocated here image for jpeg/png storing
|
||||
*/
|
||||
uint8_t *linear(const Image *I, int nchannels){ // only 1 and 3 channels supported!
|
||||
if(nchannels != 1 && nchannels != 3) return NULL;
|
||||
if(!I || !I->data || (nchannels != 1 && nchannels != 3)) return NULL;
|
||||
int width = I->width, height = I->height;
|
||||
size_t stride = width*nchannels, S = height*stride;
|
||||
uint8_t *outp = MALLOC(uint8_t, S);
|
||||
Imtype min = I->minval, max = I->maxval, W = 255./(max - min);
|
||||
float min = (float)I->minval, max = (float)I->maxval, W = 255./(max - min);
|
||||
//DBG("make linear transform %dx%d, %d channels", I->width, I->height, nchannels);
|
||||
if(nchannels == 3){
|
||||
OMP_FOR()
|
||||
@ -238,7 +311,7 @@ uint8_t *linear(const Image *I, int nchannels){ // only 1 and 3 channels support
|
||||
uint8_t *Out = &outp[(height-1-y)*stride];
|
||||
Imtype *In = &I->data[y*width];
|
||||
for(int x = 0; x < width; ++x){
|
||||
Out[0] = Out[1] = Out[2] = (uint8_t)(W*((*In++) - min));
|
||||
Out[0] = Out[1] = Out[2] = (uint8_t)(W*((float)(*In++) - min));
|
||||
Out += 3;
|
||||
}
|
||||
}
|
||||
@ -248,7 +321,7 @@ uint8_t *linear(const Image *I, int nchannels){ // only 1 and 3 channels support
|
||||
uint8_t *Out = &outp[(height-1-y)*width];
|
||||
Imtype *In = &I->data[y*width];
|
||||
for(int x = 0; x < width; ++x){
|
||||
*Out++ = (uint8_t)(W*((*In++) - min));
|
||||
*Out++ = (uint8_t)(W*((float)(*In++) - min));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -263,24 +336,19 @@ uint8_t *linear(const Image *I, int nchannels){ // only 1 and 3 channels support
|
||||
* @return allocated here image for jpeg/png storing
|
||||
*/
|
||||
uint8_t *equalize(const Image *I, int nchannels, double throwpart){
|
||||
if(nchannels != 1 && nchannels != 3) return NULL;
|
||||
if(!I || !I->data || (nchannels != 1 && nchannels != 3)) return NULL;
|
||||
int width = I->width, height = I->height;
|
||||
size_t stride = width*nchannels, S = height*stride;
|
||||
uint8_t *lin = linear(I, 1);
|
||||
if(!lin) return NULL;
|
||||
size_t *orig_histo = get_histogram(I); // original hystogram (linear)
|
||||
if(!orig_histo) return NULL;
|
||||
uint8_t *outp = MALLOC(uint8_t, S);
|
||||
int orig_hysto[256] = {0}; // original hystogram (linear)
|
||||
uint8_t eq_levls[256] = {0}; // levels to convert: newpix = eq_levls[oldpix]
|
||||
int s = width*height;
|
||||
for(int i = 0; i < s; ++i){
|
||||
++orig_hysto[lin[i]];
|
||||
}
|
||||
|
||||
int Nblack = 0, bpart = (int)(throwpart * s);
|
||||
int Nblack = 0, bpart = (int)(throwpart * (double)s);
|
||||
int startidx;
|
||||
// remove first part of black pixels
|
||||
for(startidx = 0; startidx < 256; ++startidx){
|
||||
Nblack += orig_hysto[startidx];
|
||||
Nblack += orig_histo[startidx];
|
||||
if(Nblack >= bpart) break;
|
||||
}
|
||||
++startidx;
|
||||
@ -290,15 +358,9 @@ uint8_t *equalize(const Image *I, int nchannels, double throwpart){
|
||||
if(Nwhite >= wpart) break;
|
||||
}*/
|
||||
//DBG("Throw %d (real: %d black) pixels, startidx=%d", bpart, Nblack, startidx);
|
||||
/*
|
||||
double part = (double)(s + 1) / 256., N = 0.;
|
||||
for(int i = 0; i < 256; ++i){
|
||||
N += orig_hysto[i];
|
||||
eq_levls[i] = (uint8_t)(N/part);
|
||||
}*/
|
||||
double part = (double)(s + 1. - Nblack) / 256., N = 0.;
|
||||
for(int i = startidx; i < 256; ++i){
|
||||
N += orig_hysto[i];
|
||||
N += orig_histo[i];
|
||||
eq_levls[i] = (uint8_t)(N/part);
|
||||
}
|
||||
//for(int i = stopidx; i < 256; ++i) eq_levls[i] = 255;
|
||||
@ -309,8 +371,8 @@ uint8_t *equalize(const Image *I, int nchannels, double throwpart){
|
||||
if(nchannels == 3){
|
||||
OMP_FOR()
|
||||
for(int y = 0; y < height; ++y){
|
||||
uint8_t *Out = &outp[y*stride];
|
||||
uint8_t *In = &lin[y*width];
|
||||
uint8_t *Out = &outp[(height-1-y)*stride];
|
||||
Imtype *In = &I->data[y*width];
|
||||
for(int x = 0; x < width; ++x){
|
||||
Out[0] = Out[1] = Out[2] = eq_levls[*In++];
|
||||
Out += 3;
|
||||
@ -319,14 +381,14 @@ uint8_t *equalize(const Image *I, int nchannels, double throwpart){
|
||||
}else{
|
||||
OMP_FOR()
|
||||
for(int y = 0; y < height; ++y){
|
||||
uint8_t *Out = &outp[y*width];
|
||||
uint8_t *In = &lin[y*width];
|
||||
uint8_t *Out = &outp[(height-1-y)*width];
|
||||
Imtype *In = &I->data[y*width];
|
||||
for(int x = 0; x < width; ++x){
|
||||
*Out++ = eq_levls[*In++];
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE(lin);
|
||||
FREE(orig_histo);
|
||||
return outp;
|
||||
}
|
||||
|
||||
@ -344,6 +406,7 @@ int Image_write_jpg(const Image *I, const char *name, int eq){
|
||||
outp = equalize(I, 1, theconf.throwpart);
|
||||
else
|
||||
outp = linear(I, 1);
|
||||
if(!outp) return 0;
|
||||
//DBG("Try to write %s", name);
|
||||
char *tmpnm = MALLOC(char, strlen(name) + 5);
|
||||
sprintf(tmpnm, "%s-tmp", name);
|
||||
@ -372,8 +435,9 @@ void Image_minmax(Image *I){
|
||||
int min_p = min, max_p = min;
|
||||
#pragma omp for nowait
|
||||
for(int i = 0; i < wh; ++i){
|
||||
if(I->data[i] < min_p) min_p = I->data[i];
|
||||
else if(I->data[i] > max_p) max_p = I->data[i];
|
||||
Imtype pixval = I->data[i];
|
||||
if(pixval < min_p) min_p = pixval;
|
||||
else if(pixval > max_p) max_p = pixval;
|
||||
}
|
||||
#pragma omp critical
|
||||
{
|
||||
@ -383,27 +447,26 @@ void Image_minmax(Image *I){
|
||||
}
|
||||
I->maxval = max;
|
||||
I->minval = min;
|
||||
DBG("Image_minmax(): Min=%g, Max=%g, time: %gms", min, max, (dtime()-t0)*1e3);
|
||||
DBG("Image_minmax(): Min=%d, Max=%d, time: %gms", min, max, (dtime()-t0)*1e3);
|
||||
}
|
||||
|
||||
/*
|
||||
* =================== CONVERT IMAGE TYPES ===================>
|
||||
*/
|
||||
|
||||
// convert binarized image into floating
|
||||
/**
|
||||
* @brief bin2Im - convert binarized image into floating
|
||||
* @param image - binarized image
|
||||
* @param W, H - its size (in pixels!)
|
||||
* @return Image structure
|
||||
*/
|
||||
Image *bin2Im(uint8_t *image, int W, int H){
|
||||
Image *bin2Im(const uint8_t *image, int W, int H){
|
||||
Image *ret = Image_new(W, H);
|
||||
int stride = (W + 7) / 8, s1 = (stride*8 == W) ? stride : stride - 1;
|
||||
OMP_FOR()
|
||||
for(int y = 0; y < H; y++){
|
||||
Imtype *optr = &ret->data[y*W];
|
||||
uint8_t *iptr = &image[y*stride];
|
||||
const uint8_t *iptr = &image[y*stride];
|
||||
for(int x = 0; x < s1; x++){
|
||||
register uint8_t inp = *iptr++;
|
||||
for(int i = 0; i < 8; ++i){
|
||||
@ -412,20 +475,21 @@ Image *bin2Im(uint8_t *image, int W, int H){
|
||||
}
|
||||
}
|
||||
int rest = W - s1*8;
|
||||
if(rest){
|
||||
register uint8_t inp = *iptr;
|
||||
for(int i = 0; i < rest; ++i){
|
||||
*optr++ = (inp & 0x80) ? 1. : 0;
|
||||
inp <<= 1;
|
||||
}
|
||||
}
|
||||
ret->dtype = BYTE_IMG;
|
||||
}
|
||||
ret->minval = 0;
|
||||
ret->maxval = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert floatpoint image into pseudo-packed (1 char == 8 pixels), all values > 0 will be 1, else - 0
|
||||
* Convert floatpoint image into pseudo-packed (1 char == 8 pixels), all values > bk will be 1, else - 0
|
||||
* @param im (i) - image to convert
|
||||
* @param stride (o) - new width of image
|
||||
* @param bk - background level (all values < bk will be 0, other will be 1)
|
||||
@ -438,46 +502,47 @@ uint8_t *Im2bin(const Image *im, Imtype bk){
|
||||
int y, W0 = (W + 7) / 8, s1 = (W/8 == W0) ? W0 : W0 - 1;
|
||||
uint8_t *ret = MALLOC(uint8_t, W0 * H);
|
||||
OMP_FOR()
|
||||
for(y = 0; y < H; y++){
|
||||
for(y = 0; y < H; ++y){
|
||||
Imtype *iptr = &im->data[y*W];
|
||||
uint8_t *optr = &ret[y*W0];
|
||||
register uint8_t o;
|
||||
for(int x = 0; x < s1; ++x){
|
||||
o = 0;
|
||||
register uint8_t o = 0;
|
||||
for(int i = 0; i < 8; ++i){
|
||||
o <<= 1;
|
||||
if(*iptr++ > bk) o |= 1;
|
||||
}
|
||||
*optr++ = o;
|
||||
}
|
||||
int rest = 7 - (W - s1*8);
|
||||
if(rest < 7){
|
||||
o = 0;
|
||||
for(int x = 7; x > rest; --x){
|
||||
if(*iptr++ > 0.) o |= 1<<x;
|
||||
int rest = W - s1*8;
|
||||
if(rest){
|
||||
register uint8_t o = 0;
|
||||
for(int x = 0; x < rest; ++x){
|
||||
o <<= 1;
|
||||
if(*iptr++ > bk) o |= 1;
|
||||
}
|
||||
*optr = o;
|
||||
//*optr = o | 1<<rest; // mark outern right edge (for good CC labeling)
|
||||
*optr = o << (8 - rest);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// convert size_t labels into floating
|
||||
Image *ST2Im(size_t *image, int W, int H){
|
||||
#if 0
|
||||
UNUSED function! Need to be refactored
|
||||
// convert size_t labels into Image
|
||||
Image *ST2Im(const size_t *image, int W, int H){
|
||||
Image *ret = Image_new(W, H);
|
||||
OMP_FOR()
|
||||
for(int y = 0; y < H; ++y){
|
||||
Imtype *optr = &ret->data[y*W];
|
||||
size_t *iptr = &image[y*W];
|
||||
const size_t *iptr = &image[y*W];
|
||||
for(int x = 0; x < W; ++x){
|
||||
*optr++ = (Imtype)*iptr++;
|
||||
}
|
||||
}
|
||||
ret->dtype = FLOAT_IMG;
|
||||
Image_minmax(ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Convert "packed" image into size_t array for conncomp procedure
|
||||
@ -485,13 +550,13 @@ Image *ST2Im(size_t *image, int W, int H){
|
||||
* @param W, H - size of image in pixels
|
||||
* @return allocated memory area with copy of an image
|
||||
*/
|
||||
size_t *bin2ST(uint8_t *image, int W, int H){
|
||||
size_t *bin2ST(const uint8_t *image, int W, int H){
|
||||
size_t *ret = MALLOC(size_t, W * H);
|
||||
int W0 = (W + 7) / 8, s1 = W0 - 1;
|
||||
OMP_FOR()
|
||||
for(int y = 0; y < H; y++){
|
||||
size_t *optr = &ret[y*W];
|
||||
uint8_t *iptr = &image[y*W0];
|
||||
const uint8_t *iptr = &image[y*W0];
|
||||
for(int x = 0; x < s1; ++x){
|
||||
register uint8_t inp = *iptr++;
|
||||
for(int i = 0; i < 8; ++i){
|
||||
@ -500,12 +565,14 @@ size_t *bin2ST(uint8_t *image, int W, int H){
|
||||
}
|
||||
}
|
||||
int rest = W - s1*8;
|
||||
if(rest){
|
||||
register uint8_t inp = *iptr;
|
||||
for(int i = 0; i < rest; ++i){
|
||||
*optr++ = (inp & 0x80) ? 1 : 0;
|
||||
inp <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -20,8 +20,24 @@
|
||||
#define IMAGEFILE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> // size_t
|
||||
|
||||
#include "fits.h"
|
||||
#ifndef OMP_FOR
|
||||
#define Stringify(x) #x
|
||||
#define OMP_FOR(x) _Pragma(Stringify(omp parallel for x))
|
||||
#endif
|
||||
|
||||
typedef uint8_t Imtype; // maybe float or double only
|
||||
|
||||
typedef struct{
|
||||
int width; // width
|
||||
int height; // height
|
||||
Imtype *data; // picture data
|
||||
Imtype minval; // extremal data values
|
||||
Imtype maxval;
|
||||
char **keylist; // list of options for each key
|
||||
size_t keynum; // full number of keys (size of *keylist)
|
||||
} Image;
|
||||
|
||||
// input file/directory type
|
||||
typedef enum{
|
||||
@ -46,11 +62,13 @@ Image *Image_new(int w, int h);
|
||||
Image *Image_sim(const Image *i);
|
||||
void Image_free(Image **I);
|
||||
int Image_write_jpg(const Image *I, const char *name, int equalize);
|
||||
size_t *get_histogram(const Image *I);
|
||||
int calc_background(const Image *img, Imtype *bk);
|
||||
|
||||
Image *u8toImage(uint8_t *data, int width, int height, int stride);
|
||||
Image *bin2Im(uint8_t *image, int W, int H);
|
||||
Image *u8toImage(const uint8_t *data, int width, int height, int stride);
|
||||
Image *bin2Im(const uint8_t *image, int W, int H);
|
||||
uint8_t *Im2bin(const Image *im, Imtype bk);
|
||||
size_t *bin2ST(uint8_t *image, int W, int H);
|
||||
Image *ST2Im(size_t *image, int W, int H);
|
||||
size_t *bin2ST(const uint8_t *image, int W, int H);
|
||||
//Image *ST2Im(const size_t *image, int W, int H);
|
||||
|
||||
#endif // IMAGEFILE_H__
|
||||
|
||||
@ -21,13 +21,13 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "basler.h"
|
||||
#include "binmorph.h"
|
||||
#include "cameracapture.h"
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "draw.h"
|
||||
#include "grasshopper.h"
|
||||
#include "fits.h"
|
||||
@ -47,6 +47,7 @@ steppersproc *theSteppers = NULL;
|
||||
static FILE *fXYlog = NULL;
|
||||
static double tstart = 0.; // time of logging start
|
||||
static double FPS = 0.; // frames per second
|
||||
static float xc = -1., yc = -1.; // center coordinates
|
||||
|
||||
typedef struct{
|
||||
uint32_t area; // object area in pixels
|
||||
@ -115,7 +116,7 @@ static void XYnewline(){
|
||||
|
||||
static void getDeviation(object *curobj){
|
||||
int averflag = 0;
|
||||
static double Xc[MAX_AVERAGING_ARRAY_SIZE], Yc[MAX_AVERAGING_ARRAY_SIZE];
|
||||
static double Xc[NAVER_MAX+1], Yc[NAVER_MAX+1];
|
||||
double xx = curobj->xc, yy = curobj->yc, xsum2 = 0., ysum2 = 0.;
|
||||
double Sx = 0., Sy = 0.;
|
||||
static int counter = 0;
|
||||
@ -126,23 +127,24 @@ static void getDeviation(object *curobj){
|
||||
curobj->xsigma, curobj->ysigma, curobj->WdivH);
|
||||
}
|
||||
//DBG("counter = %d", counter);
|
||||
if(++counter != theconf.naverage){
|
||||
if(++counter < theconf.naverage){
|
||||
goto process_corrections;
|
||||
}
|
||||
// it's time to calculate average deviations
|
||||
counter = 0; xx = 0.; yy = 0.;
|
||||
for(int i = 0; i < theconf.naverage; ++i){
|
||||
xx = 0.; yy = 0.;
|
||||
for(int i = 0; i < counter; ++i){
|
||||
double x = Xc[i], y = Yc[i];
|
||||
xx += x; yy += y;
|
||||
xsum2 += x*x; ysum2 += y*y;
|
||||
}
|
||||
xx /= theconf.naverage; yy /= theconf.naverage;
|
||||
Sx = sqrt(xsum2/theconf.naverage - xx*xx);
|
||||
Sy = sqrt(ysum2/theconf.naverage - yy*yy);
|
||||
xx /= counter; yy /= counter;
|
||||
Sx = sqrt(xsum2/counter - xx*xx);
|
||||
Sy = sqrt(ysum2/counter - yy*yy);
|
||||
counter = 0;
|
||||
#ifdef EBUG
|
||||
green("\n Average centroid: X=%g (+-%g), Y=%g (+-%g)\n", xx, Sx, yy, Sy);
|
||||
green("\n Average centroid: X=%.1f (+-%.1f), Y=%.1f (+-%.1f)\n", xx, Sx, yy, Sy);
|
||||
#endif
|
||||
LOGDBG("getDeviation(): Average centroid: X=%g (+-%g), Y=%g (+-%g)", xx, Sx, yy, Sy);
|
||||
LOGDBG("getDeviation(): Average centroid: X=%.1f (+-%.1f), Y=%.1f (+-%.1f)", xx, Sx, yy, Sy);
|
||||
averflag = 1;
|
||||
if(fXYlog) fprintf(fXYlog, "%.1f\t%.1f\t%.1f\t%.1f", xx, yy, Sx, Sy);
|
||||
process_corrections:
|
||||
@ -156,7 +158,6 @@ process_corrections:
|
||||
}
|
||||
|
||||
void process_file(Image *I){
|
||||
FNAME();
|
||||
static double lastTproc = 0.;
|
||||
/*
|
||||
#ifdef EBUG
|
||||
@ -176,12 +177,11 @@ void process_file(Image *I){
|
||||
return;
|
||||
}
|
||||
int W = I->width, H = I->height;
|
||||
if(!I->dtype) I->dtype = FLOAT_IMG;
|
||||
//save_fits(I, "fitsout.fits");
|
||||
//DELTA("Save original");
|
||||
Imtype bk;
|
||||
if(calc_background(I, &bk)){
|
||||
DBG("backgr = %g", bk);
|
||||
DBG("backgr = %d", bk);
|
||||
DELTA("Got background");
|
||||
uint8_t *ibin = Im2bin(I, bk);
|
||||
DELTA("Made binary");
|
||||
@ -201,14 +201,14 @@ void process_file(Image *I){
|
||||
ConnComps *cc = NULL;
|
||||
size_t *S = cclabel4(opn, W, H, &cc);
|
||||
FREE(opn);
|
||||
if(cc->Nobj > 1){
|
||||
if(cc->Nobj > 1){ // Nobj = amount of objects + 1
|
||||
DBGLOG("Nobj=%d", cc->Nobj-1);
|
||||
object *Objects = MALLOC(object, cc->Nobj-1);
|
||||
int objctr = 0;
|
||||
for(size_t i = 1; i < cc->Nobj; ++i){
|
||||
Box *b = &cc->boxes[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 < theconf.minwh || wh > theconf.maxwh) continue;
|
||||
if((int)b->area < theconf.minarea || (int)b->area > theconf.maxarea) continue;
|
||||
double xc = 0., yc = 0.;
|
||||
@ -239,13 +239,14 @@ void process_file(Image *I){
|
||||
};
|
||||
}
|
||||
DELTA("Labeling");
|
||||
DBG("T%zd, N=%d\n", time(NULL), objctr);
|
||||
DBGLOG("T%.2f, N=%d\n", dtime(), objctr);
|
||||
if(objctr > 1){
|
||||
if(theconf.starssort)
|
||||
qsort(Objects, objctr, sizeof(object), compIntens);
|
||||
else
|
||||
qsort(Objects, objctr, sizeof(object), compDist);
|
||||
}
|
||||
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",
|
||||
@ -258,6 +259,7 @@ void process_file(Image *I){
|
||||
}
|
||||
#endif
|
||||
getDeviation(Objects); // calculate dX/dY and process corrections
|
||||
}
|
||||
{ // prepare image and save jpeg
|
||||
uint8_t *outp = NULL;
|
||||
if(theconf.equalize)
|
||||
@ -265,7 +267,7 @@ void process_file(Image *I){
|
||||
else
|
||||
outp = linear(I, 3);
|
||||
static Pattern *cross = NULL;
|
||||
if(!cross) cross = Pattern_cross(33, 33);
|
||||
if(!cross) cross = Pattern_xcross(33, 33);
|
||||
Img3 i3 = {.data = outp, .w = I->width, .h = H};
|
||||
// draw fiber center position
|
||||
Pattern_draw3(&i3, cross, theconf.xtarget-theconf.xoff, H-(theconf.ytarget-theconf.yoff), C_B);
|
||||
@ -273,11 +275,12 @@ void process_file(Image *I){
|
||||
int H = I->height;
|
||||
// draw current star centroid
|
||||
Pattern_draw3(&i3, cross, Objects[0].xc, H-Objects[0].yc, C_G);
|
||||
xc = Objects[0].xc;
|
||||
yc = Objects[0].yc;
|
||||
// draw other centroids
|
||||
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!
|
||||
}
|
||||
}else{xc = -1.; yc = -1.;}
|
||||
char *tmpnm = MALLOC(char, strlen(GP->outputjpg) + 5);
|
||||
sprintf(tmpnm, "%s-tmp", GP->outputjpg);
|
||||
if(stbi_write_jpg(tmpnm, I->width, I->height, 3, outp, 95)){
|
||||
@ -290,7 +293,11 @@ void process_file(Image *I){
|
||||
FREE(outp);
|
||||
}
|
||||
FREE(Objects);
|
||||
}else Image_write_jpg(I, GP->outputjpg, theconf.equalize);
|
||||
}else{
|
||||
xc = -1.; yc = -1.;
|
||||
Image_write_jpg(I, GP->outputjpg, theconf.equalize);
|
||||
}
|
||||
DBGLOG("Image saved");
|
||||
FREE(S);
|
||||
FREE(cc);
|
||||
}
|
||||
@ -306,8 +313,8 @@ static char *localimages(const char *messageid, int isdir, char *buf, int buflen
|
||||
if(!impath){
|
||||
if(!realpath(GP->outputjpg, impath)) impath = strdup(GP->outputjpg);
|
||||
}
|
||||
snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"watch %s\", \"impath\": \"%s\"}",
|
||||
MESSAGEID, messageid, isdir ? "directory" : "file", impath);
|
||||
snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"watch %s\", \"impath\": \"%s\", \"xcenter\": %.1f, \"ycenter\": %.1f }",
|
||||
MESSAGEID, messageid, isdir ? "directory" : "file", impath, xc, yc);
|
||||
return buf;
|
||||
}
|
||||
static char *watchdr(const char *messageid, char *buf, int buflen){
|
||||
@ -383,3 +390,8 @@ void setpostprocess(const char *name){
|
||||
}
|
||||
|
||||
double getFramesPerS(){ return FPS; }
|
||||
|
||||
void getcenter(float *x, float *y){
|
||||
if(x) *x = xc;
|
||||
if(y) *y = yc;
|
||||
}
|
||||
|
||||
@ -27,8 +27,6 @@
|
||||
#define XY_TOLERANCE (5.)
|
||||
|
||||
#define PUSIROBO_POSTPROC "pusirobo"
|
||||
// how many frames will be averaged to count image deviation
|
||||
#define MAX_AVERAGING_ARRAY_SIZE (25)
|
||||
|
||||
extern volatile atomic_bool stopwork;
|
||||
extern volatile atomic_ullong ImNumber;
|
||||
@ -54,5 +52,6 @@ void openXYlog(const char *name);
|
||||
void closeXYlog();
|
||||
void setpostprocess(const char *name);
|
||||
double getFramesPerS();
|
||||
void getcenter(float *x, float *y);
|
||||
|
||||
#endif // IMPROC_H__
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/select.h>
|
||||
#include <unistd.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "imagefile.h"
|
||||
|
||||
static char filenm[FILENAME_MAX];
|
||||
|
||||
@ -19,11 +19,12 @@
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h> // signal
|
||||
#include <stdio.h>
|
||||
#include <string.h> // strdup
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "grasshopper.h"
|
||||
#include "improc.h"
|
||||
#include "pusirobo.h"
|
||||
@ -112,8 +113,8 @@ int main(int argc, char *argv[]){
|
||||
if(GP->throwpart < 0. || GP->throwpart > 0.99){
|
||||
ERRX("Fraction of black pixels should be in [0., 0.99]");
|
||||
}
|
||||
if(GP->Naveraging < 2 || GP->Naveraging > MAX_AVERAGING_ARRAY_SIZE)
|
||||
ERRX("Averaging amount should be from 2 to 25");
|
||||
if(GP->Naveraging < 1 || GP->Naveraging > NAVER_MAX)
|
||||
ERRX("Averaging amount should be from 1 to %d", NAVER_MAX);
|
||||
tp = chk_inp(GP->inputname);
|
||||
if(tp == T_WRONG) ERRX("Enter correct image file or directory name");
|
||||
// check ability of saving file
|
||||
@ -183,7 +184,7 @@ int main(int argc, char *argv[]){
|
||||
setpostprocess(GP->processing);
|
||||
check4running(self, GP->pidfile);
|
||||
DBG("%s started, snippets library version is %s\n", self, sl_libversion());
|
||||
free(self);
|
||||
free(self); self = NULL;
|
||||
signal(SIGTERM, signals); // kill (-15) - quit
|
||||
signal(SIGHUP, SIG_IGN); // hup - ignore
|
||||
signal(SIGINT, signals); // ctrl+C - quit
|
||||
|
||||
129
LocCorr/median.c
129
LocCorr/median.c
@ -26,9 +26,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "imagefile.h"
|
||||
#include "median.h"
|
||||
|
||||
@ -36,8 +36,13 @@
|
||||
#define ELEM_SWAP(a, b) {register Imtype t = a; a = b; b = t;}
|
||||
#define PIX_SORT(a, b) {if (p[a] > p[b]) ELEM_SWAP(p[a], p[b]);}
|
||||
|
||||
static inline Imtype mean(Imtype a, Imtype b){
|
||||
register uint16_t x = ((uint16_t)a + (uint16_t)b) / 2;
|
||||
return (Imtype)x;
|
||||
}
|
||||
|
||||
static Imtype opt_med2(Imtype *p){
|
||||
return (p[0] + p[1]) * 0.5;
|
||||
return mean(p[0], p[1]);
|
||||
}
|
||||
static Imtype opt_med3(Imtype *p){
|
||||
PIX_SORT(0, 1); PIX_SORT(1, 2); PIX_SORT(0, 1);
|
||||
@ -46,7 +51,7 @@ static Imtype opt_med3(Imtype *p){
|
||||
static Imtype opt_med4(Imtype *p){
|
||||
PIX_SORT(0, 2); PIX_SORT(1, 3);
|
||||
PIX_SORT(0, 1); PIX_SORT(2, 3);
|
||||
return(p[1] + p[2]) * 0.5;
|
||||
return mean(p[1], p[2]);
|
||||
}
|
||||
static Imtype opt_med5(Imtype *p){
|
||||
PIX_SORT(0, 1); PIX_SORT(3, 4); PIX_SORT(0, 3);
|
||||
@ -61,7 +66,7 @@ static Imtype opt_med6(Imtype *p){
|
||||
PIX_SORT(1, 2); PIX_SORT(3, 4);
|
||||
PIX_SORT(0, 1); PIX_SORT(2, 3); PIX_SORT(4, 5);
|
||||
PIX_SORT(1, 2); PIX_SORT(3, 4);
|
||||
return ( p[2] + p[3] ) * 0.5;
|
||||
return mean(p[2], p[3]);
|
||||
}
|
||||
static Imtype opt_med7(Imtype *p){
|
||||
PIX_SORT(0, 5); PIX_SORT(0, 3); PIX_SORT(1, 6);
|
||||
@ -78,7 +83,7 @@ static Imtype opt_med8(Imtype *p){
|
||||
PIX_SORT(3, 5); PIX_SORT(0, 1); PIX_SORT(2, 3);
|
||||
PIX_SORT(4, 5); PIX_SORT(6, 7); PIX_SORT(1, 4);
|
||||
PIX_SORT(3, 6);
|
||||
return(p[3] + p[4]) * 0.5;
|
||||
return mean(p[3], p[4]);
|
||||
}
|
||||
static Imtype opt_med9(Imtype *p){
|
||||
PIX_SORT(1, 2); PIX_SORT(4, 5); PIX_SORT(7, 8);
|
||||
@ -103,7 +108,7 @@ static Imtype opt_med16(Imtype *p){
|
||||
PIX_SORT(4, 5); PIX_SORT(6, 7); PIX_SORT(8, 9); PIX_SORT(10, 11);
|
||||
PIX_SORT(12, 13); PIX_SORT(14, 15); PIX_SORT(1, 8); PIX_SORT(3, 10);
|
||||
PIX_SORT(5, 12); PIX_SORT(7, 14); PIX_SORT(5, 8); PIX_SORT(7, 10);
|
||||
return (p[7] + p[8]) * 0.5;
|
||||
return mean(p[7], p[8]);
|
||||
}
|
||||
static Imtype opt_med25(Imtype *p){
|
||||
PIX_SORT(0, 1) ; PIX_SORT(3, 4) ; PIX_SORT(2, 4) ;
|
||||
@ -201,7 +206,7 @@ Imtype calc_median(Imtype *idata, int n){
|
||||
const medfunc fnarr[] = {opt_med2, opt_med3, opt_med4, opt_med5, opt_med6,
|
||||
opt_med7, opt_med8, opt_med9};
|
||||
if(n == 1) return *idata;
|
||||
if(n < 10) fn = fnarr[n - 1];
|
||||
if(n < 10) fn = fnarr[n - 2];
|
||||
else if(n == 16) fn = opt_med16;
|
||||
else if(n == 25) fn = opt_med25;
|
||||
if(fn){
|
||||
@ -229,12 +234,12 @@ typedef struct Mediator_t{
|
||||
#define maxCt(m) (((m)->ct)/2) //count of Imtypes in maxheap
|
||||
|
||||
//returns 1 if heap[i] < heap[j]
|
||||
inline int mmless(Mediator* m, int i, int j){
|
||||
static inline int mmless(Mediator* m, int i, int j){
|
||||
return ImtypeLess(m->data[m->heap[i]],m->data[m->heap[j]]);
|
||||
}
|
||||
|
||||
//swaps Imtypes i&j in heap, maintains indexes
|
||||
inline int mmexchange(Mediator* m, int i, int j){
|
||||
static inline int mmexchange(Mediator* m, int i, int j){
|
||||
int t = m->heap[i];
|
||||
m->heap[i] = m->heap[j];
|
||||
m->heap[j] = t;
|
||||
@ -244,12 +249,12 @@ inline int mmexchange(Mediator* m, int i, int j){
|
||||
}
|
||||
|
||||
//swaps Imtypes i&j if i<j; returns true if swapped
|
||||
inline int mmCmpExch(Mediator* m, int i, int j){
|
||||
static inline int mmCmpExch(Mediator* m, int i, int j){
|
||||
return (mmless(m,i,j) && mmexchange(m,i,j));
|
||||
}
|
||||
|
||||
//maintains minheap property for all Imtypes below i/2.
|
||||
void minSortDown(Mediator* m, int i){
|
||||
static inline void minSortDown(Mediator* m, int i){
|
||||
for(; i <= minCt(m); i*=2){
|
||||
if(i>1 && i < minCt(m) && mmless(m, i+1, i)) ++i;
|
||||
if(!mmCmpExch(m,i,i/2)) break;
|
||||
@ -257,7 +262,7 @@ void minSortDown(Mediator* m, int i){
|
||||
}
|
||||
|
||||
//maintains maxheap property for all Imtypes below i/2. (negative indexes)
|
||||
void maxSortDown(Mediator* m, int i){
|
||||
static inline void maxSortDown(Mediator* m, int i){
|
||||
for(; i >= -maxCt(m); i*=2){
|
||||
if(i<-1 && i > -maxCt(m) && mmless(m, i, i-1)) --i;
|
||||
if(!mmCmpExch(m,i/2,i)) break;
|
||||
@ -266,14 +271,14 @@ void maxSortDown(Mediator* m, int i){
|
||||
|
||||
//maintains minheap property for all Imtypes above i, including median
|
||||
//returns true if median changed
|
||||
int minSortUp(Mediator* m, int i){
|
||||
static inline int minSortUp(Mediator* m, int i){
|
||||
while (i > 0 && mmCmpExch(m, i, i/2)) i /= 2;
|
||||
return (i == 0);
|
||||
}
|
||||
|
||||
//maintains maxheap property for all Imtypes above i, including median
|
||||
//returns true if median changed
|
||||
int maxSortUp(Mediator* m, int i){
|
||||
static inline int maxSortUp(Mediator* m, int i){
|
||||
while (i < 0 && mmCmpExch(m, i/2, i)) i /= 2;
|
||||
return (i == 0);
|
||||
}
|
||||
@ -282,7 +287,7 @@ int maxSortUp(Mediator* m, int i){
|
||||
|
||||
//creates new Mediator: to calculate `nImtypes` running median.
|
||||
//mallocs single block of memory, caller must free.
|
||||
Mediator* MediatorNew(int nImtypes){
|
||||
static Mediator* MediatorNew(int nImtypes){
|
||||
int size = sizeof(Mediator) + nImtypes*(sizeof(Imtype)+sizeof(int)*2);
|
||||
Mediator* m = malloc(size);
|
||||
m->data = (Imtype*)(m + 1);
|
||||
@ -298,7 +303,7 @@ Mediator* MediatorNew(int nImtypes){
|
||||
}
|
||||
|
||||
//Inserts Imtype, maintains median in O(lg nImtypes)
|
||||
void MediatorInsert(Mediator* m, Imtype v){
|
||||
static void MediatorInsert(Mediator* m, Imtype v){
|
||||
int isNew=(m->ct<m->N);
|
||||
int p = m->pos[m->idx];
|
||||
Imtype old = m->data[m->idx];
|
||||
@ -318,14 +323,15 @@ void MediatorInsert(Mediator* m, Imtype v){
|
||||
}
|
||||
|
||||
//returns median Imtype (or average of 2 when Imtype count is even)
|
||||
Imtype MediatorMedian(Mediator* m){
|
||||
static Imtype MediatorMedian(Mediator* m){
|
||||
Imtype v = m->data[m->heap[0]];
|
||||
if ((m->ct&1) == 0) v = ImtypeMean(v, m->data[m->heap[-1]]);
|
||||
return v;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// median + min/max
|
||||
Imtype MediatorStat(Mediator* m, Imtype *minval, Imtype *maxval){
|
||||
static Imtype MediatorStat(Mediator* m, Imtype *minval, Imtype *maxval){
|
||||
Imtype v = m->data[m->heap[0]];
|
||||
if ((m->ct&1) == 0) v = ImtypeMean(v, m->data[m->heap[-1]]);
|
||||
Imtype min = v, max = v;
|
||||
@ -342,6 +348,7 @@ Imtype MediatorStat(Mediator* m, Imtype *minval, Imtype *maxval){
|
||||
*maxval = max;
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* filter image by median (seed*2 + 1) x (seed*2 + 1)
|
||||
@ -374,7 +381,7 @@ Image *get_median(const Image *img, int seed){
|
||||
MediatorInsert(m, inputima[xx]);
|
||||
med[medidx] = MediatorMedian(m);
|
||||
}
|
||||
FREE(m);
|
||||
free(m);
|
||||
}
|
||||
Image_minmax(out);
|
||||
DBG("time for median filtering %zdx%zd of image %zdx%zd: %gs", blksz, blksz, w, h,
|
||||
@ -407,12 +414,12 @@ int get_stat(const Image *in, int seed, Image **mean, Image **std){
|
||||
Imtype *om = (M) ? &M->data[startidx] : NULL;
|
||||
Imtype *os = (S) ? &S->data[startidx] : NULL;
|
||||
for(int x = seed; x < xmax; ++x){
|
||||
Imtype sum = 0, sum2 = 0;
|
||||
double sum = 0, sum2 = 0;
|
||||
int yb = y + seed + 1, xm = x - seed;
|
||||
for(int yy = y - seed; yy < yb; ++yy){
|
||||
Imtype *ptr = &in->data[yy * w + xm];
|
||||
for(int xx = 0; xx < hsz; ++xx){
|
||||
Imtype d = *ptr++;
|
||||
double d = *ptr++;
|
||||
sum += d;
|
||||
sum2 += d*d;
|
||||
}
|
||||
@ -420,10 +427,10 @@ int get_stat(const Image *in, int seed, Image **mean, Image **std){
|
||||
//DBG("sum=%g, sum2=%g, sz=%d", sum, sum2, sz);
|
||||
sum /= sz;
|
||||
if(om){
|
||||
*om++ = sum;
|
||||
*om++ = (Imtype)sum;
|
||||
//DBG("mean (%d, %d): %g", x, y, sum);
|
||||
}
|
||||
if(os) *os++ = sqrt(sum2/sz - sum*sum);
|
||||
if(os) *os++ = (Imtype)sqrt(sum2/sz - sum*sum);
|
||||
}
|
||||
}
|
||||
if(mean){
|
||||
@ -437,79 +444,3 @@ int get_stat(const Image *in, int seed, Image **mean, Image **std){
|
||||
DBG("time for mean/sigma computation: %gs", dtime() - t0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calc_background - Simple background calculation by histogram
|
||||
* @param img (i) - input image (here will be modified its top2proc field)
|
||||
* @param bk (o) - background value
|
||||
* @return 0 if error
|
||||
*/
|
||||
int calc_background(Image *img, Imtype *bk){
|
||||
//DBG("image: min=%g, max=%g", img->minval, img->maxval);
|
||||
if(!img || !bk) return FALSE;
|
||||
if(img->maxval - img->minval < DBL_EPSILON){
|
||||
WARNX("Zero or overilluminated image!");
|
||||
return FALSE;
|
||||
}
|
||||
if(theconf.fixedbkg){
|
||||
*bk = theconf.fixedbkg;
|
||||
return TRUE;
|
||||
}
|
||||
int w = img->width, h = img->height, wh = w*h;
|
||||
Imtype min = img->minval, ampl = img->maxval - min;
|
||||
int histogram[256] = {0};
|
||||
DBG("min: %g, max: %g, ampl: %g", min, img->maxval, ampl);
|
||||
#pragma omp parallel
|
||||
{
|
||||
int histogram_private[256] = {0};
|
||||
#pragma omp for nowait
|
||||
for(int i = 0; i < wh; ++i){
|
||||
int newval = (int)((((img->data[i]) - min)/ampl)*255. + 0.5);
|
||||
++histogram_private[newval];
|
||||
}
|
||||
#pragma omp critical
|
||||
{
|
||||
for(int i=0; i<256; ++i) histogram[i] += histogram_private[i];
|
||||
}
|
||||
}
|
||||
int modeidx = 0, modeval = 0;
|
||||
for(int i = 0; i < 256; ++i)
|
||||
if(modeval < histogram[i]){
|
||||
modeval = histogram[i];
|
||||
modeidx = i;
|
||||
}
|
||||
//DBG("Mode=%g @ idx%d (N=%d)", ((Imtype)modeidx / 255.)*ampl, modeidx, modeval);
|
||||
int diff2[256] = {0};
|
||||
for(int i = 2; i < 254; ++i) diff2[i] = (histogram[i+2]+histogram[i-2]-2*histogram[i])/4;
|
||||
if(modeidx < 2) modeidx = 2;
|
||||
if(modeidx > 253){
|
||||
WARNX("Overilluminated image");
|
||||
return FALSE; // very bad image: overilluminated
|
||||
}
|
||||
int borderidx = modeidx;
|
||||
// green("2\n");
|
||||
for(int i = modeidx; i < 254; ++i){ // search bend-point by second derivate
|
||||
// printf("%d: %d, %d\n", i, diff2[i], diff2[i+1]);
|
||||
if(diff2[i] <= 0 && diff2[i+1] <=0){
|
||||
borderidx = i; break;
|
||||
}
|
||||
}
|
||||
//DBG("borderidx=%d -> %d", borderidx, (borderidx+modeidx)/2);
|
||||
//borderidx = (borderidx + modeidx) / 2;
|
||||
Imtype borderval = ((Imtype)borderidx / 255.)*ampl + min;
|
||||
if(bk) *bk = borderval;
|
||||
//green("HISTO:\n");
|
||||
//for(int i = 0; i < 256; ++i) printf("%d:\t%d\t%d\n", i, histogram[i], diff2[i]);
|
||||
// calculate values of upper 2% border
|
||||
#if 0
|
||||
Image *out = Image_sim(img);
|
||||
//DBG("found border: %g @ %d", borderval, borderidx);
|
||||
OMP_FOR()
|
||||
for(int i = 0; i < wh; ++i){
|
||||
register Imtype val = img->data[i];
|
||||
if(val > borderval) out->data[i] = val - borderval;
|
||||
}
|
||||
Image_minmax(out);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -27,6 +27,5 @@
|
||||
Imtype calc_median(Imtype *idata, int n);
|
||||
Image *get_median(const Image *img, int seed);
|
||||
int get_stat(const Image *in, int seed, Image **mean, Image **std);
|
||||
int calc_background(Image *img, Imtype *bk);
|
||||
|
||||
#endif // __MEDIAN_H__
|
||||
|
||||
@ -26,9 +26,9 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "improc.h" // global variable stopwork
|
||||
#include "pusirobo.h"
|
||||
#include "socket.h"
|
||||
@ -327,7 +327,7 @@ static int chkRelay(){
|
||||
relay = r;
|
||||
ret = TRUE;
|
||||
rtn:
|
||||
FREE(ans);
|
||||
free(ans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -357,7 +357,7 @@ static int setSpeed(const char *mesg, const char *name){
|
||||
LOGERR("no %s motor", name);
|
||||
retval = FALSE;
|
||||
}
|
||||
FREE(ans);
|
||||
if(ans) free(ans);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -403,11 +403,11 @@ static int pusi_connect_server(){
|
||||
send_message_nocheck(registerVaxe);
|
||||
send_message_nocheck(registerFocus);
|
||||
send_message_nocheck(registerRelay);
|
||||
int retval = TRUE;
|
||||
if(!chkRelay()) retval = FALSE;
|
||||
if(!setSpeed(setUspeed, "U")) retval = FALSE;
|
||||
if(!setSpeed(setVspeed, "V")) retval = FALSE;
|
||||
if(!setSpeed(setFspeed, "F")) retval = FALSE;
|
||||
int retval = FALSE;
|
||||
if(chkRelay()) retval = TRUE;
|
||||
if(setSpeed(setUspeed, "U")) retval = TRUE;
|
||||
if(setSpeed(setVspeed, "V")) retval = TRUE;
|
||||
if(setSpeed(setFspeed, "F")) retval = TRUE;
|
||||
if(!retval) pusi_disconnect();
|
||||
else{
|
||||
state = PUSI_RELAX;
|
||||
@ -460,7 +460,7 @@ static int moving_finished(const char *mesgstatus, volatile atomic_int *position
|
||||
LOGDBG("%s not found in '%s'", CURPOSstatus, ans);
|
||||
}
|
||||
}
|
||||
FREE(ans);
|
||||
if(ans) free(ans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -483,7 +483,7 @@ static int move_motor(const char *movecmd, int s){
|
||||
LOGWARN("NO OK in %s", ans);
|
||||
ret = FALSE;
|
||||
}
|
||||
FREE(ans);
|
||||
if(ans) free(ans);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -968,6 +968,7 @@ static char *Umove(const char *val, char *buf, int buflen){
|
||||
int Unfixed = Uposition + d + Fposition;
|
||||
if(Unfixed > theconf.maxUsteps || Unfixed < -theconf.maxUsteps){
|
||||
snprintf(buf, buflen, FAIL);
|
||||
return buf;
|
||||
}
|
||||
dUmove = d;
|
||||
snprintf(buf, buflen, OK);
|
||||
@ -978,6 +979,7 @@ static char *Vmove(const char *val, char *buf, int buflen){
|
||||
int Vnfixed = Vposition + d + Fposition;
|
||||
if(Vnfixed > theconf.maxVsteps || Vnfixed < -theconf.maxVsteps){
|
||||
snprintf(buf, buflen, FAIL);
|
||||
return buf;
|
||||
}
|
||||
dVmove = d;
|
||||
snprintf(buf, buflen, OK);
|
||||
@ -1009,7 +1011,7 @@ static char *relaycmd(const char *val, char *buf, int buflen){
|
||||
}
|
||||
}
|
||||
}
|
||||
FREE(par);
|
||||
free(par);
|
||||
snprintf(buf, buflen, "%s", ans);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@ -29,10 +29,10 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syscall.h> // syscall
|
||||
#include <unistd.h> // daemon
|
||||
#include <usefull_macros.h>
|
||||
|
||||
#include "cmdlnopts.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "improc.h"
|
||||
#include "socket.h"
|
||||
|
||||
@ -140,7 +140,7 @@ static char *moveU(const char *val, char *buf, int buflen){
|
||||
return retFAIL(buf, buflen);
|
||||
}
|
||||
static char *moveV(const char *val, char *buf, int buflen){
|
||||
if(theSteppers && theSteppers->moveByV) return theSteppers->moveByU(val, buf, buflen);
|
||||
if(theSteppers && theSteppers->moveByV) return theSteppers->moveByV(val, buf, buflen);
|
||||
return retFAIL(buf, buflen);
|
||||
}
|
||||
static char *relaycmd(const char *val, char *buf, int buflen){
|
||||
@ -171,7 +171,7 @@ static char *processCommand(const char msg[BUFLEN], char *ans, int anslen){
|
||||
DBG("got KEY '%s' with value '%s'", kv, value);
|
||||
key_value result;
|
||||
par = chk_keyval(kv, value, &result);
|
||||
FREE(kv);
|
||||
free(kv); kv = NULL;
|
||||
if(par){
|
||||
switch(par->type){
|
||||
case PAR_INT:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user