Skip to content

Commit

Permalink
Add option to save data to file
Browse files Browse the repository at this point in the history
This function will save data file that is compatible with gnuplot.
  • Loading branch information
norihiro committed Dec 31, 2021
1 parent 144e143 commit 4eba2d7
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 28 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(LINUX_MAINTAINER_EMAIL "[email protected]")

option(WITH_PTZ_TCP "Enable to connect PTZ camera through TCP socket" ON)
option(ENABLE_MONITOR_USER "Enable monitor source for user" OFF)
option(ENABLE_DEBUG_DATA "Enable property to save error and control data" OFF)

set(CMAKE_PREFIX_PATH "${QTDIR}")
set(CMAKE_AUTOMOC ON)
Expand Down
61 changes: 45 additions & 16 deletions doc/properties-ptz.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,6 @@ The nonlinear band makes smooth connection from the dead band to the linear rang
### Attenuation time for lost face
After the face is lost, integral term will be attenuated by this time. The dimension is time and the unit is s.

## Debug
These properties enables how the face detection and tracking works.
Note that these features are automatically turned off when the source is displayed on the program of OBS Studio.
You can keep enable the checkboxes and keep monitoring the detection accuracy before the scene goes to the program.

### Show face detection results
**Deprecated**
If enabled, face detection and tracking results are shown.
The face detection results are displayed in blue boxes.
The Tracking results are displayed in green boxes.

### Always show information
**Deprecated**
If enabled, debugging properties listed above are effective even if the source is displayed on the program.
This will be useful to make a demonstration of face-tracker itself.

## Output
This property group configure how to connect to the PTZ camera.

Expand Down Expand Up @@ -153,3 +137,48 @@ It might be useful if you camera is mounted on ceil.
Just in c ase the zoom control behave opposite directon, check this.
You should not check this in most cases.
This is a deplicated option.

## Debug
These properties enables how the face detection and tracking works.
Note that these features are automatically turned off when the source is displayed on the program of OBS Studio.
You can keep enable the checkboxes and keep monitoring the detection accuracy before the scene goes to the program.

### Show face detection results
**Deprecated**
If enabled, face detection and tracking results are shown.
The face detection results are displayed in blue boxes.
The Tracking results are displayed in green boxes.

### Always show information
**Deprecated**
If enabled, debugging properties listed above are effective even if the source is displayed on the program.
This will be useful to make a demonstration of face-tracker itself.

### Save correlation tracker, calculated error, control data to file
**Not available for released version**
Save internal calculation into the specified file for each.
This option is not available without building with `ENABLE_DEBUG_DATA`
but still can be set through obs-websocket or manually editing the scene file to add a text property with a file name to be written.
To disable it back, remove the property or set zero-length text.

#### Correlation tracker
Property name: `debug_data_tracker`

The data contains time in second, 3 coordinates (X, Y, Z), and score of the correlation tracker.
The X and Y coordinates are the center of the face.
The Z coordinate is a square-root of the area.
Sometimes multiple correlation trackers run at the same time. In that case, multiple lines are written at the same timing.

#### Calculated error
Property name: `debug_data_error`

The data contains time in second, 3 coordinates (X, Y, Z).
The calculated error is the adjusted measure with current resolution, the cropped region when the frame was rendered, and user-specified tracking target.
0-value indicates the face is well aligned and positive or negative value indicates the cropped region need to be moved.

#### Control
Property name: `debug_data_control`

The data contains time in second, 3 coordinates (X, Y, Z), and another set of 3 coordinates.
The first set of the coordinates is a linear floating-point value of the control signal.
The second set of the coordinates is an integer value that should go to the PTZ device.
29 changes: 29 additions & 0 deletions doc/properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,32 @@ This is useful to check how much margins are there around the cropped area.
### Always show information
If enabled, debugging properties listed above are effective even if the source is displayed on the program.
This will be useful to make a demonstration of face-tracker itself.

### Save correlation tracker, calculated error, control data to file
**Not available for released version**
Save internal calculation into the specified file for each.
This option is not available without building with `ENABLE_DEBUG_DATA`
but still can be set through obs-websocket or manually editing the scene file to add a text property with a file name to be written.
To disable it back, remove the property or set zero-length text.

#### Correlation tracker
Property name: `debug_data_tracker`

The data contains time in second, 3 coordinates (X, Y, Z), and score of the correlation tracker.
The X and Y coordinates are the center of the face.
The Z coordinate is a square-root of the area.
Sometimes multiple correlation trackers run at the same time. In that case, multiple lines are written at the same timing.

#### Calculated error
Property name: `debug_data_error`

The data contains time in second, 3 coordinates (X, Y, Z).
The calculated error is the adjusted measure with current resolution, the cropped region when the frame was rendered, and user-specified tracking target.
0-value indicates the face is well aligned and positive or negative value indicates the cropped region need to be moved.

#### Control
Property name: `debug_data_control`

The data contains time in second, 3 coordinates (X, Y, Z).
The X and Y coordinates are the center of the cropped region.
The Z coordinate is a square-root of the area of the cropped region.
55 changes: 48 additions & 7 deletions src/face-tracker-ptz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
#endif
#include "dummy-backend.hpp"

#define debug_track(fmt, ...) // blog(LOG_INFO, fmt, __VA_ARGS__)

#define PTZ_MAX_X 0x18
#define PTZ_MAX_Y 0x14
#define PTZ_MAX_Z 0x07
Expand Down Expand Up @@ -210,6 +208,10 @@ static void ftptz_update(void *data, obs_data_t *settings)
s->debug_notrack = obs_data_get_bool(settings, "debug_notrack");
s->debug_always_show = obs_data_get_bool(settings, "debug_always_show");

debug_data_open(&s->debug_data_tracker, &s->debug_data_tracker_last, settings, "debug_data_tracker");
debug_data_open(&s->debug_data_error, &s->debug_data_error_last, settings, "debug_data_error");
debug_data_open(&s->debug_data_control, &s->debug_data_control_last, settings, "debug_data_control");

s->ptz_max_x = obs_data_get_int(settings, "ptz_max_x");
s->ptz_max_y = obs_data_get_int(settings, "ptz_max_y");
s->ptz_max_z = obs_data_get_int(settings, "ptz_max_z");
Expand Down Expand Up @@ -276,6 +278,15 @@ static void ftptz_destroy(void *data)

delete s->ftm;
bfree(s->ptz_type);
if (s->debug_data_tracker)
fclose(s->debug_data_tracker);
if (s->debug_data_error)
fclose(s->debug_data_error);
if (s->debug_data_control)
fclose(s->debug_data_control);
bfree(s->debug_data_tracker_last);
bfree(s->debug_data_error_last);
bfree(s->debug_data_control_last);

bfree(s);
}
Expand Down Expand Up @@ -392,8 +403,6 @@ static obs_properties_t *ftptz_properties(void *data)

{
obs_properties_t *pp = obs_properties_create();
obs_properties_add_bool(pp, "debug_faces", "Show face detection results");
obs_properties_add_bool(pp, "debug_always_show", "Always show information (useful for demo)");
obs_property_t *p = obs_properties_add_list(pp, "ptz-type", obs_module_text("PTZ Type"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(p, obs_module_text("None"), "dummy");
obs_property_list_add_string(p, obs_module_text("through PTZ Controls"), "obsptz");
Expand All @@ -413,6 +422,21 @@ static obs_properties_t *ftptz_properties(void *data)
obs_properties_add_group(props, "output", obs_module_text("Output"), OBS_GROUP_NORMAL, pp);
}

{
obs_properties_t *pp = obs_properties_create();
obs_properties_add_bool(pp, "debug_faces", "Show face detection results");
obs_properties_add_bool(pp, "debug_always_show", "Always show information (useful for demo)");
#ifdef ENABLE_DEBUG_DATA
obs_properties_add_path(pp, "debug_data_tracker", "Save correlation tracker data to file",
OBS_PATH_FILE_SAVE, DEBUG_DATA_PATH_FILTER, NULL );
obs_properties_add_path(pp, "debug_data_error", "Save calculated error data to file",
OBS_PATH_FILE_SAVE, DEBUG_DATA_PATH_FILTER, NULL );
obs_properties_add_path(pp, "debug_data_control", "Save control data to file",
OBS_PATH_FILE_SAVE, DEBUG_DATA_PATH_FILTER, NULL );
#endif
obs_properties_add_group(props, "debug", obs_module_text("Debugging"), OBS_GROUP_NORMAL, pp);
}

return props;
}

Expand Down Expand Up @@ -639,7 +663,13 @@ static void tick_filter(struct face_tracker_ptz *s, float second)
else if (n > +u_max[i]) n = +u_max[i];
s->u[i] = n;
}
debug_track("tick_filter: u: %d %d %d uf: %f %f %f", s->u[0], s->u[1], s->u[2], uf.v[0], uf.v[1], uf.v[2]);

if (s->debug_data_control) {
fprintf(s->debug_data_control, "%f\t%f\t%f\t%f\t%d\t%d\t%d\n",
os_gettime_ns() * 1e-9,
uf.v[0], uf.v[1], uf.v[2],
s->u[0], s->u[1], s->u[2] );
}
}

static void ftf_activate(void *data)
Expand Down Expand Up @@ -730,6 +760,7 @@ static inline void calculate_error(struct face_tracker_ptz *s)
auto &tracker_rects = s->ftm->tracker_rects;
for (int i=0; i<tracker_rects.size(); i++) {
f3 r (tracker_rects[i].rect);
float score = tracker_rects[i].rect.score;

if (s->ftm->landmark_detection_data) {
pointf_s center = landmark_center(tracker_rects[i].landmark);
Expand All @@ -742,14 +773,18 @@ static inline void calculate_error(struct face_tracker_ptz *s)
r.v[2] = sqrtf(area * (float)(4.0f / M_PI));
}

if (s->debug_data_tracker) {
fprintf(s->debug_data_tracker, "%f\t%f\t%f\t%f\t%f\n",
os_gettime_ns() * 1e-9,
r.v[0], r.v[1], r.v[2], score );
}

r.v[0] -= get_width(tracker_rects[i].crop_rect) * s->track_x;
r.v[1] += get_height(tracker_rects[i].crop_rect) * s->track_y;
r.v[2] /= s->track_z;
f3 w (tracker_rects[i].crop_rect);
float score = tracker_rects[i].rect.score;

f3 e = (r-w) * score;
debug_track("calculate_error: %d %f %f %f %f", i, e.v[0], e.v[1], e.v[2], score);
if (score>0.0f && !isnan(e)) {
e_tot += e;
sc_tot += score;
Expand All @@ -762,6 +797,12 @@ static inline void calculate_error(struct face_tracker_ptz *s)
else
s->detect_err = f3(0, 0, 0);
s->face_found = found;

if (s->debug_data_error) {
fprintf(s->debug_data_error, "%f\t%f\t%f\t%f\n",
os_gettime_ns() * 1e-9,
s->detect_err.v[0], s->detect_err.v[1], s->detect_err.v[2] );
}
}

static struct obs_source_frame *ftptz_filter_video(void *data, struct obs_source_frame *frame)
Expand Down
6 changes: 6 additions & 0 deletions src/face-tracker-ptz.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ struct face_tracker_ptz
bool debug_faces;
bool debug_notrack;
bool debug_always_show;
FILE *debug_data_tracker;
FILE *debug_data_error;
FILE *debug_data_control;
char *debug_data_tracker_last;
char *debug_data_error_last;
char *debug_data_control_last;

char *ptz_type;
int ptz_max_x, ptz_max_y, ptz_max_z;
Expand Down
45 changes: 40 additions & 5 deletions src/face-tracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
#include "face-tracker-manager.hpp"
#include "source_list.h"

// #define debug_track(fmt, ...) blog(LOG_INFO, fmt, __VA_ARGS__)
#define debug_track(fmt, ...)

static gs_effect_t *effect_ft = NULL;

static inline void scale_texture(struct face_tracker_filter *s, float scale);
Expand Down Expand Up @@ -99,6 +96,10 @@ static void ftf_update(void *data, obs_data_t *settings)
s->debug_faces = obs_data_get_bool(settings, "debug_faces");
s->debug_notrack = obs_data_get_bool(settings, "debug_notrack");
s->debug_always_show = obs_data_get_bool(settings, "debug_always_show");

debug_data_open(&s->debug_data_tracker, &s->debug_data_tracker_last, settings, "debug_data_tracker");
debug_data_open(&s->debug_data_error, &s->debug_data_error_last, settings, "debug_data_error");
debug_data_open(&s->debug_data_control, &s->debug_data_control_last, settings, "debug_data_control");
}

static void fts_update(void *data, obs_data_t *settings)
Expand Down Expand Up @@ -180,6 +181,15 @@ static void ftf_destroy(void *data)

bfree(s->target_name);
obs_weak_source_release(s->target_ref);
if (s->debug_data_tracker)
fclose(s->debug_data_tracker);
if (s->debug_data_error)
fclose(s->debug_data_error);
if (s->debug_data_control)
fclose(s->debug_data_control);
bfree(s->debug_data_tracker_last);
bfree(s->debug_data_error_last);
bfree(s->debug_data_control_last);

bfree(s);
}
Expand Down Expand Up @@ -278,6 +288,14 @@ static obs_properties_t *ftf_properties(void *data)
obs_properties_add_bool(pp, "debug_faces", "Show face detection results");
obs_properties_add_bool(pp, "debug_notrack", "Stop tracking faces");
obs_properties_add_bool(pp, "debug_always_show", "Always show information (useful for demo)");
#ifdef ENABLE_DEBUG_DATA
obs_properties_add_path(pp, "debug_data_tracker", "Save correlation tracker data to file",
OBS_PATH_FILE_SAVE, DEBUG_DATA_PATH_FILTER, NULL );
obs_properties_add_path(pp, "debug_data_error", "Save calculated error data to file",
OBS_PATH_FILE_SAVE, DEBUG_DATA_PATH_FILTER, NULL );
obs_properties_add_path(pp, "debug_data_control", "Save control data to file",
OBS_PATH_FILE_SAVE, DEBUG_DATA_PATH_FILTER, NULL );
#endif
obs_properties_add_group(props, "debug", obs_module_text("Debugging"), OBS_GROUP_NORMAL, pp);
}

Expand Down Expand Up @@ -376,6 +394,12 @@ static void tick_filter(struct face_tracker_filter *s, float second)
}
}

if (s->debug_data_control) {
fprintf(s->debug_data_control, "%f\t%f\t%f\t%f\n",
os_gettime_ns() * 1e-9,
u.v[0], u.v[1], u.v[2] );
}

s->ftm->crop_cur = f3_to_rectf(u, s->width_with_aspect, s->height_with_aspect);
}

Expand Down Expand Up @@ -610,6 +634,7 @@ static inline void calculate_error(struct face_tracker_filter *s)
auto &tracker_rects = s->ftm->tracker_rects;
for (int i=0; i<tracker_rects.size(); i++) {
f3 r (tracker_rects[i].rect);
float score = tracker_rects[i].rect.score;

if (s->ftm->landmark_detection_data) {
pointf_s center = landmark_center(tracker_rects[i].landmark);
Expand All @@ -622,15 +647,19 @@ static inline void calculate_error(struct face_tracker_filter *s)
r.v[2] = sqrtf(area * (float)(4.0f / M_PI));
}

if (s->debug_data_tracker) {
fprintf(s->debug_data_tracker, "%f\t%f\t%f\t%f\t%f\n",
os_gettime_ns() * 1e-9,
r.v[0], r.v[1], r.v[2], score );
}

r.v[0] -= get_width(tracker_rects[i].crop_rect) * s->track_x;
r.v[1] += get_height(tracker_rects[i].crop_rect) * s->track_y;
r.v[2] /= s->track_z;
r = ensure_range(r, s);
f3 w (tracker_rects[i].crop_rect);
float score = tracker_rects[i].rect.score;

f3 e = (r-w) * score;
debug_track("calculate_error: %d %f %f %f %f", i, e.v[0], e.v[1], e.v[2], score);
if (score>0.0f && !isnan(e)) {
e_tot += e;
sc_tot += score;
Expand All @@ -642,6 +671,12 @@ static inline void calculate_error(struct face_tracker_filter *s)
s->detect_err = e_tot * (1.0f / sc_tot);
else
s->detect_err = f3(0, 0, 0);

if (s->debug_data_error) {
fprintf(s->debug_data_error, "%f\t%f\t%f\t%f\n",
os_gettime_ns() * 1e-9,
s->detect_err.v[0], s->detect_err.v[1], s->detect_err.v[2] );
}
}

static inline void draw_sprite_crop(float width, float height, float x0, float y0, float x1, float y1);
Expand Down
6 changes: 6 additions & 0 deletions src/face-tracker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ struct face_tracker_filter
bool debug_faces;
bool debug_notrack;
bool debug_always_show;
FILE *debug_data_tracker;
FILE *debug_data_error;
FILE *debug_data_control;
char *debug_data_tracker_last;
char *debug_data_error_last;
char *debug_data_control_last;

bool is_paused;
obs_hotkey_pair_id hotkey_pause;
Expand Down
Loading

0 comments on commit 4eba2d7

Please sign in to comment.