monado/src/xrt/state_trackers/gui/gui_scene_calibrate.c

225 lines
5.5 KiB
C
Raw Normal View History

2019-09-23 10:46:06 +00:00
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Calibration gui scene.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup gui
*/
#include "util/u_var.h"
#include "util/u_misc.h"
#include "util/u_sink.h"
#ifdef XRT_HAVE_OPENCV
#include "tracking/t_tracking.h"
#endif
#include "xrt/xrt_frame.h"
#include "xrt/xrt_prober.h"
#include "xrt/xrt_tracking.h"
#include "xrt/xrt_frameserver.h"
#include "gui_common.h"
#include "gui_imgui.h"
#include <assert.h>
2019-09-23 10:46:06 +00:00
struct calibration_scene
{
struct gui_scene base;
#ifdef XRT_HAVE_OPENCV
struct t_calibration_params params;
#endif
2019-09-23 10:46:06 +00:00
struct xrt_frame_context *xfctx;
struct xrt_fs *xfs;
size_t mode;
2019-09-23 10:46:06 +00:00
};
/*
*
* Internal functions.
*
*/
static void
draw_texture(struct gui_ogl_texture *tex, bool header)
{
if (tex == NULL) {
return;
}
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None;
if (header && !igCollapsingHeader(tex->name, flags)) {
return;
}
gui_ogl_sink_update(tex);
int w = tex->w / (tex->half ? 2 : 1);
int h = tex->h / (tex->half ? 2 : 1);
ImVec2 size = {w, h};
ImVec2 uv0 = {0, 0};
ImVec2 uv1 = {1, 1};
ImVec4 white = {1, 1, 1, 1};
ImTextureID id = (ImTextureID)(intptr_t)tex->id;
igImage(id, size, uv0, uv1, white, white);
igText("Sequence %u", (uint32_t)tex->seq);
char temp[512];
snprintf(temp, 512, "Half (%s)", tex->name);
igCheckbox(temp, &tex->half);
}
static void
2019-10-09 15:22:34 +00:00
scene_render_video(struct gui_scene *scene, struct gui_program *p)
2019-09-23 10:46:06 +00:00
{
struct calibration_scene *cs = (struct calibration_scene *)scene;
igBegin("Calibration", NULL, 0);
draw_texture(p->texs[0], false);
draw_texture(p->texs[1], true);
for (size_t i = 2; i < ARRAY_SIZE(p->texs); i++) {
draw_texture(p->texs[i], true);
}
igSeparator();
static ImVec2 button_dims = {0, 0};
if (igButton("Exit", button_dims)) {
gui_scene_delete_me(p, &cs->base);
}
igEnd();
}
static void
2019-10-09 15:22:34 +00:00
scene_render_select(struct gui_scene *scene, struct gui_program *p)
{
struct calibration_scene *cs = (struct calibration_scene *)scene;
#ifdef XRT_HAVE_OPENCV
igBegin("Params", NULL, 0);
2019-11-20 23:48:54 +00:00
// clang-format off
2019-11-20 23:46:42 +00:00
igCheckbox("Fisheye Camera (mono only)", &cs->params.use_fisheye);
igSeparator();
igCheckbox("Mirror (no calibration effect)", &cs->params.mirror_rgb_image);
2019-11-20 23:48:54 +00:00
igCheckbox("Save images (mono only)", &cs->params.save_images);
igSeparator();
2019-11-20 23:48:54 +00:00
igInputInt("Wait for # frames", &cs->params.num_wait_for, 1, 5, 0);
igInputInt("Collect # measurements", &cs->params.num_collect_total, 1, 5, 0);
igInputInt("Collect in groups of #", &cs->params.num_collect_restart, 1, 5, 0);
igSeparator();
igComboStr("Board type", (int*)&cs->params.pattern, "Checkers\0Circles\0Asymetric Circles\0\0", 3);
switch (cs->params.pattern) {
case T_BOARD_CHECKERS:
igInputInt("Checkerboard Rows", &cs->params.checkers.rows, 1, 5, 0);
igInputInt("Checkerboard Columns", &cs->params.checkers.cols, 1, 5, 0);
igInputFloat("Checker Size (m)", &cs->params.checkers.size_meters, 0.0005, 0.001, NULL, 0);
igCheckbox("Subpixel", &cs->params.checkers.subpixel_enable);
igInputInt("Subpixel Search Size", &cs->params.checkers.subpixel_size, 1, 5, 0);
break;
case T_BOARD_CIRCLES:
igInputInt("Circle Rows", &cs->params.circles.rows, 1, 5, 0);
igInputInt("Circle Columns", &cs->params.circles.cols, 1, 5, 0);
igInputFloat("Spacing (m)", &cs->params.circles.distance_meters, 0.0005, 0.001, NULL, 0);
break;
case T_BOARD_ASYMMETRIC_CIRCLES:
igInputInt("Circle Rows", &cs->params.asymmetric_circles.rows, 1, 5, 0);
igInputInt("Circle Columns", &cs->params.asymmetric_circles.cols, 1, 5, 0);
igInputFloat("Diagonal spacing (m)", &cs->params.asymmetric_circles.diagonal_distance_meters, 0.0005, 0.001, NULL, 0);
break;
default: assert(false);
}
2019-11-20 23:48:54 +00:00
// clang-format on
static ImVec2 button_dims = {0, 0};
igSeparator();
bool pressed = igButton("Done", button_dims);
igEnd();
if (!pressed) {
return;
}
cs->base.render = scene_render_video;
struct xrt_frame_sink *rgb = NULL;
struct xrt_frame_sink *raw = NULL;
struct xrt_frame_sink *cali = NULL;
p->texs[p->num_texs++] =
gui_ogl_sink_create("Calibration", cs->xfctx, &rgb);
u_sink_create_format_converter(cs->xfctx, XRT_FORMAT_R8G8B8, rgb, &rgb);
u_sink_queue_create(cs->xfctx, rgb, &rgb);
p->texs[p->num_texs++] = gui_ogl_sink_create("Raw", cs->xfctx, &raw);
u_sink_create_format_converter(cs->xfctx, XRT_FORMAT_R8G8B8, raw, &raw);
u_sink_queue_create(cs->xfctx, raw, &raw);
t_calibration_stereo_create(cs->xfctx, &cs->params, rgb, &cali);
u_sink_create_to_yuv_or_yuyv(cs->xfctx, cali, &cali);
u_sink_queue_create(cs->xfctx, cali, &cali);
u_sink_split_create(cs->xfctx, raw, cali, &cali);
// Now that we have setup a node graph, start it.
xrt_fs_stream_start(cs->xfs, cali, cs->mode);
#else
gui_scene_delete_me(p, &cs->base);
#endif
}
2019-09-23 10:46:06 +00:00
static void
2019-10-09 15:22:34 +00:00
scene_destroy(struct gui_scene *scene, struct gui_program *p)
2019-09-23 10:46:06 +00:00
{
struct calibration_scene *cs = (struct calibration_scene *)scene;
if (cs->xfctx != NULL) {
xrt_frame_context_destroy_nodes(cs->xfctx);
cs->xfctx = NULL;
}
free(cs);
}
/*
*
* 'Exported' functions.
*
*/
void
2019-10-09 15:22:34 +00:00
gui_scene_calibrate(struct gui_program *p,
2019-09-23 10:46:06 +00:00
struct xrt_frame_context *xfctx,
struct xrt_fs *xfs,
size_t mode)
{
struct calibration_scene *cs = U_TYPED_CALLOC(struct calibration_scene);
#ifdef XRT_HAVE_OPENCV
struct t_calibration_params def = T_CALIBRATION_DEFAULT_PARAMS;
cs->params = def;
#endif
cs->base.render = scene_render_select;
2019-09-23 10:46:06 +00:00
cs->base.destroy = scene_destroy;
cs->xfctx = xfctx;
cs->xfs = xfs;
cs->mode = mode;
2019-09-23 10:46:06 +00:00
gui_scene_push_front(p, &cs->base);
}