The open source OpenXR runtime
1// Copyright 2019, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief HSV debug viewer code.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup aux_tracking
8 */
9
10#include "util/u_misc.h"
11#include "util/u_debug.h"
12#include "util/u_format.h"
13#include "tracking/t_tracking.h"
14
15#include <opencv2/opencv.hpp>
16
17
18/*
19 *
20 * Defines and structs
21 *
22 */
23
24#define HSV_WIN "HSV Filter Tester"
25
26/*!
27 * An @ref xrt_frame_sink related to debug viewing of HSV.
28 * @implements xrt_frame_sink
29 * @implements xrt_frame_node
30 */
31class DebugHSVViewer
32{
33public:
34 struct xrt_frame_sink base = {};
35 struct xrt_frame_node node = {};
36
37 struct xrt_frame_sink *passthrough;
38
39 cv::Mat bgr;
40
41 int lum_value = 0;
42
43 // No need to initialize these
44 struct t_convert_table yuv_to_rgb_table;
45 struct t_hsv_filter_large_table hsv_large;
46 struct t_hsv_filter_optimized_table hsv_opt;
47};
48
49
50/*
51 *
52 * Debug functions.
53 *
54 */
55
56static void
57process_pixel(bool f1, bool f1_diff, uint8_t *hsv_cap, uint8_t *hsv_opt, uint8_t *hsv_diff, const uint8_t *rgb)
58{
59 if (f1) {
60 hsv_cap[0] = rgb[2];
61 hsv_cap[1] = rgb[1];
62 hsv_cap[2] = rgb[0];
63 } else {
64 hsv_cap[0] = 0;
65 hsv_cap[1] = 0;
66 hsv_cap[2] = 0;
67 }
68
69 if (f1_diff) {
70 hsv_opt[0] = rgb[2];
71 hsv_opt[1] = rgb[1];
72 hsv_opt[2] = rgb[0];
73 } else {
74 hsv_opt[0] = 0;
75 hsv_opt[1] = 0;
76 hsv_opt[2] = 0;
77 }
78
79 if (f1 > f1_diff) {
80 hsv_diff[0] = 0xff;
81 hsv_diff[1] = 0;
82 hsv_diff[2] = 0;
83 } else if (f1 < f1_diff) {
84 hsv_diff[0] = 0;
85 hsv_diff[1] = 0;
86 hsv_diff[2] = 0xff;
87 } else {
88 hsv_diff[0] = 0;
89 hsv_diff[1] = 0;
90 hsv_diff[2] = 0;
91 }
92}
93
94#define SIZE 256
95#define NUM_CHAN 4
96
97static void
98process_frame(DebugHSVViewer &d, struct xrt_frame *xf)
99{
100 uint32_t width = SIZE * 3;
101 uint32_t height = SIZE * NUM_CHAN;
102
103 auto &bgr = d.bgr;
104 if (bgr.rows != (int)height || bgr.cols != (int)width) {
105 bgr = cv::Mat(height, width, CV_8UC3);
106 }
107
108 for (uint32_t yp = 0; yp < SIZE; yp++) {
109 for (int chan = 0; chan < NUM_CHAN; chan++) {
110 auto *hsv_cap = bgr.ptr<uint8_t>(yp + SIZE * chan);
111 auto *hsv_opt = bgr.ptr<uint8_t>(yp + SIZE * chan) + 256 * 3;
112 auto *hsv_diff = bgr.ptr<uint8_t>(yp + SIZE * chan) + 512 * 3;
113 int mask = 1 << chan;
114
115 for (uint32_t xp = 0; xp < SIZE; xp++) {
116 int y = d.lum_value;
117 int u = yp;
118 int v = xp;
119
120 uint8_t *rgb = d.yuv_to_rgb_table.v[y][u][v];
121 uint8_t large = d.hsv_large.v[y][u][v];
122 uint8_t opt = t_hsv_filter_sample(&d.hsv_opt, y, u, v);
123
124 large = (large & mask) != 0;
125 opt = (opt & mask) != 0;
126
127 process_pixel(large, opt, hsv_cap, hsv_opt, hsv_diff, rgb);
128
129 hsv_cap += 3;
130 hsv_opt += 3;
131 hsv_diff += 3;
132 }
133 }
134 }
135
136 cv::imshow(HSV_WIN, bgr);
137}
138
139
140/*
141 *
142 * Exported functions.
143 *
144 */
145
146extern "C" void
147t_debug_hsv_viewer_frame(struct xrt_frame_sink *xsink, struct xrt_frame *xf)
148{
149 auto &d = *(class DebugHSVViewer *)xsink;
150
151 process_frame(d, xf);
152
153 d.passthrough->push_frame(d.passthrough, xf);
154}
155
156extern "C" void
157t_debug_hsv_viewer_break_apart(struct xrt_frame_node *node)
158{}
159
160extern "C" void
161t_debug_hsv_viewer_destroy(struct xrt_frame_node *node)
162{
163 auto *d = container_of(node, DebugHSVViewer, node);
164 delete d;
165}
166
167extern "C" int
168t_debug_hsv_viewer_create(struct xrt_frame_context *xfctx,
169 struct xrt_frame_sink *passthrough,
170 struct xrt_frame_sink **out_sink)
171{
172 auto &d = *(new DebugHSVViewer());
173
174 cv::namedWindow(HSV_WIN);
175
176 cv::createTrackbar("Luma", HSV_WIN, &d.lum_value, 255, NULL);
177
178 cv::startWindowThread();
179
180 d.base.push_frame = t_debug_hsv_viewer_frame;
181 d.node.break_apart = t_debug_hsv_viewer_break_apart;
182 d.node.destroy = t_debug_hsv_viewer_destroy;
183 d.passthrough = passthrough;
184
185 t_convert_make_y8u8v8_to_r8g8b8(&d.yuv_to_rgb_table);
186 struct t_hsv_filter_params params = T_HSV_DEFAULT_PARAMS();
187 t_hsv_build_large_table(¶ms, &d.hsv_large);
188 t_hsv_build_optimized_table(¶ms, &d.hsv_opt);
189
190 xrt_frame_context_add(xfctx, &d.node);
191
192 *out_sink = &d.base;
193
194 return 0;
195}