forked from IntelRealSense/librealsense
-
Notifications
You must be signed in to change notification settings - Fork 2
/
pyrs_processing.cpp
174 lines (153 loc) · 12.9 KB
/
pyrs_processing.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* License: Apache 2.0. See LICENSE file in root directory.
Copyright(c) 2017 Intel Corporation. All Rights Reserved. */
#include "python.hpp"
#include "../include/librealsense2/hpp/rs_processing.hpp"
void init_processing(py::module &m) {
/** rs_processing.hpp **/
py::class_<rs2::frame_source> frame_source(m, "frame_source", "The source used to generate frames, which is usually done by the low level driver for each sensor. "
"frame_source is one of the parameters of processing_block's callback function, which can be used to re-generate the "
"frame and via frame_ready invoke another callback function to notify application frame is ready.");
frame_source.def("allocate_video_frame", &rs2::frame_source::allocate_video_frame, "Allocate a new video frame with given params",
"profile"_a, "original"_a, "new_bpp"_a = 0, "new_width"_a = 0,
"new_height"_a = 0, "new_stride"_a = 0, "frame_type"_a = RS2_EXTENSION_VIDEO_FRAME)
.def("allocate_points", &rs2::frame_source::allocate_points, "profile"_a,
"original"_a) // No docstring in C++
.def("allocate_composite_frame", &rs2::frame_source::allocate_composite_frame,
"Allocate composite frame with given params", "frames"_a)
.def("frame_ready", &rs2::frame_source::frame_ready, "Invoke the "
"callback funtion informing the frame is ready.", "result"_a);
// Not binding frame_processor_callback, templated
py::class_<rs2::frame_queue> frame_queue(m, "frame_queue", "Frame queues are the simplest cross-platform "
"synchronization primitive provided by librealsense to help "
"developers who are not using async APIs.");
frame_queue.def(py::init<>())
.def(py::init<unsigned int, bool>(), "capacity"_a, "keep_frames"_a = false)
.def("enqueue", &rs2::frame_queue::enqueue, "Enqueue a new frame into the queue.", "f"_a)
.def("wait_for_frame", &rs2::frame_queue::wait_for_frame, "Wait until a new frame "
"becomes available in the queue and dequeue it.", "timeout_ms"_a = 5000, py::call_guard<py::gil_scoped_release>())
.def("poll_for_frame", [](const rs2::frame_queue &self) {
rs2::frame frame;
self.poll_for_frame(&frame);
return frame;
}, "Poll if a new frame is available and dequeue it if it is")
.def("try_wait_for_frame", [](const rs2::frame_queue &self, unsigned int timeout_ms) {
rs2::frame frame;
auto success = self.try_wait_for_frame(&frame, timeout_ms);
return std::make_tuple(success, frame);
}, "timeout_ms"_a = 5000, py::call_guard<py::gil_scoped_release>()) // No docstring in C++
.def("__call__", &rs2::frame_queue::operator(), "Identical to calling enqueue.", "f"_a)
.def("capacity", &rs2::frame_queue::capacity, "Return the capacity of the queue.")
.def("keep_frames", &rs2::frame_queue::keep_frames, "Return whether or not the queue calls keep on enqueued frames.");
py::class_<rs2::processing_block, rs2::options> processing_block(m, "processing_block", "Define the processing block workflow, inherit this class to "
"generate your own processing_block.");
processing_block.def(py::init([](std::function<void(rs2::frame, rs2::frame_source&)> processing_function) {
return new rs2::processing_block(processing_function);
}), "processing_function"_a)
.def("start", [](rs2::processing_block& self, std::function<void(rs2::frame)> f) {
self.start(f);
}, "Start the processing block with callback function to inform the application the frame is processed.", "callback"_a)
.def("invoke", &rs2::processing_block::invoke, "Ask processing block to process the frame", "f"_a)
.def("supports", (bool (rs2::processing_block::*)(rs2_camera_info) const) &rs2::processing_block::supports, "Check if a specific camera info field is supported.")
.def("get_info", &rs2::processing_block::get_info, "Retrieve camera specific information, like versions of various internal components.");
/*.def("__call__", &rs2::processing_block::operator(), "f"_a)*/
// supports(camera_info) / get_info(camera_info)?
py::class_<rs2::filter, rs2::processing_block, rs2::filter_interface> filter(m, "filter", "Define the filter workflow, inherit this class to generate your own filter.");
filter.def(py::init([](std::function<void(rs2::frame, rs2::frame_source&)> filter_function, int queue_size) {
return new rs2::filter(filter_function, queue_size);
}), "filter_function"_a, "queue_size"_a = 1)
.def(BIND_DOWNCAST(filter, decimation_filter))
.def(BIND_DOWNCAST(filter, disparity_transform))
.def(BIND_DOWNCAST(filter, hole_filling_filter))
.def(BIND_DOWNCAST(filter, spatial_filter))
.def(BIND_DOWNCAST(filter, temporal_filter))
.def(BIND_DOWNCAST(filter, threshold_filter))
.def(BIND_DOWNCAST(filter, zero_order_invalidation))
.def("__nonzero__", &rs2::filter::operator bool); // No docstring in C++
// get_queue?
// is/as?
py::class_<rs2::pointcloud, rs2::filter> pointcloud(m, "pointcloud", "Generates 3D point clouds based on a depth frame. Can also map textures from a color frame.");
pointcloud.def(py::init<>())
.def(py::init<rs2_stream, int>(), "stream"_a, "index"_a = 0)
.def("calculate", &rs2::pointcloud::calculate, "Generate the pointcloud and texture mappings of depth map.", "depth"_a)
.def("map_to", &rs2::pointcloud::map_to, "Map the point cloud to the given color frame.", "mapped"_a);
py::class_<rs2::yuy_decoder, rs2::filter> yuy_decoder(m, "yuy_decoder", "Converts frames in raw YUY format to RGB. This conversion is somewhat costly, "
"but the SDK will automatically try to use SSE2, AVX, or CUDA instructions where available to "
"get better performance. Othere implementations (GLSL, OpenCL, Neon, NCS) should follow.");
yuy_decoder.def(py::init<>());
py::class_<rs2::threshold_filter, rs2::filter> threshold(m, "threshold_filter", "Depth thresholding filter. By controlling min and "
"max options on the block, one could filter out depth values that are either too large "
"or too small, as a software post-processing step");
threshold.def(py::init<float, float>(), "min_dist"_a = 0.15f, "max_dist"_a = 4.f);
py::class_<rs2::units_transform, rs2::filter> units_transform(m, "units_transform");
units_transform.def(py::init<>());
// rs2::asynchronous_syncer
py::class_<rs2::syncer> syncer(m, "syncer", "Sync instance to align frames from different streams");
syncer.def(py::init<int>(), "queue_size"_a = 1)
.def("wait_for_frames", &rs2::syncer::wait_for_frames, "Wait until a coherent set "
"of frames becomes available", "timeout_ms"_a = 5000, py::call_guard<py::gil_scoped_release>())
.def("poll_for_frames", [](const rs2::syncer &self) {
rs2::frameset frames;
self.poll_for_frames(&frames);
return frames;
}, "Check if a coherent set of frames is available")
.def("try_wait_for_frames", [](const rs2::syncer &self, unsigned int timeout_ms) {
rs2::frameset fs;
auto success = self.try_wait_for_frames(&fs, timeout_ms);
return std::make_tuple(success, fs);
}, "timeout_ms"_a = 5000, py::call_guard<py::gil_scoped_release>()); // No docstring in C++
/*.def("__call__", &rs2::syncer::operator(), "frame"_a)*/
py::class_<rs2::align, rs2::filter> align(m, "align", "Performs alignment between depth image and another image.");
align.def(py::init<rs2_stream>(), "To perform alignment of a depth image to the other, set the align_to parameter with the other stream type.\n"
"To perform alignment of a non depth image to a depth image, set the align_to parameter to RS2_STREAM_DEPTH.\n"
"Camera calibration and frame's stream type are determined on the fly, according to the first valid frameset passed to process().", "align_to"_a)
.def("process", (rs2::frameset(rs2::align::*)(rs2::frameset)) &rs2::align::process, "Run thealignment process on the given frames to get an aligned set of frames", "frames"_a);
py::class_<rs2::colorizer, rs2::filter> colorizer(m, "colorizer", "Colorizer filter generates color images based on input depth frame");
colorizer.def(py::init<>())
.def(py::init<float>(), "Possible values for color_scheme:\n"
"0 - Jet\n"
"1 - Classic\n"
"2 - WhiteToBlack\n"
"3 - BlackToWhite\n"
"4 - Bio\n"
"5 - Cold\n"
"6 - Warm\n"
"7 - Quantized\n"
"8 - Pattern", "color_scheme"_a)
.def("colorize", &rs2::colorizer::colorize, "Start to generate color image base on depth frame", "depth"_a)
/*.def("__call__", &rs2::colorizer::operator())*/;
py::class_<rs2::decimation_filter, rs2::filter> decimation_filter(m, "decimation_filter", "Performs downsampling by using the median with specific kernel size.");
decimation_filter.def(py::init<>())
.def(py::init<float>(), "magnitude"_a);
py::class_<rs2::temporal_filter, rs2::filter> temporal_filter(m, "temporal_filter", "Temporal filter smooths the image by calculating multiple frames "
"with alpha and delta settings. Alpha defines the weight of current frame, and delta defines the"
"threshold for edge classification and preserving.");
temporal_filter.def(py::init<>())
.def(py::init<float, float, int>(), "Possible values for persistence_control:\n"
"1 - Valid in 8/8 - Persistency activated if the pixel was valid in 8 out of the last 8 frames\n"
"2 - Valid in 2 / last 3 - Activated if the pixel was valid in two out of the last 3 frames\n"
"3 - Valid in 2 / last 4 - Activated if the pixel was valid in two out of the last 4 frames\n"
"4 - Valid in 2 / 8 - Activated if the pixel was valid in two out of the last 8 frames\n"
"5 - Valid in 1 / last 2 - Activated if the pixel was valid in one of the last two frames\n"
"6 - Valid in 1 / last 5 - Activated if the pixel was valid in one out of the last 5 frames\n"
"7 - Valid in 1 / last 8 - Activated if the pixel was valid in one out of the last 8 frames\n"
"8 - Persist Indefinitely - Persistency will be imposed regardless of the stored history(most aggressive filtering)",
"smooth_alpha"_a, "smooth_delta"_a, "persistence_control"_a);
py::class_<rs2::spatial_filter, rs2::filter> spatial_filter(m, "spatial_filter", "Spatial filter smooths the image by calculating frame with alpha and delta settings. "
"Alpha defines the weight of the current pixel for smoothing, and is bounded within [25..100]%. Delta "
"defines the depth gradient below which the smoothing will occur as number of depth levels.");
spatial_filter.def(py::init<>())
.def(py::init<float, float, float, float>(), "smooth_alpha"_a, "smooth_delta"_a, "magnitude"_a, "hole_fill"_a);;
py::class_<rs2::disparity_transform, rs2::filter> disparity_transform(m, "disparity_transform", "Converts from depth representation "
"to disparity representation and vice - versa in depth frames");
disparity_transform.def(py::init<bool>(), "transform_to_disparity"_a = true);
py::class_<rs2::zero_order_invalidation, rs2::filter> zero_order_invalidation(m, "zero_order_invalidation", "Fixes the zero order artifact");
zero_order_invalidation.def(py::init<>());
py::class_<rs2::hole_filling_filter, rs2::filter> hole_filling_filter(m, "hole_filling_filter", "The processing performed depends on the selected hole filling mode.");
hole_filling_filter.def(py::init<>())
.def(py::init<int>(), "Possible values for mode:\n"
"0 - fill_from_left - Use the value from the left neighbor pixel to fill the hole\n"
"1 - farest_from_around - Use the value from the neighboring pixel which is furthest away from the sensor\n"
"2 - nearest_from_around - -Use the value from the neighboring pixel closest to the sensor", "mode"_a);
// rs2::rates_printer
/** end rs_processing.hpp **/
}