mirror of
https://github.com/eddyem/astrovideoguide_v3.git
synced 2025-12-06 10:45:10 +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(MAJOR_VERSION "0")
|
||||||
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||||
|
|
||||||
project(${PROJ} VERSION ${PROJ_VERSION} LANGUAGES C)
|
project(${PROJ} VERSION ${VERSION} LANGUAGES C)
|
||||||
|
|
||||||
# default flags
|
# default flags
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -std=gnu99 -march=native -fdata-sections -ffunction-sections")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
|
||||||
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections")
|
|
||||||
|
|
||||||
set(CMAKE_COLOR_MAKEFILE ON)
|
set(CMAKE_COLOR_MAKEFILE ON)
|
||||||
|
|
||||||
@ -20,10 +19,12 @@ set(CMAKE_VERBOSE_MAKEFILE "ON")
|
|||||||
|
|
||||||
# cmake -DEBUG=1 -> debugging
|
# cmake -DEBUG=1 -> debugging
|
||||||
if(DEFINED EBUG AND EBUG EQUAL 1)
|
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)
|
set(CMAKE_BUILD_TYPE DEBUG)
|
||||||
add_definitions(-DEBUG)
|
add_definitions(-DEBUG)
|
||||||
else()
|
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)
|
set(CMAKE_BUILD_TYPE RELEASE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ link_directories(${${PROJ}_LIBRARY_DIRS} ${FLYCAP_LIBRARY_DIRS} ${BASLER_LIBRARY
|
|||||||
add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\"
|
add_definitions(${CFLAGS} -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_VESION}\" -DTHREAD_NUMBER=${PROCESSOR_COUNT})
|
-DMAJOR_VERSION=\"${MAJOR_VERSION}\" -DTHREAD_NUMBER=${PROCESSOR_COUNT})
|
||||||
|
|
||||||
# -l
|
# -l
|
||||||
target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES} ${FLYCAP_LIBRARIES} ${BASLER_LIBRARIES} -lm)
|
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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <usefull_macros.h>
|
|
||||||
#include <pylonc/PylonC.h>
|
#include <pylonc/PylonC.h>
|
||||||
|
|
||||||
#include "basler.h"
|
#include "basler.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "imagefile.h"
|
#include "imagefile.h"
|
||||||
|
|
||||||
static PYLON_DEVICE_HANDLE hDev;
|
static PYLON_DEVICE_HANDLE hDev;
|
||||||
@ -74,7 +74,6 @@ static void disconnect(){
|
|||||||
isopened = FALSE;
|
isopened = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get node & check it for read/write
|
|
||||||
/**
|
/**
|
||||||
* @brief chkNode - get node & check it for read/write
|
* @brief chkNode - get node & check it for read/write
|
||||||
* @param phNode (io) - pointer to node
|
* @param phNode (io) - pointer to node
|
||||||
@ -144,6 +143,7 @@ static int setBoolean(char *featureName, _Bool val){
|
|||||||
NODE_HANDLE hNode;
|
NODE_HANDLE hNode;
|
||||||
if(!chkNode(&hNode, featureName, BooleanNode, TRUE)) return FALSE;
|
if(!chkNode(&hNode, featureName, BooleanNode, TRUE)) return FALSE;
|
||||||
PYLONFN(GenApiBooleanSetValue, hNode, val);
|
PYLONFN(GenApiBooleanSetValue, hNode, val);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
static int setInt(char *featureName, int64_t val){
|
static int setInt(char *featureName, int64_t val){
|
||||||
if(!isopened || !featureName) return FALSE;
|
if(!isopened || !featureName) return FALSE;
|
||||||
@ -222,6 +222,7 @@ static Image *capture(){
|
|||||||
float_values f;
|
float_values f;
|
||||||
if(!getFloat("DeviceTemperature", &f)) WARNX("Can't get temperature");
|
if(!getFloat("DeviceTemperature", &f)) WARNX("Can't get temperature");
|
||||||
else{
|
else{
|
||||||
|
LOGDBG("Basler temperature: %.1f", f.val);
|
||||||
DBG("Temperature: %.1f", f.val);
|
DBG("Temperature: %.1f", f.val);
|
||||||
if(f.val > 80.){
|
if(f.val > 80.){
|
||||||
WARNX("Device too hot");
|
WARNX("Device too hot");
|
||||||
@ -230,7 +231,7 @@ static Image *capture(){
|
|||||||
toohot = TRUE;
|
toohot = TRUE;
|
||||||
}
|
}
|
||||||
}else if(toohot && f.val < 75.){
|
}else if(toohot && f.val < 75.){
|
||||||
LOGMSG("Device temperature is normal");
|
LOGDBG("Device temperature is normal");
|
||||||
toohot = FALSE;
|
toohot = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,8 +24,9 @@
|
|||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
#include "binmorph.h"
|
#include "binmorph.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "imagefile.h"
|
#include "imagefile.h"
|
||||||
|
|
||||||
// global arrays for erosion/dilation masks
|
// 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);
|
uint8_t *ret = MALLOC(uint8_t, W*H);
|
||||||
int W0 = (W + 7) / 8; // width in bytes
|
int W0 = (W + 7) / 8; // width in bytes
|
||||||
int w = W0-1, h = H-1;
|
int w = W0-1, h = H-1;
|
||||||
{int y = 0;
|
{
|
||||||
// top of image, y = 0
|
// top of image, y = 0
|
||||||
#define IM_UP
|
#define IM_UP
|
||||||
#include "fc_filter.h"
|
#include "fc_filter.h"
|
||||||
@ -79,7 +80,6 @@ uint8_t *filter4(uint8_t *image, int W, int H){
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
// image bottom, y = h
|
// image bottom, y = h
|
||||||
int y = h;
|
|
||||||
#define IM_DOWN
|
#define IM_DOWN
|
||||||
#include "fc_filter.h"
|
#include "fc_filter.h"
|
||||||
#undef IM_DOWN
|
#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);
|
uint8_t *ret = MALLOC(uint8_t, W*H);
|
||||||
int W0 = (W + 7) / 8; // width in bytes
|
int W0 = (W + 7) / 8; // width in bytes
|
||||||
int w = W0-1, h = H-1;
|
int w = W0-1, h = H-1;
|
||||||
{int y = 0;
|
{
|
||||||
#define IM_UP
|
#define IM_UP
|
||||||
#include "ec_filter.h"
|
#include "ec_filter.h"
|
||||||
#undef IM_UP
|
#undef IM_UP
|
||||||
@ -108,7 +108,6 @@ uint8_t *filter8(uint8_t *image, int W, int H){
|
|||||||
#include "ec_filter.h"
|
#include "ec_filter.h"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int y = h;
|
|
||||||
#define IM_DOWN
|
#define IM_DOWN
|
||||||
#include "ec_filter.h"
|
#include "ec_filter.h"
|
||||||
#undef IM_DOWN
|
#undef IM_DOWN
|
||||||
@ -130,7 +129,7 @@ uint8_t *dilation(uint8_t *image, int W, int H){
|
|||||||
uint8_t lastmask = ~(1<<rest);
|
uint8_t lastmask = ~(1<<rest);
|
||||||
if(!DIL) morph_init();
|
if(!DIL) morph_init();
|
||||||
uint8_t *ret = MALLOC(uint8_t, W0*H);
|
uint8_t *ret = MALLOC(uint8_t, W0*H);
|
||||||
{int y = 0;
|
{
|
||||||
// top of image, y = 0
|
// top of image, y = 0
|
||||||
#define IM_UP
|
#define IM_UP
|
||||||
#include "dilation.h"
|
#include "dilation.h"
|
||||||
@ -140,7 +139,7 @@ uint8_t *dilation(uint8_t *image, int W, int H){
|
|||||||
// mid of image, y = 1..h-1
|
// mid of image, y = 1..h-1
|
||||||
#include "dilation.h"
|
#include "dilation.h"
|
||||||
}
|
}
|
||||||
{int y = h;
|
{
|
||||||
// image bottom, y = h
|
// image bottom, y = h
|
||||||
#define IM_DOWN
|
#define IM_DOWN
|
||||||
#include "dilation.h"
|
#include "dilation.h"
|
||||||
@ -329,6 +328,23 @@ uint8_t *substim(uint8_t *im1, uint8_t *im2, int W, int H){
|
|||||||
#define TEST(...)
|
#define TEST(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// check table and rename all "oldval" into "newval"
|
||||||
|
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);
|
||||||
|
do{oldval = assoc[oldval];}while(assoc[oldval] != oldval);
|
||||||
|
TEST("\trealnew = %zd, realold=%zd ", newval, oldval);
|
||||||
|
// now change larger value to smaller
|
||||||
|
if(newval > oldval){
|
||||||
|
assoc[newval] = oldval;
|
||||||
|
TEST("change %zd to %zd\n", newval, oldval);
|
||||||
|
}else{
|
||||||
|
assoc[oldval] = newval;
|
||||||
|
TEST("change %zd to %zd\n", oldval, newval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* label 4-connected components on image
|
* label 4-connected components on image
|
||||||
* (slow algorythm, but easy to parallel)
|
* (slow algorythm, but easy to parallel)
|
||||||
@ -340,22 +356,6 @@ uint8_t *substim(uint8_t *im1, uint8_t *im2, int W, int H){
|
|||||||
*/
|
*/
|
||||||
size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC){
|
size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC){
|
||||||
size_t *assoc;
|
size_t *assoc;
|
||||||
// check table and rename all "oldval" into "newval"
|
|
||||||
inline void remark(size_t newval, size_t oldval){
|
|
||||||
TEST("\tnew = %zd, old=%zd; ", newval, oldval);
|
|
||||||
// find the least values
|
|
||||||
do{newval = assoc[newval];}while(assoc[newval] != newval);
|
|
||||||
do{oldval = assoc[oldval];}while(assoc[oldval] != oldval);
|
|
||||||
TEST("\trealnew = %zd, realold=%zd ", newval, oldval);
|
|
||||||
// now change larger value to smaller
|
|
||||||
if(newval > oldval){
|
|
||||||
assoc[newval] = oldval;
|
|
||||||
TEST("change %zd to %zd\n", newval, oldval);
|
|
||||||
}else{
|
|
||||||
assoc[oldval] = newval;
|
|
||||||
TEST("change %zd to %zd\n", oldval, newval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(W < MINWIDTH || H < MINHEIGHT) return NULL;
|
if(W < MINWIDTH || H < MINHEIGHT) return NULL;
|
||||||
uint8_t *f = filter4(Img, W, H); // remove all non 4-connected pixels
|
uint8_t *f = filter4(Img, W, H); // remove all non 4-connected pixels
|
||||||
//DBG("convert to size_t");
|
//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(found){ // there's a pixel to the left
|
||||||
if(U && U != curmark){ // meet old mark -> remark one of them in assoc[]
|
if(U && U != curmark){ // meet old mark -> remark one of them in assoc[]
|
||||||
TEST("(%d, %d): remark %zd --> %zd\n", x, y, U, curmark);
|
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)
|
curmark = U; // change curmark to upper mark (to reduce further checks)
|
||||||
}
|
}
|
||||||
}else{ // new mark -> change curmark
|
}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].xmin = W;
|
||||||
boxes[i].ymin = H;
|
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)
|
#pragma omp parallel shared(boxes)
|
||||||
{
|
{
|
||||||
Box *l_boxes = MALLOC(Box, cidx);
|
Box *l_boxes = MALLOC(Box, cidx);
|
||||||
@ -507,60 +490,6 @@ size_t *cclabel8(size_t *labels, int W, int H, size_t *Nobj){
|
|||||||
}
|
}
|
||||||
#endif
|
#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 ===================
|
* <=================== 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);
|
uint8_t *filter8(uint8_t *image, int W, int H);
|
||||||
|
|
||||||
size_t *cclabel4(uint8_t *Img, int W, int H, ConnComps **CC);
|
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
|
#if 0
|
||||||
|
size_t *cclabel8(uint8_t *Img, int W, int H, size_t *Nobj);
|
||||||
// logical operations
|
// logical operations
|
||||||
uint8_t *imand(uint8_t *im1, uint8_t *im2, int W, int H);
|
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);
|
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
|
||||||
|
|
||||||
#endif // BINMORPH_H__
|
#endif // BINMORPH_H__
|
||||||
|
|||||||
@ -20,10 +20,10 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "fits.h"
|
#include "fits.h"
|
||||||
#include "grasshopper.h"
|
#include "grasshopper.h"
|
||||||
#include "imagefile.h"
|
#include "imagefile.h"
|
||||||
@ -132,31 +132,19 @@ static void recalcexp(Image *I){
|
|||||||
exptime = theconf.maxexp;
|
exptime = theconf.maxexp;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(I->minval < 0. || I->maxval > 255.1){
|
size_t *histogram = get_histogram(I);
|
||||||
DBG("Bad image data: min=%g, max=%g", I->minval, I->maxval);
|
if(!histogram){
|
||||||
|
WARNX("Can't calculate histogram");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int wh = I->width * I->height;
|
int idx100;
|
||||||
int histogram[256] = {0};
|
size_t sum100 = 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;
|
|
||||||
for(idx100 = 255; idx100 >= 0; --idx100){
|
for(idx100 = 255; idx100 >= 0; --idx100){
|
||||||
sum100 += histogram[idx100];
|
sum100 += histogram[idx100];
|
||||||
if(sum100 > 100) break;
|
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 > 230 && idx100 < 253) return; // good values
|
||||||
if(idx100 > 253){ // exposure too long
|
if(idx100 > 253){ // exposure too long
|
||||||
calcexpgain(0.7*exptime);
|
calcexpgain(0.7*exptime);
|
||||||
@ -248,13 +236,25 @@ int camcapture(void (*process)(Image*)){
|
|||||||
FREE(oIma->data);
|
FREE(oIma->data);
|
||||||
FREE(oIma);
|
FREE(oIma);
|
||||||
}
|
}
|
||||||
|
if(oIma){
|
||||||
|
FREE(oIma->data);
|
||||||
|
FREE(oIma);
|
||||||
|
}
|
||||||
camdisconnect();
|
camdisconnect();
|
||||||
DBG("CAMCAPTURE: out");
|
DBG("CAMCAPTURE: out");
|
||||||
return 1;
|
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){
|
char *camstatus(const char *messageid, char *buf, int buflen){
|
||||||
|
if(!buf || buflen < 2) return NULL;
|
||||||
|
if(!messageid) messageid = "unknown";
|
||||||
static char *impath = NULL;
|
static char *impath = NULL;
|
||||||
if(!impath){
|
if(!impath){
|
||||||
if(!(impath = realpath(GP->outputjpg, impath))){
|
if(!(impath = realpath(GP->outputjpg, impath))){
|
||||||
@ -263,9 +263,13 @@ char *camstatus(const char *messageid, char *buf, int buflen){
|
|||||||
}
|
}
|
||||||
DBG("path: %s", impath);
|
DBG("path: %s", impath);
|
||||||
}
|
}
|
||||||
|
float 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, \"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(),
|
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;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,11 +15,12 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifndef CAMERACAPTURE_H__
|
#ifndef CAMERACAPTURE_H__
|
||||||
#define CAMERACAPTURE_H__
|
#define CAMERACAPTURE_H__
|
||||||
#include "fits.h" // Image*
|
|
||||||
|
#include "imagefile.h" // Image
|
||||||
|
|
||||||
|
|
||||||
// format of single frame
|
// format of single frame
|
||||||
typedef struct{
|
typedef struct{
|
||||||
|
|||||||
@ -23,10 +23,10 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "improc.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)")},
|
{"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 ")")},
|
{"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)")},
|
{"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")},
|
{"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.)")},
|
// {"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")},
|
{"equalize", NO_ARGS, NULL, 'e', arg_int, APTR(&G.equalize), _("make historam equalization of saved jpeg")},
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
static char *conffile = NULL; // configuration file name
|
static char *conffile = NULL; // configuration file name
|
||||||
|
|
||||||
@ -192,12 +192,12 @@ static char *read_key(FILE *file, char value[128]){
|
|||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
int got = getline(&line, &n, file);
|
int got = getline(&line, &n, file);
|
||||||
|
if(!line) return NULL;
|
||||||
if(got < 0){
|
if(got < 0){
|
||||||
FREE(line);
|
free(line);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
char *kv = get_keyval(line, value);
|
char *kv = get_keyval(line, value);
|
||||||
FREE(line);
|
|
||||||
return kv;
|
return kv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ confparam *chk_keyval(const char *key, const char *val, key_value *result){
|
|||||||
*/
|
*/
|
||||||
int chkconfig(const char *confname){
|
int chkconfig(const char *confname){
|
||||||
DBG("Config name: %s", confname);
|
DBG("Config name: %s", confname);
|
||||||
FREE(conffile);
|
if(conffile){ free(conffile); conffile = NULL; }
|
||||||
conffile = strdup(confname);
|
conffile = strdup(confname);
|
||||||
FILE *f = fopen(confname, "r");
|
FILE *f = fopen(confname, "r");
|
||||||
int ret = TRUE;
|
int ret = TRUE;
|
||||||
@ -283,7 +283,8 @@ int chkconfig(const char *confname){
|
|||||||
}
|
}
|
||||||
while((key = read_key(f, val))){
|
while((key = read_key(f, val))){
|
||||||
if(*key == '#'){
|
if(*key == '#'){
|
||||||
FREE(key);
|
free(key);
|
||||||
|
key = NULL;
|
||||||
continue; // comment
|
continue; // comment
|
||||||
}
|
}
|
||||||
//DBG("key: %s", key);
|
//DBG("key: %s", key);
|
||||||
@ -291,7 +292,8 @@ int chkconfig(const char *confname){
|
|||||||
par = chk_keyval(key, val, &kv);
|
par = chk_keyval(key, val, &kv);
|
||||||
if(!par){
|
if(!par){
|
||||||
WARNX("Parameter '%s' is wrong or out of range", key);
|
WARNX("Parameter '%s' is wrong or out of range", key);
|
||||||
FREE(key);
|
free(key);
|
||||||
|
key = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch(par->type){
|
switch(par->type){
|
||||||
@ -303,7 +305,8 @@ int chkconfig(const char *confname){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++par->got;
|
++par->got;
|
||||||
FREE(key);
|
free(key);
|
||||||
|
key = NULL;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
int found = 0;
|
int found = 0;
|
||||||
@ -321,34 +324,6 @@ int chkconfig(const char *confname){
|
|||||||
}
|
}
|
||||||
++found; ++par;
|
++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);
|
DBG("chkconfig(): found %d", found);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,12 +42,12 @@
|
|||||||
#define BRIGHT_MIN (0.)
|
#define BRIGHT_MIN (0.)
|
||||||
#define BRIGHT_MAX (10.)
|
#define BRIGHT_MAX (10.)
|
||||||
// max average images counter
|
// max average images counter
|
||||||
#define NAVER_MAX (50)
|
#define NAVER_MAX (25)
|
||||||
// coefficients to convert dx,dy to du,dv
|
// coefficients to convert dx,dy to du,dv
|
||||||
#define KUVMIN (-5000.)
|
#define KUVMIN (-5000.)
|
||||||
#define KUVMAX (5000.)
|
#define KUVMAX (5000.)
|
||||||
// default coefficient for corrections (move to Kdu, Kdv instead of du, dv)
|
// default coefficient for corrections (move to Kdu, Kdv instead of du, dv)
|
||||||
#define KCORR (0.97)
|
#define KCORR (0.90)
|
||||||
// min/max median seed
|
// min/max median seed
|
||||||
#define MIN_MEDIAN_SEED (1)
|
#define MIN_MEDIAN_SEED (1)
|
||||||
#define MAX_MEDIAN_SEED (7)
|
#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++)
|
for(int y = 1; y < h; y++)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef IM_UP
|
||||||
|
int y = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef IM_DOWN
|
||||||
|
int y = h;
|
||||||
|
#endif
|
||||||
uint8_t *iptr = &image[W0*y];
|
uint8_t *iptr = &image[W0*y];
|
||||||
uint8_t *optr = &ret[W0*y];
|
uint8_t *optr = &ret[W0*y];
|
||||||
uint8_t p = DIL[*iptr]
|
uint8_t p = DIL[*iptr]
|
||||||
|
|||||||
@ -16,11 +16,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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 "draw.h"
|
||||||
#include "fits.h"
|
#include "fits.h"
|
||||||
|
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
// base colors:
|
// base colors:
|
||||||
const uint8_t
|
const uint8_t
|
||||||
@ -46,13 +46,35 @@ void Pattern_free(Pattern **p){
|
|||||||
Pattern *Pattern_cross(int h, int w){
|
Pattern *Pattern_cross(int h, int w){
|
||||||
int s = h*w, hmid = h/2, wmid = w/2;
|
int s = h*w, hmid = h/2, wmid = w/2;
|
||||||
uint8_t *data = MALLOC(uint8_t, s);
|
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];
|
uint8_t *ptr = &data[wmid];
|
||||||
for(int y = 0; y < h; ++y, ptr += w) *ptr = 255;
|
for(int y = 0; y < h; ++y, ptr += w) *ptr = 255;
|
||||||
ptr = &data[hmid*w];
|
ptr = &data[hmid*w];
|
||||||
for(int x = 0; x < w; ++x, ++ptr) *ptr = 255;
|
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);
|
Pattern *p = MALLOC(Pattern, 1);
|
||||||
p->data = data;
|
p->data = data;
|
||||||
p->h = h; p->w = w;
|
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;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +85,8 @@ Pattern *Pattern_cross(int h, int w){
|
|||||||
* @param xc, yc - coordinates of pattern center @ image
|
* @param xc, yc - coordinates of pattern center @ image
|
||||||
* @param colr - color to draw pattern (when opaque == 255)
|
* @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 xul = xc - p->w/2, yul = yc - p->h/2;
|
||||||
int xdr = xul+p->w-1, ydr = yul+p->h-1;
|
int xdr = xul+p->w-1, ydr = yul+p->h-1;
|
||||||
int R = img->w, D = img->h; // right and down border coordinates + 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 *in = &p->data[(iylow+y-oylow)*p->w + ixlow]; // opaque component
|
||||||
uint8_t *out = &img->data[(y*img->w + oxlow)*3]; // 3-colours
|
uint8_t *out = &img->data[(y*img->w + oxlow)*3]; // 3-colours
|
||||||
for(int x = oxlow; x < oxhigh; ++x, ++in, out += 3){
|
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){
|
for(int c = 0; c < 3; ++c){
|
||||||
out[c] = (uint8_t)(colr[c] * opaque + out[c]*(1.-opaque));
|
out[c] = (uint8_t)(colr[c] * opaque + out[c]*(1.-opaque));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,17 +28,6 @@ typedef struct{
|
|||||||
int h; // height
|
int h; // height
|
||||||
} Img3;
|
} 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
|
// opaque pattern for drawing
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
@ -50,7 +39,8 @@ typedef struct{
|
|||||||
extern const uint8_t C_R[], C_G[], C_B[], C_K[], C_W[];
|
extern const uint8_t C_R[], C_G[], C_B[], C_K[], C_W[];
|
||||||
|
|
||||||
void Pattern_free(Pattern **p);
|
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_cross(int h, int w);
|
||||||
|
Pattern *Pattern_xcross(int h, int w);
|
||||||
|
|
||||||
#endif // DRAW_H__
|
#endif // DRAW_H__
|
||||||
|
|||||||
@ -23,6 +23,12 @@ OMP_FOR()
|
|||||||
for(int y = 1; y < h; y++)
|
for(int y = 1; y < h; y++)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef IM_UP
|
||||||
|
int y = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef IM_DOWN
|
||||||
|
int y = h;
|
||||||
|
#endif
|
||||||
uint8_t *iptr = &image[W0*y];
|
uint8_t *iptr = &image[W0*y];
|
||||||
uint8_t *optr = &ret[W0*y];
|
uint8_t *optr = &ret[W0*y];
|
||||||
// x=0
|
// x=0
|
||||||
|
|||||||
@ -23,6 +23,12 @@ OMP_FOR()
|
|||||||
for(int y = 1; y < h; y++)
|
for(int y = 1; y < h; y++)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef IM_UP
|
||||||
|
int y = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef IM_DOWN
|
||||||
|
int y = h;
|
||||||
|
#endif
|
||||||
uint8_t *iptr = &image[W0*y];
|
uint8_t *iptr = &image[W0*y];
|
||||||
uint8_t *optr = &ret[W0*y];
|
uint8_t *optr = &ret[W0*y];
|
||||||
// x=0
|
// x=0
|
||||||
|
|||||||
116
LocCorr/fits.c
116
LocCorr/fits.c
@ -18,9 +18,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
#include "fits.h"
|
#include "fits.h"
|
||||||
|
|
||||||
static int fitsstatus = 0;
|
static int fitsstatus = 0;
|
||||||
@ -56,12 +56,40 @@ void Image_free(Image **img){
|
|||||||
FREE(*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){
|
bool FITS_read(const char *filename, Image **fits){
|
||||||
FNAME();
|
FNAME();
|
||||||
bool ret = TRUE;
|
bool ret = TRUE;
|
||||||
fitsfile *fp;
|
fitsfile *fp;
|
||||||
int i, j, hdunum, hdutype, nkeys, keypos;
|
int i, j, hdunum, hdutype, nkeys, keypos;
|
||||||
int naxis;
|
int naxis, dtype;
|
||||||
long naxes[2];
|
long naxes[2];
|
||||||
char card[FLEN_CARD];
|
char card[FLEN_CARD];
|
||||||
Image *img = MALLOC(Image, 1);
|
Image *img = MALLOC(Image, 1);
|
||||||
@ -75,7 +103,7 @@ bool FITS_read(const char *filename, Image **fits){
|
|||||||
goto returning;
|
goto returning;
|
||||||
}
|
}
|
||||||
// get image dimensions
|
// 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);
|
DBG("Image have %d axis", naxis);
|
||||||
if(naxis > 2){
|
if(naxis > 2){
|
||||||
WARNX(_("Images with > 2 dimensions are not supported"));
|
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->width = naxes[0];
|
||||||
img->height = naxes[1];
|
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
|
// loop through all HDUs
|
||||||
for(i = 1; !(fits_movabs_hdu(fp, i, &hdutype, &fitsstatus)); ++i){
|
for(i = 1; !(fits_movabs_hdu(fp, i, &hdutype, &fitsstatus)); ++i){
|
||||||
TRYFITS(fits_get_hdrpos, fp, &nkeys, &keypos);
|
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];
|
size_t sz = naxes[0] * naxes[1];
|
||||||
img->data = MALLOC(Imtype, sz);
|
img->data = MALLOC(Imtype, sz);
|
||||||
|
float *targ = MALLOC(float, sz);
|
||||||
int stat = 0;
|
int stat = 0;
|
||||||
TRYFITS(fits_read_img, fp, FITSDATATYPE, 1, sz, NULL, img->data, &stat);
|
TRYFITS(fits_read_img, fp, TFLOAT, 1, sz, NULL, targ, &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);
|
|
||||||
if(stat) WARNX(_("Found %d pixels with undefined value"), stat);
|
if(stat) WARNX(_("Found %d pixels with undefined value"), stat);
|
||||||
|
convflt2ima(targ, img);
|
||||||
|
FREE(targ);
|
||||||
DBG("ready");
|
DBG("ready");
|
||||||
|
|
||||||
returning:
|
returning:
|
||||||
FITSFUN(fits_close_file, fp);
|
FITSFUN(fits_close_file, fp);
|
||||||
if(!ret){
|
if(!ret || !fits){
|
||||||
Image_free(&img);
|
Image_free(&img);
|
||||||
}
|
}else *fits = img;
|
||||||
if(fits) *fits = img;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,63 +165,8 @@ bool FITS_write(const char *filename, const Image *fits){
|
|||||||
fitsfile *fp;
|
fitsfile *fp;
|
||||||
|
|
||||||
TRYFITS(fits_create_file, &fp, filename);
|
TRYFITS(fits_create_file, &fp, filename);
|
||||||
TRYFITS(fits_create_img, fp, fits->dtype, 2, naxes);
|
TRYFITS(fits_create_img, fp, SHORT_IMG, 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");
|
|
||||||
}
|
|
||||||
if(keys){ // there's keys
|
if(keys){ // there's keys
|
||||||
size_t i;
|
size_t i;
|
||||||
char **records = fits->keylist;
|
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");
|
FITSFUN(fits_write_record, fp, "COMMENT modified by loccorr");
|
||||||
fitsstatus = 0;
|
fitsstatus = 0;
|
||||||
fits_write_img(fp, FITSDATATYPE, 1, sz, outp, &fitsstatus);
|
fits_write_img(fp, TBYTE, 1, sz, fits->data, &fitsstatus);
|
||||||
if(need2free) FREE(outp);
|
|
||||||
if(fitsstatus){
|
if(fitsstatus){
|
||||||
fits_report_error(stderr, fitsstatus);
|
fits_report_error(stderr, fitsstatus);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@ -22,31 +22,9 @@
|
|||||||
|
|
||||||
#include <fitsio.h>
|
#include <fitsio.h>
|
||||||
#include <omp.h>
|
#include <omp.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define Stringify(x) #x
|
#include "imagefile.h"
|
||||||
#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;
|
|
||||||
|
|
||||||
void Image_free(Image **ima);
|
void Image_free(Image **ima);
|
||||||
bool FITS_read(const char *filename, Image **fits);
|
bool FITS_read(const char *filename, Image **fits);
|
||||||
|
|||||||
@ -22,9 +22,9 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "grasshopper.h"
|
#include "grasshopper.h"
|
||||||
#include "imagefile.h"
|
#include "imagefile.h"
|
||||||
|
|
||||||
@ -32,8 +32,12 @@ static fc2Context context;
|
|||||||
static fc2PGRGuid guid;
|
static fc2PGRGuid guid;
|
||||||
static fc2Error err = FC2_ERROR_OK;
|
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__))){ \
|
#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(){
|
static void disconnect(){
|
||||||
fc2DestroyContext(context);
|
fc2DestroyContext(context);
|
||||||
@ -146,6 +150,7 @@ static int geometrylimits(frameformat *max, frameformat *step){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int getformat(frameformat *fmt){
|
static int getformat(frameformat *fmt){
|
||||||
|
if(!fmt) return FALSE;
|
||||||
unsigned int packsz; float pc;
|
unsigned int packsz; float pc;
|
||||||
fc2Format7ImageSettings f7;
|
fc2Format7ImageSettings f7;
|
||||||
FC2FN(fc2GetFormat7Configuration, &f7, &packsz, &pc);
|
FC2FN(fc2GetFormat7Configuration, &f7, &packsz, &pc);
|
||||||
@ -155,7 +160,7 @@ static int getformat(frameformat *fmt){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int changeformat(frameformat *fmt){
|
static int changeformat(frameformat *fmt){
|
||||||
FNAME();
|
if(!fmt) return FALSE;
|
||||||
BOOL b;
|
BOOL b;
|
||||||
fc2Format7ImageSettings f7;
|
fc2Format7ImageSettings f7;
|
||||||
f7.mode = FC2_MODE_0;
|
f7.mode = FC2_MODE_0;
|
||||||
@ -203,7 +208,7 @@ static int connect(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int GrabImage(fc2Image *convertedImage){
|
static int GrabImage(fc2Image *convertedImage){
|
||||||
//FNAME();
|
if(!convertedImage) return FALSE;
|
||||||
int ret = FALSE;
|
int ret = FALSE;
|
||||||
fc2Image rawImage;
|
fc2Image rawImage;
|
||||||
// start capture
|
// start capture
|
||||||
@ -211,7 +216,8 @@ static int GrabImage(fc2Image *convertedImage){
|
|||||||
err = fc2CreateImage(&rawImage);
|
err = fc2CreateImage(&rawImage);
|
||||||
if(err != FC2_ERROR_OK){
|
if(err != FC2_ERROR_OK){
|
||||||
WARNX("Error in fc2CreateImage: %s", fc2ErrorToDescription(err));
|
WARNX("Error in fc2CreateImage: %s", fc2ErrorToDescription(err));
|
||||||
goto rtn;
|
fc2StopCapture(context);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
// Retrieve the image
|
// Retrieve the image
|
||||||
err = fc2RetrieveBuffer(context, &rawImage);
|
err = fc2RetrieveBuffer(context, &rawImage);
|
||||||
|
|||||||
@ -22,7 +22,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include <stb/stb_image.h>
|
#include <stb/stb_image.h>
|
||||||
#include <stb/stb_image_write.h>
|
#include <stb/stb_image_write.h>
|
||||||
@ -31,7 +30,9 @@
|
|||||||
#include "cameracapture.h"
|
#include "cameracapture.h"
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
#include "fits.h"
|
||||||
#include "grasshopper.h"
|
#include "grasshopper.h"
|
||||||
#include "imagefile.h"
|
#include "imagefile.h"
|
||||||
#include "median.h"
|
#include "median.h"
|
||||||
@ -68,6 +69,11 @@ static char *hexdmp(const char sig[8]){
|
|||||||
}
|
}
|
||||||
#endif
|
#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){
|
static InputType imtype(FILE *f){
|
||||||
char signature[8];
|
char signature[8];
|
||||||
int x = fread(signature, 1, 7, f);
|
int x = fread(signature, 1, 7, f);
|
||||||
@ -122,37 +128,22 @@ InputType chkinput(const char *name){
|
|||||||
return tp;
|
return tp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *u8toImage(uint8_t *data, int width, int height, int stride){
|
/**
|
||||||
|
* @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)
|
||||||
|
*/
|
||||||
|
Image *u8toImage(const uint8_t *data, int width, int height, int stride){
|
||||||
FNAME();
|
FNAME();
|
||||||
Image *outp = MALLOC(Image, 1);
|
Image *outp = Image_new(width, height);
|
||||||
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]);
|
|
||||||
*/
|
|
||||||
|
|
||||||
outp->data = MALLOC(Imtype, width*height);
|
|
||||||
// flip image updown for FITS coordinate system
|
// flip image updown for FITS coordinate system
|
||||||
OMP_FOR()
|
OMP_FOR()
|
||||||
for(int y = 0; y < height; ++y){
|
for(int y = 0; y < height; ++y){
|
||||||
Imtype *Out = &outp->data[(height-1-y)*width];
|
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){
|
for(int x = 0; x < width; ++x){
|
||||||
*Out++ = (Imtype)(*In++);
|
*Out++ = (Imtype)(*In++);
|
||||||
}
|
}
|
||||||
@ -161,15 +152,21 @@ Image *u8toImage(uint8_t *data, int width, int height, int stride){
|
|||||||
return outp;
|
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;
|
int width, height, channels;
|
||||||
uint8_t *img = stbi_load(name, &width, &height, &channels, 1);
|
uint8_t *img = stbi_load(name, &width, &height, &channels, 1);
|
||||||
if(!img){
|
if(!img){
|
||||||
WARNX("Error in loading the image %s\n", name);
|
WARNX("Error in loading the image %s\n", name);
|
||||||
return NULL;
|
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
|
* @return data allocated here
|
||||||
*/
|
*/
|
||||||
Image *Image_new(int w, int h){
|
Image *Image_new(int w, int h){
|
||||||
|
if(w < 1 || h < 1) return NULL;
|
||||||
Image *outp = MALLOC(Image, 1);
|
Image *outp = MALLOC(Image, 1);
|
||||||
outp->width = w;
|
outp->width = w;
|
||||||
outp->height = h;
|
outp->height = h;
|
||||||
@ -213,24 +211,99 @@ Image *Image_new(int w, int h){
|
|||||||
*/
|
*/
|
||||||
Image *Image_sim(const Image *i){
|
Image *Image_sim(const Image *i){
|
||||||
if(!i) return NULL;
|
if(!i) return NULL;
|
||||||
if((i->width * i->height) < 1) return NULL;
|
|
||||||
Image *outp = Image_new(i->width, i->height);
|
Image *outp = Image_new(i->width, i->height);
|
||||||
outp->dtype = i->dtype;
|
|
||||||
return outp;
|
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 I - input image
|
||||||
* @param nchannels - 1 or 3 colour channels
|
* @param nchannels - 1 or 3 colour channels
|
||||||
* @return allocated here image for jpeg/png storing
|
* @return allocated here image for jpeg/png storing
|
||||||
*/
|
*/
|
||||||
uint8_t *linear(const Image *I, int nchannels){ // only 1 and 3 channels supported!
|
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;
|
int width = I->width, height = I->height;
|
||||||
size_t stride = width*nchannels, S = height*stride;
|
size_t stride = width*nchannels, S = height*stride;
|
||||||
uint8_t *outp = MALLOC(uint8_t, S);
|
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);
|
//DBG("make linear transform %dx%d, %d channels", I->width, I->height, nchannels);
|
||||||
if(nchannels == 3){
|
if(nchannels == 3){
|
||||||
OMP_FOR()
|
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];
|
uint8_t *Out = &outp[(height-1-y)*stride];
|
||||||
Imtype *In = &I->data[y*width];
|
Imtype *In = &I->data[y*width];
|
||||||
for(int x = 0; x < width; ++x){
|
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;
|
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];
|
uint8_t *Out = &outp[(height-1-y)*width];
|
||||||
Imtype *In = &I->data[y*width];
|
Imtype *In = &I->data[y*width];
|
||||||
for(int x = 0; x < width; ++x){
|
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
|
* @return allocated here image for jpeg/png storing
|
||||||
*/
|
*/
|
||||||
uint8_t *equalize(const Image *I, int nchannels, double throwpart){
|
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;
|
int width = I->width, height = I->height;
|
||||||
size_t stride = width*nchannels, S = height*stride;
|
size_t stride = width*nchannels, S = height*stride;
|
||||||
uint8_t *lin = linear(I, 1);
|
size_t *orig_histo = get_histogram(I); // original hystogram (linear)
|
||||||
if(!lin) return NULL;
|
if(!orig_histo) return NULL;
|
||||||
uint8_t *outp = MALLOC(uint8_t, S);
|
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]
|
uint8_t eq_levls[256] = {0}; // levels to convert: newpix = eq_levls[oldpix]
|
||||||
int s = width*height;
|
int s = width*height;
|
||||||
for(int i = 0; i < s; ++i){
|
int Nblack = 0, bpart = (int)(throwpart * (double)s);
|
||||||
++orig_hysto[lin[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
int Nblack = 0, bpart = (int)(throwpart * s);
|
|
||||||
int startidx;
|
int startidx;
|
||||||
// remove first part of black pixels
|
// remove first part of black pixels
|
||||||
for(startidx = 0; startidx < 256; ++startidx){
|
for(startidx = 0; startidx < 256; ++startidx){
|
||||||
Nblack += orig_hysto[startidx];
|
Nblack += orig_histo[startidx];
|
||||||
if(Nblack >= bpart) break;
|
if(Nblack >= bpart) break;
|
||||||
}
|
}
|
||||||
++startidx;
|
++startidx;
|
||||||
@ -290,15 +358,9 @@ uint8_t *equalize(const Image *I, int nchannels, double throwpart){
|
|||||||
if(Nwhite >= wpart) break;
|
if(Nwhite >= wpart) break;
|
||||||
}*/
|
}*/
|
||||||
//DBG("Throw %d (real: %d black) pixels, startidx=%d", bpart, Nblack, startidx);
|
//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.;
|
double part = (double)(s + 1. - Nblack) / 256., N = 0.;
|
||||||
for(int i = startidx; i < 256; ++i){
|
for(int i = startidx; i < 256; ++i){
|
||||||
N += orig_hysto[i];
|
N += orig_histo[i];
|
||||||
eq_levls[i] = (uint8_t)(N/part);
|
eq_levls[i] = (uint8_t)(N/part);
|
||||||
}
|
}
|
||||||
//for(int i = stopidx; i < 256; ++i) eq_levls[i] = 255;
|
//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){
|
if(nchannels == 3){
|
||||||
OMP_FOR()
|
OMP_FOR()
|
||||||
for(int y = 0; y < height; ++y){
|
for(int y = 0; y < height; ++y){
|
||||||
uint8_t *Out = &outp[y*stride];
|
uint8_t *Out = &outp[(height-1-y)*stride];
|
||||||
uint8_t *In = &lin[y*width];
|
Imtype *In = &I->data[y*width];
|
||||||
for(int x = 0; x < width; ++x){
|
for(int x = 0; x < width; ++x){
|
||||||
Out[0] = Out[1] = Out[2] = eq_levls[*In++];
|
Out[0] = Out[1] = Out[2] = eq_levls[*In++];
|
||||||
Out += 3;
|
Out += 3;
|
||||||
@ -319,14 +381,14 @@ uint8_t *equalize(const Image *I, int nchannels, double throwpart){
|
|||||||
}else{
|
}else{
|
||||||
OMP_FOR()
|
OMP_FOR()
|
||||||
for(int y = 0; y < height; ++y){
|
for(int y = 0; y < height; ++y){
|
||||||
uint8_t *Out = &outp[y*width];
|
uint8_t *Out = &outp[(height-1-y)*width];
|
||||||
uint8_t *In = &lin[y*width];
|
Imtype *In = &I->data[y*width];
|
||||||
for(int x = 0; x < width; ++x){
|
for(int x = 0; x < width; ++x){
|
||||||
*Out++ = eq_levls[*In++];
|
*Out++ = eq_levls[*In++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE(lin);
|
FREE(orig_histo);
|
||||||
return outp;
|
return outp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +406,7 @@ int Image_write_jpg(const Image *I, const char *name, int eq){
|
|||||||
outp = equalize(I, 1, theconf.throwpart);
|
outp = equalize(I, 1, theconf.throwpart);
|
||||||
else
|
else
|
||||||
outp = linear(I, 1);
|
outp = linear(I, 1);
|
||||||
|
if(!outp) return 0;
|
||||||
//DBG("Try to write %s", name);
|
//DBG("Try to write %s", name);
|
||||||
char *tmpnm = MALLOC(char, strlen(name) + 5);
|
char *tmpnm = MALLOC(char, strlen(name) + 5);
|
||||||
sprintf(tmpnm, "%s-tmp", name);
|
sprintf(tmpnm, "%s-tmp", name);
|
||||||
@ -372,8 +435,9 @@ void Image_minmax(Image *I){
|
|||||||
int min_p = min, max_p = min;
|
int min_p = min, max_p = min;
|
||||||
#pragma omp for nowait
|
#pragma omp for nowait
|
||||||
for(int i = 0; i < wh; ++i){
|
for(int i = 0; i < wh; ++i){
|
||||||
if(I->data[i] < min_p) min_p = I->data[i];
|
Imtype pixval = I->data[i];
|
||||||
else if(I->data[i] > max_p) max_p = I->data[i];
|
if(pixval < min_p) min_p = pixval;
|
||||||
|
else if(pixval > max_p) max_p = pixval;
|
||||||
}
|
}
|
||||||
#pragma omp critical
|
#pragma omp critical
|
||||||
{
|
{
|
||||||
@ -383,27 +447,26 @@ void Image_minmax(Image *I){
|
|||||||
}
|
}
|
||||||
I->maxval = max;
|
I->maxval = max;
|
||||||
I->minval = min;
|
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 IMAGE TYPES ===================>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// convert binarized image into floating
|
|
||||||
/**
|
/**
|
||||||
* @brief bin2Im - convert binarized image into floating
|
* @brief bin2Im - convert binarized image into floating
|
||||||
* @param image - binarized image
|
* @param image - binarized image
|
||||||
* @param W, H - its size (in pixels!)
|
* @param W, H - its size (in pixels!)
|
||||||
* @return Image structure
|
* @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);
|
Image *ret = Image_new(W, H);
|
||||||
int stride = (W + 7) / 8, s1 = (stride*8 == W) ? stride : stride - 1;
|
int stride = (W + 7) / 8, s1 = (stride*8 == W) ? stride : stride - 1;
|
||||||
OMP_FOR()
|
OMP_FOR()
|
||||||
for(int y = 0; y < H; y++){
|
for(int y = 0; y < H; y++){
|
||||||
Imtype *optr = &ret->data[y*W];
|
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++){
|
for(int x = 0; x < s1; x++){
|
||||||
register uint8_t inp = *iptr++;
|
register uint8_t inp = *iptr++;
|
||||||
for(int i = 0; i < 8; ++i){
|
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;
|
int rest = W - s1*8;
|
||||||
register uint8_t inp = *iptr;
|
if(rest){
|
||||||
for(int i = 0; i < rest; ++i){
|
register uint8_t inp = *iptr;
|
||||||
*optr++ = (inp & 0x80) ? 1. : 0;
|
for(int i = 0; i < rest; ++i){
|
||||||
inp <<= 1;
|
*optr++ = (inp & 0x80) ? 1. : 0;
|
||||||
|
inp <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret->dtype = BYTE_IMG;
|
|
||||||
ret->minval = 0;
|
ret->minval = 0;
|
||||||
ret->maxval = 1;
|
ret->maxval = 1;
|
||||||
return ret;
|
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 im (i) - image to convert
|
||||||
* @param stride (o) - new width of image
|
* @param stride (o) - new width of image
|
||||||
* @param bk - background level (all values < bk will be 0, other will be 1)
|
* @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;
|
int y, W0 = (W + 7) / 8, s1 = (W/8 == W0) ? W0 : W0 - 1;
|
||||||
uint8_t *ret = MALLOC(uint8_t, W0 * H);
|
uint8_t *ret = MALLOC(uint8_t, W0 * H);
|
||||||
OMP_FOR()
|
OMP_FOR()
|
||||||
for(y = 0; y < H; y++){
|
for(y = 0; y < H; ++y){
|
||||||
Imtype *iptr = &im->data[y*W];
|
Imtype *iptr = &im->data[y*W];
|
||||||
uint8_t *optr = &ret[y*W0];
|
uint8_t *optr = &ret[y*W0];
|
||||||
register uint8_t o;
|
|
||||||
for(int x = 0; x < s1; ++x){
|
for(int x = 0; x < s1; ++x){
|
||||||
o = 0;
|
register uint8_t o = 0;
|
||||||
for(int i = 0; i < 8; ++i){
|
for(int i = 0; i < 8; ++i){
|
||||||
o <<= 1;
|
o <<= 1;
|
||||||
if(*iptr++ > bk) o |= 1;
|
if(*iptr++ > bk) o |= 1;
|
||||||
}
|
}
|
||||||
*optr++ = o;
|
*optr++ = o;
|
||||||
}
|
}
|
||||||
int rest = 7 - (W - s1*8);
|
int rest = W - s1*8;
|
||||||
if(rest < 7){
|
if(rest){
|
||||||
o = 0;
|
register uint8_t o = 0;
|
||||||
for(int x = 7; x > rest; --x){
|
for(int x = 0; x < rest; ++x){
|
||||||
if(*iptr++ > 0.) o |= 1<<x;
|
o <<= 1;
|
||||||
|
if(*iptr++ > bk) o |= 1;
|
||||||
}
|
}
|
||||||
*optr = o;
|
*optr = o << (8 - rest);
|
||||||
//*optr = o | 1<<rest; // mark outern right edge (for good CC labeling)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert size_t labels into floating
|
#if 0
|
||||||
Image *ST2Im(size_t *image, int W, int H){
|
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);
|
Image *ret = Image_new(W, H);
|
||||||
OMP_FOR()
|
OMP_FOR()
|
||||||
for(int y = 0; y < H; ++y){
|
for(int y = 0; y < H; ++y){
|
||||||
Imtype *optr = &ret->data[y*W];
|
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){
|
for(int x = 0; x < W; ++x){
|
||||||
*optr++ = (Imtype)*iptr++;
|
*optr++ = (Imtype)*iptr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret->dtype = FLOAT_IMG;
|
|
||||||
Image_minmax(ret);
|
Image_minmax(ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert "packed" image into size_t array for conncomp procedure
|
* 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
|
* @param W, H - size of image in pixels
|
||||||
* @return allocated memory area with copy of an image
|
* @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);
|
size_t *ret = MALLOC(size_t, W * H);
|
||||||
int W0 = (W + 7) / 8, s1 = W0 - 1;
|
int W0 = (W + 7) / 8, s1 = W0 - 1;
|
||||||
OMP_FOR()
|
OMP_FOR()
|
||||||
for(int y = 0; y < H; y++){
|
for(int y = 0; y < H; y++){
|
||||||
size_t *optr = &ret[y*W];
|
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){
|
for(int x = 0; x < s1; ++x){
|
||||||
register uint8_t inp = *iptr++;
|
register uint8_t inp = *iptr++;
|
||||||
for(int i = 0; i < 8; ++i){
|
for(int i = 0; i < 8; ++i){
|
||||||
@ -500,10 +565,12 @@ size_t *bin2ST(uint8_t *image, int W, int H){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
int rest = W - s1*8;
|
int rest = W - s1*8;
|
||||||
register uint8_t inp = *iptr;
|
if(rest){
|
||||||
for(int i = 0; i < rest; ++i){
|
register uint8_t inp = *iptr;
|
||||||
*optr++ = (inp & 0x80) ? 1 : 0;
|
for(int i = 0; i < rest; ++i){
|
||||||
inp <<= 1;
|
*optr++ = (inp & 0x80) ? 1 : 0;
|
||||||
|
inp <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@ -20,8 +20,24 @@
|
|||||||
#define IMAGEFILE_H__
|
#define IMAGEFILE_H__
|
||||||
|
|
||||||
#include <stdint.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
|
// input file/directory type
|
||||||
typedef enum{
|
typedef enum{
|
||||||
@ -46,11 +62,13 @@ Image *Image_new(int w, int h);
|
|||||||
Image *Image_sim(const Image *i);
|
Image *Image_sim(const Image *i);
|
||||||
void Image_free(Image **I);
|
void Image_free(Image **I);
|
||||||
int Image_write_jpg(const Image *I, const char *name, int equalize);
|
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 *u8toImage(const uint8_t *data, int width, int height, int stride);
|
||||||
Image *bin2Im(uint8_t *image, int W, int H);
|
Image *bin2Im(const uint8_t *image, int W, int H);
|
||||||
uint8_t *Im2bin(const Image *im, Imtype bk);
|
uint8_t *Im2bin(const Image *im, Imtype bk);
|
||||||
size_t *bin2ST(uint8_t *image, int W, int H);
|
size_t *bin2ST(const uint8_t *image, int W, int H);
|
||||||
Image *ST2Im(size_t *image, int W, int H);
|
//Image *ST2Im(const size_t *image, int W, int H);
|
||||||
|
|
||||||
#endif // IMAGEFILE_H__
|
#endif // IMAGEFILE_H__
|
||||||
|
|||||||
@ -21,13 +21,13 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "basler.h"
|
#include "basler.h"
|
||||||
#include "binmorph.h"
|
#include "binmorph.h"
|
||||||
#include "cameracapture.h"
|
#include "cameracapture.h"
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "grasshopper.h"
|
#include "grasshopper.h"
|
||||||
#include "fits.h"
|
#include "fits.h"
|
||||||
@ -47,6 +47,7 @@ steppersproc *theSteppers = NULL;
|
|||||||
static FILE *fXYlog = NULL;
|
static FILE *fXYlog = NULL;
|
||||||
static double tstart = 0.; // time of logging start
|
static double tstart = 0.; // time of logging start
|
||||||
static double FPS = 0.; // frames per second
|
static double FPS = 0.; // frames per second
|
||||||
|
static float xc = -1., yc = -1.; // center coordinates
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint32_t area; // object area in pixels
|
uint32_t area; // object area in pixels
|
||||||
@ -115,7 +116,7 @@ static void XYnewline(){
|
|||||||
|
|
||||||
static void getDeviation(object *curobj){
|
static void getDeviation(object *curobj){
|
||||||
int averflag = 0;
|
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 xx = curobj->xc, yy = curobj->yc, xsum2 = 0., ysum2 = 0.;
|
||||||
double Sx = 0., Sy = 0.;
|
double Sx = 0., Sy = 0.;
|
||||||
static int counter = 0;
|
static int counter = 0;
|
||||||
@ -126,23 +127,24 @@ static void getDeviation(object *curobj){
|
|||||||
curobj->xsigma, curobj->ysigma, curobj->WdivH);
|
curobj->xsigma, curobj->ysigma, curobj->WdivH);
|
||||||
}
|
}
|
||||||
//DBG("counter = %d", counter);
|
//DBG("counter = %d", counter);
|
||||||
if(++counter != theconf.naverage){
|
if(++counter < theconf.naverage){
|
||||||
goto process_corrections;
|
goto process_corrections;
|
||||||
}
|
}
|
||||||
// it's time to calculate average deviations
|
// it's time to calculate average deviations
|
||||||
counter = 0; xx = 0.; yy = 0.;
|
xx = 0.; yy = 0.;
|
||||||
for(int i = 0; i < theconf.naverage; ++i){
|
for(int i = 0; i < counter; ++i){
|
||||||
double x = Xc[i], y = Yc[i];
|
double x = Xc[i], y = Yc[i];
|
||||||
xx += x; yy += y;
|
xx += x; yy += y;
|
||||||
xsum2 += x*x; ysum2 += y*y;
|
xsum2 += x*x; ysum2 += y*y;
|
||||||
}
|
}
|
||||||
xx /= theconf.naverage; yy /= theconf.naverage;
|
xx /= counter; yy /= counter;
|
||||||
Sx = sqrt(xsum2/theconf.naverage - xx*xx);
|
Sx = sqrt(xsum2/counter - xx*xx);
|
||||||
Sy = sqrt(ysum2/theconf.naverage - yy*yy);
|
Sy = sqrt(ysum2/counter - yy*yy);
|
||||||
|
counter = 0;
|
||||||
#ifdef EBUG
|
#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
|
#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;
|
averflag = 1;
|
||||||
if(fXYlog) fprintf(fXYlog, "%.1f\t%.1f\t%.1f\t%.1f", xx, yy, Sx, Sy);
|
if(fXYlog) fprintf(fXYlog, "%.1f\t%.1f\t%.1f\t%.1f", xx, yy, Sx, Sy);
|
||||||
process_corrections:
|
process_corrections:
|
||||||
@ -156,7 +158,6 @@ process_corrections:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void process_file(Image *I){
|
void process_file(Image *I){
|
||||||
FNAME();
|
|
||||||
static double lastTproc = 0.;
|
static double lastTproc = 0.;
|
||||||
/*
|
/*
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
@ -176,12 +177,11 @@ void process_file(Image *I){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int W = I->width, H = I->height;
|
int W = I->width, H = I->height;
|
||||||
if(!I->dtype) I->dtype = FLOAT_IMG;
|
|
||||||
//save_fits(I, "fitsout.fits");
|
//save_fits(I, "fitsout.fits");
|
||||||
//DELTA("Save original");
|
//DELTA("Save original");
|
||||||
Imtype bk;
|
Imtype bk;
|
||||||
if(calc_background(I, &bk)){
|
if(calc_background(I, &bk)){
|
||||||
DBG("backgr = %g", bk);
|
DBG("backgr = %d", bk);
|
||||||
DELTA("Got background");
|
DELTA("Got background");
|
||||||
uint8_t *ibin = Im2bin(I, bk);
|
uint8_t *ibin = Im2bin(I, bk);
|
||||||
DELTA("Made binary");
|
DELTA("Made binary");
|
||||||
@ -201,14 +201,14 @@ void process_file(Image *I){
|
|||||||
ConnComps *cc = NULL;
|
ConnComps *cc = NULL;
|
||||||
size_t *S = cclabel4(opn, W, H, &cc);
|
size_t *S = cclabel4(opn, W, H, &cc);
|
||||||
FREE(opn);
|
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);
|
object *Objects = MALLOC(object, cc->Nobj-1);
|
||||||
int objctr = 0;
|
int objctr = 0;
|
||||||
for(size_t i = 1; i < cc->Nobj; ++i){
|
for(size_t i = 1; i < cc->Nobj; ++i){
|
||||||
Box *b = &cc->boxes[i];
|
Box *b = &cc->boxes[i];
|
||||||
double wh = ((double)b->xmax - b->xmin)/(b->ymax - b->ymin);
|
double wh = ((double)b->xmax - b->xmin)/(b->ymax - b->ymin);
|
||||||
//DBG("Obj# %zd: wh=%g, area=%d", i, wh, b->area);
|
//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(wh < theconf.minwh || wh > theconf.maxwh) continue;
|
||||||
if((int)b->area < theconf.minarea || (int)b->area > theconf.maxarea) continue;
|
if((int)b->area < theconf.minarea || (int)b->area > theconf.maxarea) continue;
|
||||||
double xc = 0., yc = 0.;
|
double xc = 0., yc = 0.;
|
||||||
@ -239,25 +239,27 @@ void process_file(Image *I){
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
DELTA("Labeling");
|
DELTA("Labeling");
|
||||||
DBG("T%zd, N=%d\n", time(NULL), objctr);
|
DBGLOG("T%.2f, N=%d\n", dtime(), objctr);
|
||||||
if(objctr > 1){
|
if(objctr > 1){
|
||||||
if(theconf.starssort)
|
if(theconf.starssort)
|
||||||
qsort(Objects, objctr, sizeof(object), compIntens);
|
qsort(Objects, objctr, sizeof(object), compIntens);
|
||||||
else
|
else
|
||||||
qsort(Objects, objctr, sizeof(object), compDist);
|
qsort(Objects, objctr, sizeof(object), compDist);
|
||||||
}
|
}
|
||||||
|
if(objctr){
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
object *o = Objects;
|
object *o = Objects;
|
||||||
green("%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%6s\t%8s\n",
|
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");
|
"N", "Area", "Mv", "W/H", "Xc", "Yc", "Sx", "Sy", "Area/r^2");
|
||||||
for(int i = 0; i < objctr; ++i, ++o){
|
for(int i = 0; i < objctr; ++i, ++o){
|
||||||
// 1.0857 = 2.5/ln(10)
|
// 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",
|
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,
|
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);
|
o->xsigma, o->ysigma, o->area/o->xsigma/o->ysigma);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
getDeviation(Objects); // calculate dX/dY and process corrections
|
getDeviation(Objects); // calculate dX/dY and process corrections
|
||||||
|
}
|
||||||
{ // prepare image and save jpeg
|
{ // prepare image and save jpeg
|
||||||
uint8_t *outp = NULL;
|
uint8_t *outp = NULL;
|
||||||
if(theconf.equalize)
|
if(theconf.equalize)
|
||||||
@ -265,7 +267,7 @@ void process_file(Image *I){
|
|||||||
else
|
else
|
||||||
outp = linear(I, 3);
|
outp = linear(I, 3);
|
||||||
static Pattern *cross = NULL;
|
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};
|
Img3 i3 = {.data = outp, .w = I->width, .h = H};
|
||||||
// draw fiber center position
|
// draw fiber center position
|
||||||
Pattern_draw3(&i3, cross, theconf.xtarget-theconf.xoff, H-(theconf.ytarget-theconf.yoff), C_B);
|
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;
|
int H = I->height;
|
||||||
// draw current star centroid
|
// draw current star centroid
|
||||||
Pattern_draw3(&i3, cross, Objects[0].xc, H-Objects[0].yc, C_G);
|
Pattern_draw3(&i3, cross, Objects[0].xc, H-Objects[0].yc, C_G);
|
||||||
|
xc = Objects[0].xc;
|
||||||
|
yc = Objects[0].yc;
|
||||||
// draw other centroids
|
// draw other centroids
|
||||||
for(int i = 1; i < objctr; ++i)
|
for(int i = 1; i < objctr; ++i)
|
||||||
Pattern_draw3(&i3, cross, Objects[i].xc, H-Objects[i].yc, C_R);
|
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);
|
char *tmpnm = MALLOC(char, strlen(GP->outputjpg) + 5);
|
||||||
sprintf(tmpnm, "%s-tmp", GP->outputjpg);
|
sprintf(tmpnm, "%s-tmp", GP->outputjpg);
|
||||||
if(stbi_write_jpg(tmpnm, I->width, I->height, 3, outp, 95)){
|
if(stbi_write_jpg(tmpnm, I->width, I->height, 3, outp, 95)){
|
||||||
@ -290,7 +293,11 @@ void process_file(Image *I){
|
|||||||
FREE(outp);
|
FREE(outp);
|
||||||
}
|
}
|
||||||
FREE(Objects);
|
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(S);
|
||||||
FREE(cc);
|
FREE(cc);
|
||||||
}
|
}
|
||||||
@ -306,8 +313,8 @@ static char *localimages(const char *messageid, int isdir, char *buf, int buflen
|
|||||||
if(!impath){
|
if(!impath){
|
||||||
if(!realpath(GP->outputjpg, impath)) impath = strdup(GP->outputjpg);
|
if(!realpath(GP->outputjpg, impath)) impath = strdup(GP->outputjpg);
|
||||||
}
|
}
|
||||||
snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"watch %s\", \"impath\": \"%s\"}",
|
snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"watch %s\", \"impath\": \"%s\", \"xcenter\": %.1f, \"ycenter\": %.1f }",
|
||||||
MESSAGEID, messageid, isdir ? "directory" : "file", impath);
|
MESSAGEID, messageid, isdir ? "directory" : "file", impath, xc, yc);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
static char *watchdr(const char *messageid, char *buf, int buflen){
|
static char *watchdr(const char *messageid, char *buf, int buflen){
|
||||||
@ -383,3 +390,8 @@ void setpostprocess(const char *name){
|
|||||||
}
|
}
|
||||||
|
|
||||||
double getFramesPerS(){ return FPS; }
|
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 XY_TOLERANCE (5.)
|
||||||
|
|
||||||
#define PUSIROBO_POSTPROC "pusirobo"
|
#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_bool stopwork;
|
||||||
extern volatile atomic_ullong ImNumber;
|
extern volatile atomic_ullong ImNumber;
|
||||||
@ -54,5 +52,6 @@ void openXYlog(const char *name);
|
|||||||
void closeXYlog();
|
void closeXYlog();
|
||||||
void setpostprocess(const char *name);
|
void setpostprocess(const char *name);
|
||||||
double getFramesPerS();
|
double getFramesPerS();
|
||||||
|
void getcenter(float *x, float *y);
|
||||||
|
|
||||||
#endif // IMPROC_H__
|
#endif // IMPROC_H__
|
||||||
|
|||||||
@ -23,8 +23,8 @@
|
|||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
#include "imagefile.h"
|
#include "imagefile.h"
|
||||||
|
|
||||||
static char filenm[FILENAME_MAX];
|
static char filenm[FILENAME_MAX];
|
||||||
|
|||||||
@ -19,11 +19,12 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h> // signal
|
#include <signal.h> // signal
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h> // strdup
|
#include <string.h> // strdup
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "grasshopper.h"
|
#include "grasshopper.h"
|
||||||
#include "improc.h"
|
#include "improc.h"
|
||||||
#include "pusirobo.h"
|
#include "pusirobo.h"
|
||||||
@ -112,8 +113,8 @@ int main(int argc, char *argv[]){
|
|||||||
if(GP->throwpart < 0. || GP->throwpart > 0.99){
|
if(GP->throwpart < 0. || GP->throwpart > 0.99){
|
||||||
ERRX("Fraction of black pixels should be in [0., 0.99]");
|
ERRX("Fraction of black pixels should be in [0., 0.99]");
|
||||||
}
|
}
|
||||||
if(GP->Naveraging < 2 || GP->Naveraging > MAX_AVERAGING_ARRAY_SIZE)
|
if(GP->Naveraging < 1 || GP->Naveraging > NAVER_MAX)
|
||||||
ERRX("Averaging amount should be from 2 to 25");
|
ERRX("Averaging amount should be from 1 to %d", NAVER_MAX);
|
||||||
tp = chk_inp(GP->inputname);
|
tp = chk_inp(GP->inputname);
|
||||||
if(tp == T_WRONG) ERRX("Enter correct image file or directory name");
|
if(tp == T_WRONG) ERRX("Enter correct image file or directory name");
|
||||||
// check ability of saving file
|
// check ability of saving file
|
||||||
@ -183,7 +184,7 @@ int main(int argc, char *argv[]){
|
|||||||
setpostprocess(GP->processing);
|
setpostprocess(GP->processing);
|
||||||
check4running(self, GP->pidfile);
|
check4running(self, GP->pidfile);
|
||||||
DBG("%s started, snippets library version is %s\n", self, sl_libversion());
|
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(SIGTERM, signals); // kill (-15) - quit
|
||||||
signal(SIGHUP, SIG_IGN); // hup - ignore
|
signal(SIGHUP, SIG_IGN); // hup - ignore
|
||||||
signal(SIGINT, signals); // ctrl+C - quit
|
signal(SIGINT, signals); // ctrl+C - quit
|
||||||
|
|||||||
131
LocCorr/median.c
131
LocCorr/median.c
@ -26,9 +26,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "imagefile.h"
|
#include "imagefile.h"
|
||||||
#include "median.h"
|
#include "median.h"
|
||||||
|
|
||||||
@ -36,8 +36,13 @@
|
|||||||
#define ELEM_SWAP(a, b) {register Imtype t = a; a = b; b = t;}
|
#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]);}
|
#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){
|
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){
|
static Imtype opt_med3(Imtype *p){
|
||||||
PIX_SORT(0, 1); PIX_SORT(1, 2); PIX_SORT(0, 1);
|
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){
|
static Imtype opt_med4(Imtype *p){
|
||||||
PIX_SORT(0, 2); PIX_SORT(1, 3);
|
PIX_SORT(0, 2); PIX_SORT(1, 3);
|
||||||
PIX_SORT(0, 1); PIX_SORT(2, 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){
|
static Imtype opt_med5(Imtype *p){
|
||||||
PIX_SORT(0, 1); PIX_SORT(3, 4); PIX_SORT(0, 3);
|
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(1, 2); PIX_SORT(3, 4);
|
||||||
PIX_SORT(0, 1); PIX_SORT(2, 3); PIX_SORT(4, 5);
|
PIX_SORT(0, 1); PIX_SORT(2, 3); PIX_SORT(4, 5);
|
||||||
PIX_SORT(1, 2); PIX_SORT(3, 4);
|
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){
|
static Imtype opt_med7(Imtype *p){
|
||||||
PIX_SORT(0, 5); PIX_SORT(0, 3); PIX_SORT(1, 6);
|
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(3, 5); PIX_SORT(0, 1); PIX_SORT(2, 3);
|
||||||
PIX_SORT(4, 5); PIX_SORT(6, 7); PIX_SORT(1, 4);
|
PIX_SORT(4, 5); PIX_SORT(6, 7); PIX_SORT(1, 4);
|
||||||
PIX_SORT(3, 6);
|
PIX_SORT(3, 6);
|
||||||
return(p[3] + p[4]) * 0.5;
|
return mean(p[3], p[4]);
|
||||||
}
|
}
|
||||||
static Imtype opt_med9(Imtype *p){
|
static Imtype opt_med9(Imtype *p){
|
||||||
PIX_SORT(1, 2); PIX_SORT(4, 5); PIX_SORT(7, 8);
|
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(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(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);
|
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){
|
static Imtype opt_med25(Imtype *p){
|
||||||
PIX_SORT(0, 1) ; PIX_SORT(3, 4) ; PIX_SORT(2, 4) ;
|
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,
|
const medfunc fnarr[] = {opt_med2, opt_med3, opt_med4, opt_med5, opt_med6,
|
||||||
opt_med7, opt_med8, opt_med9};
|
opt_med7, opt_med8, opt_med9};
|
||||||
if(n == 1) return *idata;
|
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 == 16) fn = opt_med16;
|
||||||
else if(n == 25) fn = opt_med25;
|
else if(n == 25) fn = opt_med25;
|
||||||
if(fn){
|
if(fn){
|
||||||
@ -229,12 +234,12 @@ typedef struct Mediator_t{
|
|||||||
#define maxCt(m) (((m)->ct)/2) //count of Imtypes in maxheap
|
#define maxCt(m) (((m)->ct)/2) //count of Imtypes in maxheap
|
||||||
|
|
||||||
//returns 1 if heap[i] < heap[j]
|
//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]]);
|
return ImtypeLess(m->data[m->heap[i]],m->data[m->heap[j]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//swaps Imtypes i&j in heap, maintains indexes
|
//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];
|
int t = m->heap[i];
|
||||||
m->heap[i] = m->heap[j];
|
m->heap[i] = m->heap[j];
|
||||||
m->heap[j] = t;
|
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
|
//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));
|
return (mmless(m,i,j) && mmexchange(m,i,j));
|
||||||
}
|
}
|
||||||
|
|
||||||
//maintains minheap property for all Imtypes below i/2.
|
//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){
|
for(; i <= minCt(m); i*=2){
|
||||||
if(i>1 && i < minCt(m) && mmless(m, i+1, i)) ++i;
|
if(i>1 && i < minCt(m) && mmless(m, i+1, i)) ++i;
|
||||||
if(!mmCmpExch(m,i,i/2)) break;
|
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)
|
//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){
|
for(; i >= -maxCt(m); i*=2){
|
||||||
if(i<-1 && i > -maxCt(m) && mmless(m, i, i-1)) --i;
|
if(i<-1 && i > -maxCt(m) && mmless(m, i, i-1)) --i;
|
||||||
if(!mmCmpExch(m,i/2,i)) break;
|
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
|
//maintains minheap property for all Imtypes above i, including median
|
||||||
//returns true if median changed
|
//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;
|
while (i > 0 && mmCmpExch(m, i, i/2)) i /= 2;
|
||||||
return (i == 0);
|
return (i == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//maintains maxheap property for all Imtypes above i, including median
|
//maintains maxheap property for all Imtypes above i, including median
|
||||||
//returns true if median changed
|
//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;
|
while (i < 0 && mmCmpExch(m, i/2, i)) i /= 2;
|
||||||
return (i == 0);
|
return (i == 0);
|
||||||
}
|
}
|
||||||
@ -282,7 +287,7 @@ int maxSortUp(Mediator* m, int i){
|
|||||||
|
|
||||||
//creates new Mediator: to calculate `nImtypes` running median.
|
//creates new Mediator: to calculate `nImtypes` running median.
|
||||||
//mallocs single block of memory, caller must free.
|
//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);
|
int size = sizeof(Mediator) + nImtypes*(sizeof(Imtype)+sizeof(int)*2);
|
||||||
Mediator* m = malloc(size);
|
Mediator* m = malloc(size);
|
||||||
m->data = (Imtype*)(m + 1);
|
m->data = (Imtype*)(m + 1);
|
||||||
@ -298,7 +303,7 @@ Mediator* MediatorNew(int nImtypes){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Inserts Imtype, maintains median in O(lg 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 isNew=(m->ct<m->N);
|
||||||
int p = m->pos[m->idx];
|
int p = m->pos[m->idx];
|
||||||
Imtype old = m->data[m->idx];
|
Imtype old = m->data[m->idx];
|
||||||
@ -318,15 +323,16 @@ void MediatorInsert(Mediator* m, Imtype v){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//returns median Imtype (or average of 2 when Imtype count is even)
|
//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]];
|
Imtype v = m->data[m->heap[0]];
|
||||||
if ((m->ct&1) == 0) v = ImtypeMean(v, m->data[m->heap[-1]]);
|
if ((m->ct&1) == 0) v = ImtypeMean(v, m->data[m->heap[-1]]);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
// median + min/max
|
// 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]];
|
Imtype v = m->data[m->heap[0]];
|
||||||
if ((m->ct&1) == 0) v = ImtypeMean(v, m->data[m->heap[-1]]);
|
if ((m->ct&1) == 0) v = ImtypeMean(v, m->data[m->heap[-1]]);
|
||||||
Imtype min = v, max = v;
|
Imtype min = v, max = v;
|
||||||
int i;
|
int i;
|
||||||
@ -342,6 +348,7 @@ Imtype MediatorStat(Mediator* m, Imtype *minval, Imtype *maxval){
|
|||||||
*maxval = max;
|
*maxval = max;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* filter image by median (seed*2 + 1) x (seed*2 + 1)
|
* 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]);
|
MediatorInsert(m, inputima[xx]);
|
||||||
med[medidx] = MediatorMedian(m);
|
med[medidx] = MediatorMedian(m);
|
||||||
}
|
}
|
||||||
FREE(m);
|
free(m);
|
||||||
}
|
}
|
||||||
Image_minmax(out);
|
Image_minmax(out);
|
||||||
DBG("time for median filtering %zdx%zd of image %zdx%zd: %gs", blksz, blksz, w, h,
|
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 *om = (M) ? &M->data[startidx] : NULL;
|
||||||
Imtype *os = (S) ? &S->data[startidx] : NULL;
|
Imtype *os = (S) ? &S->data[startidx] : NULL;
|
||||||
for(int x = seed; x < xmax; ++x){
|
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;
|
int yb = y + seed + 1, xm = x - seed;
|
||||||
for(int yy = y - seed; yy < yb; ++yy){
|
for(int yy = y - seed; yy < yb; ++yy){
|
||||||
Imtype *ptr = &in->data[yy * w + xm];
|
Imtype *ptr = &in->data[yy * w + xm];
|
||||||
for(int xx = 0; xx < hsz; ++xx){
|
for(int xx = 0; xx < hsz; ++xx){
|
||||||
Imtype d = *ptr++;
|
double d = *ptr++;
|
||||||
sum += d;
|
sum += d;
|
||||||
sum2 += d*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);
|
//DBG("sum=%g, sum2=%g, sz=%d", sum, sum2, sz);
|
||||||
sum /= sz;
|
sum /= sz;
|
||||||
if(om){
|
if(om){
|
||||||
*om++ = sum;
|
*om++ = (Imtype)sum;
|
||||||
//DBG("mean (%d, %d): %g", x, y, 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){
|
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);
|
DBG("time for mean/sigma computation: %gs", dtime() - t0);
|
||||||
return TRUE;
|
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);
|
Imtype calc_median(Imtype *idata, int n);
|
||||||
Image *get_median(const Image *img, int seed);
|
Image *get_median(const Image *img, int seed);
|
||||||
int get_stat(const Image *in, int seed, Image **mean, Image **std);
|
int get_stat(const Image *in, int seed, Image **mean, Image **std);
|
||||||
int calc_background(Image *img, Imtype *bk);
|
|
||||||
|
|
||||||
#endif // __MEDIAN_H__
|
#endif // __MEDIAN_H__
|
||||||
|
|||||||
@ -26,9 +26,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "improc.h" // global variable stopwork
|
#include "improc.h" // global variable stopwork
|
||||||
#include "pusirobo.h"
|
#include "pusirobo.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
@ -327,7 +327,7 @@ static int chkRelay(){
|
|||||||
relay = r;
|
relay = r;
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
rtn:
|
rtn:
|
||||||
FREE(ans);
|
free(ans);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,7 +357,7 @@ static int setSpeed(const char *mesg, const char *name){
|
|||||||
LOGERR("no %s motor", name);
|
LOGERR("no %s motor", name);
|
||||||
retval = FALSE;
|
retval = FALSE;
|
||||||
}
|
}
|
||||||
FREE(ans);
|
if(ans) free(ans);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,11 +403,11 @@ static int pusi_connect_server(){
|
|||||||
send_message_nocheck(registerVaxe);
|
send_message_nocheck(registerVaxe);
|
||||||
send_message_nocheck(registerFocus);
|
send_message_nocheck(registerFocus);
|
||||||
send_message_nocheck(registerRelay);
|
send_message_nocheck(registerRelay);
|
||||||
int retval = TRUE;
|
int retval = FALSE;
|
||||||
if(!chkRelay()) retval = FALSE;
|
if(chkRelay()) retval = TRUE;
|
||||||
if(!setSpeed(setUspeed, "U")) retval = FALSE;
|
if(setSpeed(setUspeed, "U")) retval = TRUE;
|
||||||
if(!setSpeed(setVspeed, "V")) retval = FALSE;
|
if(setSpeed(setVspeed, "V")) retval = TRUE;
|
||||||
if(!setSpeed(setFspeed, "F")) retval = FALSE;
|
if(setSpeed(setFspeed, "F")) retval = TRUE;
|
||||||
if(!retval) pusi_disconnect();
|
if(!retval) pusi_disconnect();
|
||||||
else{
|
else{
|
||||||
state = PUSI_RELAX;
|
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);
|
LOGDBG("%s not found in '%s'", CURPOSstatus, ans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE(ans);
|
if(ans) free(ans);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,7 +483,7 @@ static int move_motor(const char *movecmd, int s){
|
|||||||
LOGWARN("NO OK in %s", ans);
|
LOGWARN("NO OK in %s", ans);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
FREE(ans);
|
if(ans) free(ans);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -968,6 +968,7 @@ static char *Umove(const char *val, char *buf, int buflen){
|
|||||||
int Unfixed = Uposition + d + Fposition;
|
int Unfixed = Uposition + d + Fposition;
|
||||||
if(Unfixed > theconf.maxUsteps || Unfixed < -theconf.maxUsteps){
|
if(Unfixed > theconf.maxUsteps || Unfixed < -theconf.maxUsteps){
|
||||||
snprintf(buf, buflen, FAIL);
|
snprintf(buf, buflen, FAIL);
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
dUmove = d;
|
dUmove = d;
|
||||||
snprintf(buf, buflen, OK);
|
snprintf(buf, buflen, OK);
|
||||||
@ -978,6 +979,7 @@ static char *Vmove(const char *val, char *buf, int buflen){
|
|||||||
int Vnfixed = Vposition + d + Fposition;
|
int Vnfixed = Vposition + d + Fposition;
|
||||||
if(Vnfixed > theconf.maxVsteps || Vnfixed < -theconf.maxVsteps){
|
if(Vnfixed > theconf.maxVsteps || Vnfixed < -theconf.maxVsteps){
|
||||||
snprintf(buf, buflen, FAIL);
|
snprintf(buf, buflen, FAIL);
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
dVmove = d;
|
dVmove = d;
|
||||||
snprintf(buf, buflen, OK);
|
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);
|
snprintf(buf, buflen, "%s", ans);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,10 +29,10 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/syscall.h> // syscall
|
#include <sys/syscall.h> // syscall
|
||||||
#include <unistd.h> // daemon
|
#include <unistd.h> // daemon
|
||||||
#include <usefull_macros.h>
|
|
||||||
|
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "debug.h"
|
||||||
#include "improc.h"
|
#include "improc.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ static char *moveU(const char *val, char *buf, int buflen){
|
|||||||
return retFAIL(buf, buflen);
|
return retFAIL(buf, buflen);
|
||||||
}
|
}
|
||||||
static char *moveV(const char *val, char *buf, int 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);
|
return retFAIL(buf, buflen);
|
||||||
}
|
}
|
||||||
static char *relaycmd(const char *val, char *buf, int 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);
|
DBG("got KEY '%s' with value '%s'", kv, value);
|
||||||
key_value result;
|
key_value result;
|
||||||
par = chk_keyval(kv, value, &result);
|
par = chk_keyval(kv, value, &result);
|
||||||
FREE(kv);
|
free(kv); kv = NULL;
|
||||||
if(par){
|
if(par){
|
||||||
switch(par->type){
|
switch(par->type){
|
||||||
case PAR_INT:
|
case PAR_INT:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user