diff --git a/SDK/C/include/ftl/ftl.h b/SDK/C/include/ftl/ftl.h index 2820e2436ce1be05cbad2668cd44e8e9d5738838..6a9afabeb5f359e8eb6b3b1ee266f517793592fb 100644 --- a/SDK/C/include/ftl/ftl.h +++ b/SDK/C/include/ftl/ftl.h @@ -32,7 +32,11 @@ enum ftlError_t { FTLERROR_STREAM_BAD_IMAGE_SIZE, FTLERROR_STREAM_NO_INTRINSICS, FTLERROR_STREAM_NO_DATA, - FTLERROR_STREAM_DUPLICATE + FTLERROR_STREAM_BAD_SOURCE, + FTLERROR_STREAM_DUPLICATE, + FTLERROR_OPERATOR_MISSING_CHANNEL, + FTLERROR_OPERATOR_INVALID_FRAME, + FTLERROR_OPERATOR_BAD_FORMAT }; enum ftlChannel_t { @@ -97,6 +101,11 @@ enum ftlImageFormat_t { FTLIMAGE_RGB_FLOAT // Used by Blender }; +enum ftlPipeline_t { + FTLPIPE_DEPTH, + FTLPIPE_RECONSTRUCT +}; + #ifdef __cplusplus extern "C" { #endif @@ -107,20 +116,66 @@ extern "C" { */ ftlError_t ftlGetLastStreamError(ftlStream_t stream); +const char *ftlGetErrorString(ftlError_t err); + // ==== FTL Stream API ========================================================= /** * Create a new file or net stream from a URI. This is for writing or sending - * data and makes a write only stream. + * data and makes a write only stream. Note that a NULL uri string is valid + * and will result in an in-memory stream to allow for temporary framesets + * that might then be transformed or rendered into an actual output stream. */ ftlStream_t ftlCreateWriteStream(const char *uri); /** * Open an existing file or network stream from the URI. These streams are - * read only. + * read only. The URI can also be a device URI. */ ftlStream_t ftlCreateReadStream(const char *uri); +/** + * Set a configurable property for this stream. The `name` parameter is the + * path part of a configurable URI, this is prepended with the streams internal + * URI so that this path is relative to the stream object. + */ +ftlError_t ftlSetConfigString(ftlStream_t stream, const char *name, const char *value); + +/** + * Set a configurable property for this stream. The `name` parameter is the + * path part of a configurable URI, this is prepended with the streams internal + * URI so that this path is relative to the stream object. An example: + * `ftlSetConfigInt(stream, "sender/codec", 2);` + * + * The example makes the streams encoder use HEVC codec. + */ +ftlError_t ftlSetConfigInt(ftlStream_t stream, const char *name, int value); + +ftlError_t ftlSetConfigFloat(ftlStream_t stream, const char *name, float value); + +ftlError_t ftlSetConfigJSON(ftlStream_t stream, const char *name, const char *json); + +/** + * Set a configurable property for this stream. The `name` parameter is the + * path part of a configurable URI, this is prepended with the streams internal + * URI so that this path is relative to the stream object. An example: + * `ftlSetConfigBool(stream, "sender/lossless", false);` + * + * The example makes the streams encoder use lossy encoding. + */ +ftlError_t ftlSetConfigBool(ftlStream_t stream, const char *name, bool value); + +/** + * General write function to put any data into a frames channel. This could + * be used instead of `ftlImageWrite` or `ftlPoseWrite`, for example. + */ +//ftlError_t ftlWrite(ftlStream_t stream, int32_t sourceId, ftlChannel_t channel, ftlDataType_t type, int32_t size, const void *data); + +/** + * Read data from stream source channel. + */ +//ftlError_t ftlRead(ftlStream_t stream, int32_t sourceId, ftlChannel_t channel, ftlDataType_t type, int32_t *size, void *data); + /** * Write raw image data to a frame. The width and height of * the image contained in `data` are contained within the intrinsics data which @@ -189,6 +244,86 @@ ftlError_t ftlIntrinsicsWriteRight(ftlStream_t stream, int32_t sourceId, int32_t */ ftlError_t ftlDestroyStream(ftlStream_t stream); +// ==== Operator functions ===================================================== + +/** + * Enable a pipeline to be applied before the current frameset is encoded into + * the stream. A frameset is only encoded and streamed after a call to + * `ftlNextFrame` or `ftlDestroyStream`, therefore this can be enabled any time + * before the first such call. Multiple pipelines can be enabled and will be + * applied in the order enabled. Default settings for pipelines can be + * changed using `ftlSetConfig...` functions with a URI of "pipes/depth/...", + * for example. + */ +ftlError_t ftlEnablePipeline(ftlStream_t stream, ftlPipeline_t pipeline); + +ftlError_t ftlDisablePipeline(ftlStream_t stream, ftlPipeline_t pipeline); + +/** + * Mark an additional channel as needing saving to the stream. The results of + * various pipelines produce channels in addition to the `ftlImageWrite` + * function, these need to be selected here. + */ +ftlError_t ftlSelect(ftlStream_t stream, ftlChannel_t channel); + +/** + * Apply the depth operator to a frameset to generate a depth channel. This + * requires that the frames already have a left and right channel. + */ +//ftlError_t ftlDepth(ftlStream_t stream); + +/** + * Remove occlusions from a depth map. The `data` passed is a + * right depth image with same resolution as in the intrinsics. The `channel` + * parameter says which channel in the frame contains the depth map to compare + * against, allowing ground truth channel to be used. + */ +ftlError_t ftlRemoveOcclusion(ftlStream_t stream, int32_t sourceId, ftlChannel_t channel, uint32_t pitch, const float *data); + +/** + * Instead of removing occluded pixels, this will add a bit to the mask channel + * to indicate an occlusion. It also implicitely selects the mask channel for + * encoding into the stream. + */ +ftlError_t ftlMaskOcclusion(ftlStream_t stream, int32_t sourceId, ftlChannel_t channel, uint32_t pitch, const float *data); + +/** + * Apply a discontinuity detection to the specified channel. The given channel + * must be a depth map. The operator adds a discontinuity flag to the mask + * channel. + */ +//ftlError_t ftlDiscontinuity(ftlStream_t stream, ftlChannel_t channel); + +/** + * Performs a frameset reconstruction on the current stream frameset. This + * updates and modifies depths maps. The depth channel must exist for this to + * work, if not then it will run `ftlDepth` automatically. + */ +//ftlError_t ftlReconstruction(ftlStream_t stream); + +// ==== Rendering ============================================================== + +/*ftlError_t ftlRender( + ftlStream_t input, + ftlStream_t output, + const float *pose, + ... + )*/ + +// ==== Misc frame operations ================================================== + +/** + * Set config properties within a frame. For example, set the `name` property + * to give this source frame a label. + */ +ftlError_t ftlSetPropertyString(ftlStream_t stream, int32_t sourceId, const char *prop, const char *value); + +ftlError_t ftlSetPropertyInt(ftlStream_t stream, int32_t sourceId, const char *prop, int value); + +ftlError_t ftlSetPropertyFloat(ftlStream_t stream, int32_t sourceId, const char *prop, float value); + +// TODO: Possibly add shapes and other kinds of data to the frame? + #ifdef __cplusplus }; #endif diff --git a/SDK/C/src/streams.cpp b/SDK/C/src/streams.cpp index 94b1fb01413dfda8fd9725bb04617c9d097f5862..01350a45944b44b970b98451aa99ce2ba2de5f4c 100644 --- a/SDK/C/src/streams.cpp +++ b/SDK/C/src/streams.cpp @@ -4,6 +4,10 @@ #include <ftl/streams/sender.hpp> #include <ftl/streams/filestream.hpp> #include <ftl/streams/netstream.hpp> +#include <ftl/operators/cuda/disparity.hpp> +#include <ftl/operators/operator.hpp> +#include <ftl/operators/disparity.hpp> +#include <ftl/operators/mvmls.hpp> #include <opencv2/imgproc.hpp> @@ -21,6 +25,8 @@ struct FTLStream { int64_t interval; bool has_fresh_data; + ftl::operators::Graph *pipelines; + std::vector<ftl::rgbd::FrameState> video_states; ftl::rgbd::FrameSet video_fs; }; @@ -55,6 +61,7 @@ ftlStream_t ftlCreateWriteStream(const char *uri) { s->last_error = FTLERROR_OK; s->stream = nullptr; s->sender = nullptr; + s->pipelines = nullptr; s->video_fs.id = 0; s->video_fs.count = 0; s->video_fs.mask = 0; @@ -194,8 +201,6 @@ ftlError_t ftlIntrinsicsWriteLeft(ftlStream_t stream, int32_t sourceId, int32_t stream->video_fs.frames[sourceId].setLeft(cam); stream->has_fresh_data = true; - LOG(INFO) << "INTRIN " << f << "," << cx << "," << cy << "," << baseline; - return FTLERROR_OK; } @@ -221,8 +226,6 @@ ftlError_t ftlIntrinsicsWriteRight(ftlStream_t stream, int32_t sourceId, int32_t stream->video_fs.frames[sourceId].setRight(cam); stream->has_fresh_data = true; - LOG(INFO) << "INTRINR " << f << "," << cx << "," << cy << "," << baseline; - return FTLERROR_OK; } @@ -244,6 +247,100 @@ ftlError_t ftlPoseWrite(ftlStream_t stream, int32_t sourceId, const float *data) return FTLERROR_OK; } +ftlError_t ftlRemoveOcclusion(ftlStream_t stream, int32_t sourceId, ftlChannel_t channel, uint32_t pitch, const float *data) { + if (!stream) return FTLERROR_STREAM_INVALID_STREAM; + if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; + if (sourceId < 0 || sourceId >= 32) + return FTLERROR_STREAM_INVALID_PARAMETER; + if (!stream->video_fs.hasFrame(sourceId)) + return FTLERROR_STREAM_NO_INTRINSICS; + if (static_cast<int>(channel) < 0 || static_cast<int>(channel) > 32) + return FTLERROR_STREAM_BAD_CHANNEL; + if (!stream->video_fs.frames[sourceId].hasChannel(static_cast<ftl::codecs::Channel>(channel))) + return FTLERROR_STREAM_BAD_CHANNEL; + + auto &frame = stream->video_fs.frames[sourceId]; + //auto &mask = frame.create<cv::cuda::GpuMat>(ftl::codecs::Channel::Mask); + auto &depth = frame.get<cv::cuda::GpuMat>(static_cast<ftl::codecs::Channel>(channel)); + auto &intrin = frame.getLeft(); + + cv::Mat depthR(intrin.height, intrin.width, CV_32F, const_cast<float*>(data), pitch); + cv::Mat tmp; + cv::flip(depthR, tmp, 0); + cv::cuda::GpuMat depthRGPU; + depthRGPU.upload(tmp); + ftl::cuda::remove_occlusions(depth, depthRGPU, intrin, 0); + + return FTLERROR_OK; +} + +ftlError_t ftlMaskOcclusion(ftlStream_t stream, int32_t sourceId, ftlChannel_t channel, uint32_t pitch, const float *data) { + if (!stream) return FTLERROR_STREAM_INVALID_STREAM; + if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; + if (sourceId < 0 || sourceId >= 32) + return FTLERROR_STREAM_INVALID_PARAMETER; + if (!stream->video_fs.hasFrame(sourceId)) + return FTLERROR_STREAM_NO_INTRINSICS; + if (static_cast<int>(channel) < 0 || static_cast<int>(channel) > 32) + return FTLERROR_STREAM_BAD_CHANNEL; + if (!stream->video_fs.frames[sourceId].hasChannel(static_cast<ftl::codecs::Channel>(channel))) + return FTLERROR_STREAM_BAD_CHANNEL; + + auto &frame = stream->video_fs.frames[sourceId]; + auto &mask = frame.create<cv::cuda::GpuMat>(ftl::codecs::Channel::Mask); + auto &depth = frame.get<cv::cuda::GpuMat>(static_cast<ftl::codecs::Channel>(channel)); + auto &intrin = frame.getLeft(); + + mask.create(depth.size(), CV_8UC1); + + cv::Mat depthR(intrin.height, intrin.width, CV_32F, const_cast<float*>(data), pitch); + cv::Mat tmp; + cv::flip(depthR, tmp, 0); + cv::cuda::GpuMat depthRGPU; + depthRGPU.upload(tmp); + ftl::cuda::mask_occlusions(depth, depthRGPU, mask, intrin, 0); + + ftlSelect(stream, FTLCHANNEL_Mask); + + return FTLERROR_OK; +} + +ftlError_t ftlEnablePipeline(ftlStream_t stream, ftlPipeline_t pipeline) { + if (!stream) return FTLERROR_STREAM_INVALID_STREAM; + if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; + + if (stream->pipelines == nullptr) { + stream->pipelines = ftl::create<ftl::operators::Graph>(root, "pipes"); + } + + switch (pipeline) { + case FTLPIPE_DEPTH : stream->pipelines->append<ftl::operators::DepthChannel>("depth"); + ftlSelect(stream, FTLCHANNEL_Depth); // Enable saving of depth automatrically + break; + case FTLPIPE_RECONSTRUCT : stream->pipelines->append<ftl::operators::MultiViewMLS>("reconstruct"); break; + default: return FTLERROR_STREAM_INVALID_PARAMETER; + } + + return FTLERROR_OK; +} + +ftlError_t ftlDisablePipeline(ftlStream_t stream, ftlPipeline_t pipeline) { + return FTLERROR_OK; +} + +ftlError_t ftlSelect(ftlStream_t stream, ftlChannel_t channel) { + if (!stream) return FTLERROR_STREAM_INVALID_STREAM; + if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; + if (static_cast<int>(channel) < 0 || static_cast<int>(channel) > 32) + return FTLERROR_STREAM_BAD_CHANNEL; + + ftl::codecs::Channels<0> channels; + if (stream->stream->size() > static_cast<unsigned int>(stream->video_fs.id)) channels = stream->stream->selected(stream->video_fs.id); + channels += static_cast<ftl::codecs::Channel>(channel); + stream->stream->select(stream->video_fs.id, channels, true); + return FTLERROR_OK; +} + ftlError_t ftlSetFrameRate(ftlStream_t stream, float fps) { if (!stream) return FTLERROR_STREAM_INVALID_STREAM; if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; @@ -260,6 +357,9 @@ ftlError_t ftlNextFrame(ftlStream_t stream) { try { cudaSetDevice(0); + if (stream->pipelines) { + stream->pipelines->apply(stream->video_fs, stream->video_fs, 0); + } stream->sender->post(stream->video_fs); } catch (const std::exception &e) { return FTLERROR_STREAM_ENCODE_FAILED; @@ -292,9 +392,13 @@ ftlError_t ftlDestroyStream(ftlStream_t stream) { if (stream->has_fresh_data) { try { cudaSetDevice(0); + if (stream->pipelines) { + stream->pipelines->apply(stream->video_fs, stream->video_fs, 0); + } stream->sender->post(stream->video_fs); } catch (const std::exception &e) { err = FTLERROR_STREAM_ENCODE_FAILED; + LOG(ERROR) << "Sender exception: " << e.what(); } } @@ -302,11 +406,55 @@ ftlError_t ftlDestroyStream(ftlStream_t stream) { err = FTLERROR_STREAM_FILE_CREATE_FAILED; } if (stream->sender) delete stream->sender; + if (stream->pipelines) delete stream->pipelines; delete stream->stream; stream->sender = nullptr; stream->stream = nullptr; + stream->pipelines = nullptr; delete stream; //}); //return FTLERROR_OK; return err; } + +ftlError_t ftlSetPropertyString(ftlStream_t stream, int32_t sourceId, const char *prop, const char *value) { + if (!stream) return FTLERROR_STREAM_INVALID_STREAM; + if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; + if (sourceId < 0 || sourceId >= 32) + return FTLERROR_STREAM_INVALID_PARAMETER; + if (!stream->video_fs.hasFrame(sourceId)) + return FTLERROR_STREAM_NO_INTRINSICS; + if (!value) return FTLERROR_STREAM_INVALID_PARAMETER; + if (!prop) return FTLERROR_STREAM_INVALID_PARAMETER; + + stream->video_fs.frames[sourceId].set(std::string(prop), std::string(value)); + return FTLERROR_OK; +} + +ftlError_t ftlSetPropertyInt(ftlStream_t stream, int32_t sourceId, const char *prop, int value) { + if (!stream) return FTLERROR_STREAM_INVALID_STREAM; + if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; + if (sourceId < 0 || sourceId >= 32) + return FTLERROR_STREAM_INVALID_PARAMETER; + if (!stream->video_fs.hasFrame(sourceId)) + return FTLERROR_STREAM_NO_INTRINSICS; + if (!value) return FTLERROR_STREAM_INVALID_PARAMETER; + if (!prop) return FTLERROR_STREAM_INVALID_PARAMETER; + + stream->video_fs.frames[sourceId].set(std::string(prop), value); + return FTLERROR_OK; +} + +ftlError_t ftlSetPropertyFloat(ftlStream_t stream, int32_t sourceId, const char *prop, float value) { + if (!stream) return FTLERROR_STREAM_INVALID_STREAM; + if (!stream->stream) return FTLERROR_STREAM_INVALID_STREAM; + if (sourceId < 0 || sourceId >= 32) + return FTLERROR_STREAM_INVALID_PARAMETER; + if (!stream->video_fs.hasFrame(sourceId)) + return FTLERROR_STREAM_NO_INTRINSICS; + if (!value) return FTLERROR_STREAM_INVALID_PARAMETER; + if (!prop) return FTLERROR_STREAM_INVALID_PARAMETER; + + stream->video_fs.frames[sourceId].set(std::string(prop), value); + return FTLERROR_OK; +} diff --git a/SDK/Python/blender_script.py b/SDK/Python/blender_script.py index 1a567e429af02eec04e2746398ebe6c5ab8830f8..96dea4cb4616416ef123a93d6bcf46c1e21166a6 100644 --- a/SDK/Python/blender_script.py +++ b/SDK/Python/blender_script.py @@ -251,6 +251,22 @@ ftlImageWrite = ftl.ftlImageWrite ftlImageWrite.restype = c_int ftlImageWrite.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_void_p] +ftlRemoveOcclusion = ftl.ftlRemoveOcclusion +ftlRemoveOcclusion.restype = c_int +ftlRemoveOcclusion.argtypes = [c_void_p, c_int, c_int, c_int, c_void_p] + +ftlMaskOcclusion = ftl.ftlMaskOcclusion +ftlMaskOcclusion.restype = c_int +ftlMaskOcclusion.argtypes = [c_void_p, c_int, c_int, c_int, c_void_p] + +ftlEnablePipeline = ftl.ftlEnablePipeline +ftlEnablePipeline.restype = c_int +ftlEnablePipeline.argtypes = [c_void_p, c_int] + +ftlSelect = ftl.ftlSelect +ftlSelect.restype = c_int +ftlSelect.argtypes = [c_void_p, c_int] + ftlPoseWrite = ftl.ftlPoseWrite ftlPoseWrite.restype = c_int ftlPoseWrite.argtypes = [c_void_p, c_int, c_void_p] @@ -273,6 +289,8 @@ def render_and_save(filename, cameras): print("Could not create FTL stream") return + ftlCheck(ftlEnablePipeline(stream, 0)) + for camname in cameras: obj = bpy.context.scene.objects[camname] if obj.type == 'CAMERA': @@ -281,7 +299,6 @@ def render_and_save(filename, cameras): ftlCheck(ftlIntrinsicsWriteLeft(c_void_p(stream), c_int(i), c_int(int(image.intrinsics.width)), c_int(int(image.intrinsics.height)), c_float(image.intrinsics.fx), c_float(image.intrinsics.cx), c_float(image.intrinsics.cy), c_float(image.intrinsics.baseline), c_float(image.intrinsics.min_depth), c_float(image.intrinsics.max_depth))) ftlCheck(ftlIntrinsicsWriteRight(c_void_p(stream), c_int(i), c_int(int(image.intrinsics.width)), c_int(int(image.intrinsics.height)), c_float(image.intrinsics.fx), c_float(image.intrinsics.cx), c_float(image.intrinsics.cy), c_float(image.intrinsics.baseline), c_float(image.intrinsics.min_depth), c_float(image.intrinsics.max_depth))) - # This line needs fixing M = np.identity(4,dtype=np.float32) M[0:3,0:4] = image.pose M = np.transpose(M) @@ -291,9 +308,10 @@ def render_and_save(filename, cameras): ftlCheck(ftlImageWrite(stream, c_int(i), 0, 5, 0, image.imL.ctypes.data_as(c_void_p))) ftlCheck(ftlImageWrite(stream, c_int(i), 2, 5, 0, image.imR.ctypes.data_as(c_void_p))) ftlCheck(ftlImageWrite(stream, c_int(i), 22, 0, 0, image.depthL.ctypes.data_as(c_void_p))) + ftlCheck(ftlMaskOcclusion(stream, c_int(i), 22, 0, image.depthR.ctypes.data_as(c_void_p))) i = i + 1 ftlCheck(ftlDestroyStream(stream)) -render_and_save(b'./blender.ftl', ['Camera', 'Camera.002']) +render_and_save(b'./blender.ftl', ['Camera']) diff --git a/components/codecs/src/channels.cpp b/components/codecs/src/channels.cpp index 75dc784fb09a6f9882f1a0156c09314641fdaef4..1e9d8d5260e1c969d4e04325fd4084498cc5d390 100644 --- a/components/codecs/src/channels.cpp +++ b/components/codecs/src/channels.cpp @@ -13,23 +13,23 @@ static ChannelInfo info[] = { "Right", CV_8UC4, // 2 "DepthRight", CV_32F, // 3 "Deviation", CV_32F, // 4 - "Normals", CV_32FC4, // 5 + "Normals", CV_16FC4, // 5 "Weights", CV_16SC1, // 6 "Confidence", CV_32F, // 7 "EnergyVector", CV_32FC4, // 8 "Flow", CV_32F, // 9 "Energy", CV_32F, // 10 - "Mask", CV_32S, // 11 + "Mask", CV_8U, // 11 "Density", CV_32F, // 12 "Support1", CV_8UC4, // 13 "Support2", CV_8UC4, // 14 "Segmentation", CV_32S, // 15 "ColourNormals", 0, // 16 - "ColourHighRes", 0, // 17 - "Disparity", 0, // 18 + "ColourHighRes", CV_8UC4, // 17 + "Disparity", CV_32F, // 18 "Smoothing", 0, // 19 - "Colour2HighRes", 0, // 20 + "Colour2HighRes", CV_8UC4, // 20 "Overlay", 0, // 21 "GroundTruth", CV_32F, // 22 "NoName", 0, diff --git a/components/codecs/src/generate.cpp b/components/codecs/src/generate.cpp index f39167dfd6e1ac1e953be8813ca9725c600e47de..64dd2a042a42b6e5dbf272a01f4a922ed00168fe 100644 --- a/components/codecs/src/generate.cpp +++ b/components/codecs/src/generate.cpp @@ -31,6 +31,8 @@ void init_encoders() { encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::HD1080, definition_t::HD720)); encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::HD1080, definition_t::HD720)); encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::HD1080, definition_t::HD720)); + encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::HD1080, definition_t::HD720)); + encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::HD1080, definition_t::HD720)); encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::SD576, definition_t::LD360)); encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::SD576, definition_t::LD360)); encoders.push_back(new ftl::codecs::OpenCVEncoder(definition_t::SD576, definition_t::LD360)); diff --git a/components/codecs/src/opencv_decoder.cpp b/components/codecs/src/opencv_decoder.cpp index be3c800d63611b940b0c1f2f4032b3681bdf6585..981bac10e6155a05fab467407483e9d47656d2c9 100644 --- a/components/codecs/src/opencv_decoder.cpp +++ b/components/codecs/src/opencv_decoder.cpp @@ -59,6 +59,8 @@ bool OpenCVDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out chunkHead.upload(tmp_); } else if (!tmp_.empty() && tmp_.type() == CV_16U && chunkHead.type() == CV_16U) { chunkHead.upload(tmp_); + } else if (!tmp_.empty() && tmp_.type() == CV_8UC1 && chunkHead.type() == CV_8UC1) { + chunkHead.upload(tmp_); } else { // Silent ignore? } diff --git a/components/codecs/src/opencv_encoder.cpp b/components/codecs/src/opencv_encoder.cpp index 1bb96812802eb59b0ac97bd07f9700e53596a57e..6cf2a3183ded4e3090dbcd9cb89f4b3574b4fe90 100644 --- a/components/codecs/src/opencv_encoder.cpp +++ b/components/codecs/src/opencv_encoder.cpp @@ -30,7 +30,7 @@ bool OpenCVEncoder::supports(ftl::codecs::codec_t codec) { bool OpenCVEncoder::encode(const cv::cuda::GpuMat &in, ftl::codecs::Packet &pkt) { bool is_colour = !(pkt.flags & ftl::codecs::kFlagFloat); - if (is_colour && in.type() != CV_8UC4) return false; + if (is_colour && in.type() != CV_8UC4 && in.type() != CV_8UC1) return false; if (!is_colour && in.type() == CV_8UC4) { LOG(ERROR) << "OpenCV Encoder doesn't support lossy depth"; return false; @@ -74,7 +74,7 @@ bool OpenCVEncoder::encode(const cv::cuda::GpuMat &in, ftl::codecs::Packet &pkt) return false; } - if (pkt.codec == codec_t::Any) pkt.codec = (is_colour) ? codec_t::JPG : codec_t::PNG; + if (pkt.codec == codec_t::Any) pkt.codec = (is_colour && in.type() != CV_8UC1) ? codec_t::JPG : codec_t::PNG; //for (int i=0; i<chunk_count_; ++i) { // Add chunk job to thread pool diff --git a/components/operators/src/disparity/cuda.hpp b/components/operators/include/ftl/operators/cuda/disparity.hpp similarity index 65% rename from components/operators/src/disparity/cuda.hpp rename to components/operators/include/ftl/operators/cuda/disparity.hpp index 74102111e31b6f44a22ae083fa8cf698723ec904..e18fcd4fe972b82706fdefecb285546e345c2778 100644 --- a/components/operators/src/disparity/cuda.hpp +++ b/components/operators/include/ftl/operators/cuda/disparity.hpp @@ -9,6 +9,14 @@ void disparity_to_depth(const cv::cuda::GpuMat &disparity, cv::cuda::GpuMat &dep void depth_to_disparity(cv::cuda::GpuMat &disparity, const cv::cuda::GpuMat &depth, const ftl::rgbd::Camera &c, cudaStream_t &stream); +void remove_occlusions(cv::cuda::GpuMat &depth, const cv::cuda::GpuMat &depthR, + const ftl::rgbd::Camera &c, cudaStream_t stream); + +void mask_occlusions(const cv::cuda::GpuMat &depth, + const cv::cuda::GpuMat &depthR, + cv::cuda::GpuMat &mask, + const ftl::rgbd::Camera &c, cudaStream_t stream); + void optflow_filter(cv::cuda::GpuMat &disp, const cv::cuda::GpuMat &optflow, cv::cuda::GpuMat &history, cv::cuda::GpuMat &support, int n_max, float threshold, bool fill, diff --git a/components/operators/include/ftl/operators/gt_cuda.hpp b/components/operators/include/ftl/operators/cuda/gt.hpp similarity index 100% rename from components/operators/include/ftl/operators/gt_cuda.hpp rename to components/operators/include/ftl/operators/cuda/gt.hpp diff --git a/components/operators/include/ftl/operators/mask_cuda.hpp b/components/operators/include/ftl/operators/cuda/mask.hpp similarity index 98% rename from components/operators/include/ftl/operators/mask_cuda.hpp rename to components/operators/include/ftl/operators/cuda/mask.hpp index aadab5e5a640c7200bc87f76b4b80d496b6dbe59..8e136371879c451a9b03997998c46e7b50a8c943 100644 --- a/components/operators/include/ftl/operators/mask_cuda.hpp +++ b/components/operators/include/ftl/operators/cuda/mask.hpp @@ -41,6 +41,7 @@ class Mask { static constexpr type kMask_Correspondence = 0x04; static constexpr type kMask_Bad = 0x08; static constexpr type kMask_Noise = 0x10; + static constexpr type kMask_Occlusion = 0x20; private: type v_; diff --git a/components/operators/include/ftl/operators/gt_analysis.hpp b/components/operators/include/ftl/operators/gt_analysis.hpp index 9397a96da2ff80985d08d90d7f68697935fc895f..a89230caa12e42fc05027506c6484be1bf348d91 100644 --- a/components/operators/include/ftl/operators/gt_analysis.hpp +++ b/components/operators/include/ftl/operators/gt_analysis.hpp @@ -3,7 +3,7 @@ #include <ftl/operators/operator.hpp> #include <ftl/cuda_common.hpp> -#include <ftl/operators/gt_cuda.hpp> +#include <ftl/operators/cuda/gt.hpp> namespace ftl { namespace operators { diff --git a/components/operators/src/disparity/bilateral_filter.cpp b/components/operators/src/disparity/bilateral_filter.cpp index 694a23a9a0e9bab1b144ed9b279f4952dce022ff..0f515ed41b842df11099927542498ae861dc1df9 100644 --- a/components/operators/src/disparity/bilateral_filter.cpp +++ b/components/operators/src/disparity/bilateral_filter.cpp @@ -1,7 +1,7 @@ #include <ftl/operators/disparity.hpp> #include "opencv/joint_bilateral.hpp" -#include "cuda.hpp" +#include <ftl/operators/cuda/disparity.hpp> #include <opencv2/cudaimgproc.hpp> diff --git a/components/operators/src/disparity/disp2depth.cu b/components/operators/src/disparity/disp2depth.cu index e39afe6f60e236530985874dba9c0f598fe6a5e3..cc023c6c2b551043042ae93cc13830aec307bc98 100644 --- a/components/operators/src/disparity/disp2depth.cu +++ b/components/operators/src/disparity/disp2depth.cu @@ -1,6 +1,8 @@ #include <ftl/cuda_common.hpp> #include <ftl/rgbd/camera.hpp> #include <opencv2/core/cuda_stream_accessor.hpp> +#include <ftl/operators/cuda/disparity.hpp> +#include <ftl/operators/cuda/mask.hpp> #ifndef PINF #define PINF __int_as_float(0x7f800000) @@ -60,3 +62,66 @@ void depth_to_disparity(cv::cuda::GpuMat &disparity, const cv::cuda::GpuMat &dep } } } + +// ============================================================================= + +__global__ void remove_occ_kernel(cv::cuda::PtrStepSz<float> depth, cv::cuda::PtrStepSz<float> depthR, + ftl::rgbd::Camera cam) +{ + for (STRIDE_Y(v,depth.rows)) { + for (STRIDE_X(u,depth.cols)) { + float d = depth(v,u); + int disparity = int((d > cam.maxDepth || d < cam.minDepth) ? 0.0f : ((cam.baseline*cam.fx) / d) + cam.doffs); + + if (disparity > 0 && u-disparity > 0) { + float dR = depthR(v,u-disparity); + if (fabsf(d-dR) > 0.01f*d) { + depth(v,u) = 0.0f; + } + } + } + } +} + +void ftl::cuda::remove_occlusions(cv::cuda::GpuMat &depth, const cv::cuda::GpuMat &depthR, + const ftl::rgbd::Camera &c, cudaStream_t stream) { + dim3 grid(1,1,1); + dim3 threads(128, 4, 1); + grid.x = cv::cuda::device::divUp(depth.cols, 128); + grid.y = cv::cuda::device::divUp(depth.rows, 4); + remove_occ_kernel<<<grid, threads, 0, stream>>>( + depth, depthR, c); + cudaSafeCall( cudaGetLastError() ); +} + +__global__ void mask_occ_kernel(cv::cuda::PtrStepSz<float> depth, + cv::cuda::PtrStepSz<float> depthR, + cv::cuda::PtrStepSz<uchar> mask, + ftl::rgbd::Camera cam) +{ + for (STRIDE_Y(v,depth.rows)) { + for (STRIDE_X(u,depth.cols)) { + float d = depth(v,u); + int disparity = int((d > cam.maxDepth || d < cam.minDepth) ? 0.0f : ((cam.baseline*cam.fx) / d) + cam.doffs); + + if (disparity > 0 && u-disparity > 0) { + float dR = depthR(v,u-disparity); + if (fabsf(d-dR) > 0.01f*d) { + mask(v,u) = mask(v,u) | ftl::cuda::Mask::kMask_Occlusion; + } + } + } + } +} + +void ftl::cuda::mask_occlusions(const cv::cuda::GpuMat &depth, const cv::cuda::GpuMat &depthR, + cv::cuda::GpuMat &mask, + const ftl::rgbd::Camera &c, cudaStream_t stream) { + dim3 grid(1,1,1); + dim3 threads(128, 4, 1); + grid.x = cv::cuda::device::divUp(depth.cols, 128); + grid.y = cv::cuda::device::divUp(depth.rows, 4); + mask_occ_kernel<<<grid, threads, 0, stream>>>( + depth, depthR, mask, c); + cudaSafeCall( cudaGetLastError() ); +} diff --git a/components/operators/src/disparity/disparity_to_depth.cpp b/components/operators/src/disparity/disparity_to_depth.cpp index d00cced27bb6e5e8fc5870e6ac5cde432f964917..5dbe97b335e4d40d06cd61f63bac37f1d2a2d215 100644 --- a/components/operators/src/disparity/disparity_to_depth.cpp +++ b/components/operators/src/disparity/disparity_to_depth.cpp @@ -1,5 +1,5 @@ #include "ftl/operators/disparity.hpp" -#include "disparity/cuda.hpp" +#include <ftl/operators/cuda/disparity.hpp> using ftl::operators::DisparityToDepth; using ftl::codecs::Channel; diff --git a/components/operators/src/disparity/optflow_smoothing.cpp b/components/operators/src/disparity/optflow_smoothing.cpp index 82476395a7ed7a5ec90b79f3aebbd1b7e9b3fb16..e2f1e6f936fec0236ce0be92ba05335e5150e8f3 100644 --- a/components/operators/src/disparity/optflow_smoothing.cpp +++ b/components/operators/src/disparity/optflow_smoothing.cpp @@ -1,7 +1,7 @@ #include <loguru.hpp> #include "ftl/operators/disparity.hpp" -#include "disparity/cuda.hpp" +#include <ftl/operators/cuda/disparity.hpp> #ifdef HAVE_OPTFLOW diff --git a/components/operators/src/disparity/optflow_smoothing.cu b/components/operators/src/disparity/optflow_smoothing.cu index 8e3293cd99c8136925acbd999d1c9be90b09e2f4..c30302b85ac218d464624e6fbb6c740b95a304ee 100644 --- a/components/operators/src/disparity/optflow_smoothing.cu +++ b/components/operators/src/disparity/optflow_smoothing.cu @@ -3,7 +3,7 @@ #include <opencv2/core/cuda_stream_accessor.hpp> #include "disparity/qsort.h" -#include "disparity/cuda.hpp" +#include <ftl/operators/cuda/disparity.hpp> __device__ void quicksort(float A[], size_t n) { diff --git a/components/operators/src/fusion/correspondence.cu b/components/operators/src/fusion/correspondence.cu index b19a84af903af05b3908a3d2f782c16eeb6559d8..be72902428eb2e2e0d985755b8d55cf4e66391e6 100644 --- a/components/operators/src/fusion/correspondence.cu +++ b/components/operators/src/fusion/correspondence.cu @@ -1,6 +1,6 @@ #include "mvmls_cuda.hpp" #include <ftl/cuda/weighting.hpp> -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> #include <ftl/cuda/warp.hpp> using ftl::cuda::TextureObject; diff --git a/components/operators/src/fusion/correspondence_depth.cu b/components/operators/src/fusion/correspondence_depth.cu index 9f83fa79f33da8e9c275b13e7951f74f418cafed..f7303cfc413f03b49bdc75510906a5cbd409b626 100644 --- a/components/operators/src/fusion/correspondence_depth.cu +++ b/components/operators/src/fusion/correspondence_depth.cu @@ -1,6 +1,6 @@ #include "mvmls_cuda.hpp" #include <ftl/cuda/weighting.hpp> -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> #include <ftl/cuda/warp.hpp> using ftl::cuda::TextureObject; diff --git a/components/operators/src/fusion/correspondence_util.cu b/components/operators/src/fusion/correspondence_util.cu index de91eabe6b2c4f8a52d6ee4abb993ee8d0ecebcc..5145f69767866e66ed01518b6e492328f022f595 100644 --- a/components/operators/src/fusion/correspondence_util.cu +++ b/components/operators/src/fusion/correspondence_util.cu @@ -1,6 +1,6 @@ #include "mvmls_cuda.hpp" #include <ftl/cuda/weighting.hpp> -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> #include <ftl/cuda/warp.hpp> using ftl::cuda::TextureObject; diff --git a/components/operators/src/fusion/mls_aggr.cu b/components/operators/src/fusion/mls_aggr.cu index 9332117bc11f382f418151c5305f2d694cf3e7e0..d597654480909974c1b2605ff643fc5516a90fc1 100644 --- a/components/operators/src/fusion/mls_aggr.cu +++ b/components/operators/src/fusion/mls_aggr.cu @@ -1,6 +1,6 @@ #include "mvmls_cuda.hpp" #include <ftl/cuda/weighting.hpp> -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> #include <ftl/cuda/warp.hpp> using ftl::cuda::TextureObject; diff --git a/components/operators/src/gt_analysis.cpp b/components/operators/src/gt_analysis.cpp index 91d59ca3d362a0f59580773b11fa0a9d7e3ac405..d4a29a5894580bdaf6bb0839ea9b11fb058c776c 100644 --- a/components/operators/src/gt_analysis.cpp +++ b/components/operators/src/gt_analysis.cpp @@ -1,5 +1,5 @@ #include <ftl/operators/gt_analysis.hpp> -#include <ftl/operators/gt_cuda.hpp> +#include <ftl/operators/cuda/gt.hpp> using ftl::operators::GTAnalysis; using ftl::codecs::Channel; diff --git a/components/operators/src/gt_analysis.cu b/components/operators/src/gt_analysis.cu index 230f2fd20c44dce8e6db125434d6801b69183cef..53b76cd6332f6c00878be70c187d5cefdaa930a8 100644 --- a/components/operators/src/gt_analysis.cu +++ b/components/operators/src/gt_analysis.cu @@ -1,4 +1,4 @@ -#include <ftl/operators/gt_cuda.hpp> +#include <ftl/operators/cuda/gt.hpp> #ifndef WARP_SIZE #define WARP_SIZE 32 diff --git a/components/operators/src/mask.cpp b/components/operators/src/mask.cpp index 1c53630cf7b43112d2fe7ceba19110e9b89024b8..e39fcabea0fa322ef2c6d8333a6366aef664e0e4 100644 --- a/components/operators/src/mask.cpp +++ b/components/operators/src/mask.cpp @@ -1,5 +1,5 @@ #include <ftl/operators/mask.hpp> -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> using ftl::operators::DiscontinuityMask; using ftl::operators::BorderMask; @@ -27,6 +27,12 @@ bool DiscontinuityMask::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaS if (!in.hasChannel(Channel::Depth) || !in.hasChannel(Channel::Support1)) return false; + if (!out.hasChannel(Channel::Mask)) { + auto &m = out.create<cv::cuda::GpuMat>(Channel::Mask); + m.create(in.get<cv::cuda::GpuMat>(Channel::Depth).size(), CV_8UC1); + m.setTo(cv::Scalar(0)); + } + /*ftl::cuda::discontinuity( out.createTexture<uint8_t>(Channel::Mask, ftl::rgbd::Format<uint8_t>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), in.createTexture<uchar4>(Channel::Support1), @@ -37,7 +43,7 @@ bool DiscontinuityMask::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaS );*/ ftl::cuda::discontinuity( - out.createTexture<uint8_t>(Channel::Mask, ftl::rgbd::Format<uint8_t>(in.get<cv::cuda::GpuMat>(Channel::Depth).size())), + out.createTexture<uint8_t>(Channel::Mask), in.createTexture<uchar4>(Channel::Support1), in.createTexture<float>(Channel::Depth), in.get<cv::cuda::GpuMat>(Channel::Depth).size(), diff --git a/components/operators/src/mask.cu b/components/operators/src/mask.cu index 85fde5190a7c1e4fd69432b61b515a0c868501de..8632420d7c2510c1c547f2617c7c61a96a4e2d55 100644 --- a/components/operators/src/mask.cu +++ b/components/operators/src/mask.cu @@ -1,4 +1,4 @@ -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> #define T_PER_BLOCK 8 @@ -14,7 +14,7 @@ __global__ void discontinuity_kernel(ftl::cuda::TextureObject<uint8_t> mask_out, const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y; if (x < size.width && y < size.height) { - Mask mask(0); + Mask mask(mask_out(x,y)); const float d = depth.tex2D((int)x, (int)y); // Multiples of pixel size at given depth diff --git a/components/operators/src/nvopticalflow.cpp b/components/operators/src/nvopticalflow.cpp index deee3ecdbc27d9d99228cf607d02703beca8c866..422fc3040d27edd0ee49e0e37f62e1185a1d872e 100644 --- a/components/operators/src/nvopticalflow.cpp +++ b/components/operators/src/nvopticalflow.cpp @@ -3,6 +3,9 @@ #include <opencv2/cudaimgproc.hpp> +#define LOGURU_REPLACE_GLOG 1 +#include <loguru.hpp> + using ftl::rgbd::Frame; using ftl::rgbd::Source; using ftl::codecs::Channel; @@ -29,7 +32,9 @@ NVOpticalFlow::~NVOpticalFlow() { bool NVOpticalFlow::init() { if (!ftl::cuda::hasCompute(7,5)) { config()->set("enabled", false); - throw FTL_Error("GPU does not support optical flow"); + //throw FTL_Error("GPU does not support optical flow"); + LOG(ERROR) << "GPU does not support optical flow"; + return false; } nvof_ = cv::cuda::NvidiaOpticalFlow_1_0::create( size_.width, size_.height, @@ -47,7 +52,7 @@ bool NVOpticalFlow::apply(Frame &in, Frame &out, cudaStream_t stream) { if (in.get<GpuMat>(channel_in_).size() != size_) { size_ = in.get<GpuMat>(channel_in_).size(); - init(); + if (!init()) return false; } auto cvstream = cv::cuda::StreamAccessor::wrapStream(stream); diff --git a/components/operators/src/segmentation.cu b/components/operators/src/segmentation.cu index 8704cd275939f9350ead23538ef419b5da6ff0a2..de1268931a7b91bb09f0e3dc6385a8d9c7a4a9d8 100644 --- a/components/operators/src/segmentation.cu +++ b/components/operators/src/segmentation.cu @@ -1,5 +1,5 @@ #include "segmentation_cuda.hpp" -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> #define T_PER_BLOCK 8 diff --git a/components/operators/src/weighting.cpp b/components/operators/src/weighting.cpp index 5445d6786de3bc04bd515315910740a49d35290a..549a22f144d7627277e4e0396dd24331feaaacf3 100644 --- a/components/operators/src/weighting.cpp +++ b/components/operators/src/weighting.cpp @@ -37,10 +37,16 @@ bool PixelWeights::apply(ftl::rgbd::Frame &in, ftl::rgbd::Frame &out, cudaStream Channel dchan = (in.hasChannel(Channel::Depth)) ? Channel::Depth : Channel::GroundTruth; + if (!out.hasChannel(Channel::Mask)) { + auto &m = out.create<cv::cuda::GpuMat>(Channel::Mask); + m.create(in.get<cv::cuda::GpuMat>(dchan).size(), CV_8UC1); + m.setTo(cv::Scalar(0)); + } + if (output_normals) { ftl::cuda::pixel_weighting( out.createTexture<short>(Channel::Weights, ftl::rgbd::Format<short>(in.get<cv::cuda::GpuMat>(dchan).size())), - out.createTexture<uint8_t>(Channel::Mask, ftl::rgbd::Format<uint8_t>(in.get<cv::cuda::GpuMat>(dchan).size())), + out.createTexture<uint8_t>(Channel::Mask), out.createTexture<half4>(Channel::Normals, ftl::rgbd::Format<half4>(in.get<cv::cuda::GpuMat>(dchan).size())), in.createTexture<uchar4>(Channel::Support1), in.createTexture<float>(dchan), diff --git a/components/operators/src/weighting.cu b/components/operators/src/weighting.cu index ccb5d7f4e31389edd17a22a139b9391d40b16068..90aa5fd494f19e20a28eb7f6dc3ff822bd5c05ce 100644 --- a/components/operators/src/weighting.cu +++ b/components/operators/src/weighting.cu @@ -24,7 +24,7 @@ __global__ void pixel_weight_kernel( const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y; if (x < size.width && y < size.height) { - Mask mask(0); + Mask mask(mask_out(x,y)); const float d = depth.tex2D((int)x, (int)y); // Multiples of pixel size at given depth diff --git a/components/operators/src/weighting_cuda.hpp b/components/operators/src/weighting_cuda.hpp index 782aae3df36b214f2962093890c0b8a72b3f1ef9..69b679196e3880991f41e64cc1c2e8308b31f44b 100644 --- a/components/operators/src/weighting_cuda.hpp +++ b/components/operators/src/weighting_cuda.hpp @@ -1,7 +1,7 @@ #ifndef _FTL_OPERATORS_WEIGHTING_CUDA_HPP_ #define _FTL_OPERATORS_WEIGHTING_CUDA_HPP_ -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> namespace ftl { namespace cuda { diff --git a/components/renderers/cpp/src/CUDARender.cpp b/components/renderers/cpp/src/CUDARender.cpp index c2673073bf35d959a6c79441be8a67155b94a8e6..b00efb036525426c8ec7bc61a01f247b83d8436d 100644 --- a/components/renderers/cpp/src/CUDARender.cpp +++ b/components/renderers/cpp/src/CUDARender.cpp @@ -3,7 +3,7 @@ #include "splatter_cuda.hpp" #include <ftl/cuda/points.hpp> #include <ftl/cuda/normals.hpp> -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> #include <ftl/render/colouriser.hpp> #include <ftl/cuda/transform.hpp> diff --git a/components/renderers/cpp/src/mask.cu b/components/renderers/cpp/src/mask.cu index 7e36d9b32e5c024e2fc3094daf66d55248304b8d..9952cf80ce04f785862c2c6a958ab6b267e4697c 100644 --- a/components/renderers/cpp/src/mask.cu +++ b/components/renderers/cpp/src/mask.cu @@ -1,5 +1,5 @@ #include "splatter_cuda.hpp" -#include <ftl/operators/mask_cuda.hpp> +#include <ftl/operators/cuda/mask.hpp> using ftl::cuda::TextureObject; using ftl::cuda::Mask; diff --git a/components/streams/src/receiver.cpp b/components/streams/src/receiver.cpp index dfd8f0003bda646ae4588003c6339d219623192c..6a274d56c3efc52007b996b20d0f8bdf7b6b67ef 100644 --- a/components/streams/src/receiver.cpp +++ b/components/streams/src/receiver.cpp @@ -208,7 +208,11 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) { auto &surface = ividstate.surface[static_cast<int>(spkt.channel)]; // Allocate a decode surface, this is a tiled image to be split later - surface.create(height*ty, width*tx, ((isFloatChannel(spkt.channel)) ? ((pkt.flags & 0x2) ? CV_16UC4 : CV_16U) : CV_8UC4)); + int cvtype = ftl::codecs::type(spkt.channel); + if (cvtype == CV_32F) cvtype = (pkt.flags & 0x2) ? CV_16UC4 : CV_16U; + + //surface.create(height*ty, width*tx, ((isFloatChannel(spkt.channel)) ? ((pkt.flags & 0x2) ? CV_16UC4 : CV_16U) : CV_8UC4)); + surface.create(height*ty, width*tx, cvtype); bool is_static = ividstate.decoders[channum] && (spkt.hint_capability & ftl::codecs::kStreamCap_Static); @@ -279,7 +283,7 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) { // Add channel to frame and allocate memory if required const cv::Size size = cv::Size(width, height); - frame.getBuffer<cv::cuda::GpuMat>(spkt.channel).create(size, (isFloatChannel(rchan) ? CV_32FC1 : CV_8UC4)); + frame.getBuffer<cv::cuda::GpuMat>(spkt.channel).create(size, ftl::codecs::type(spkt.channel)); //(isFloatChannel(rchan) ? CV_32FC1 : CV_8UC4)); cv::Rect roi((i % tx)*width, (i / tx)*height, width, height); cv::cuda::GpuMat sroi = surface(roi); @@ -300,6 +304,8 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) { ftl::cuda::vuya_to_depth(frame.getBuffer<cv::cuda::GpuMat>(spkt.channel), sroi, 16.0f, cvstream); } else if (isFloatChannel(rchan)) { sroi.convertTo(frame.getBuffer<cv::cuda::GpuMat>(spkt.channel), CV_32FC1, 1.0f/1000.0f, cvstream); + } else if (sroi.type() == CV_8UC1) { + sroi.copyTo(frame.getBuffer<cv::cuda::GpuMat>(spkt.channel), cvstream); } else { cv::cuda::cvtColor(sroi, frame.getBuffer<cv::cuda::GpuMat>(spkt.channel), cv::COLOR_RGBA2BGRA, 0, cvstream); } diff --git a/components/streams/src/sender.cpp b/components/streams/src/sender.cpp index 623baf76de7f541d487614467851ac82327db2bb..236f96f5ec959f124dc04fcea909b362591760fb 100644 --- a/components/streams/src/sender.cpp +++ b/components/streams/src/sender.cpp @@ -409,7 +409,14 @@ int Sender::_generateTiles(const ftl::rgbd::FrameSet &fs, int offset, Channel c, int tilecount = tx*ty; uint32_t count = 0; - surface.surface.create(height, width, (lossless && m.type() == CV_32F) ? CV_16U : CV_8UC4); + int cvtype = CV_8UC4; + switch (m.type()) { + case CV_32F : cvtype = (lossless && m.type() == CV_32F) ? CV_16U : CV_8UC4; break; + case CV_8UC1 : cvtype = CV_8UC1; break; + default : cvtype = CV_8UC4; + } + + surface.surface.create(height, width, cvtype); // Loop over tiles with ROI mats and do colour conversions. while (tilecount > 0 && count+offset < fs.frames.size()) { @@ -429,6 +436,8 @@ int Sender::_generateTiles(const ftl::rgbd::FrameSet &fs, int offset, Channel c, cv::cuda::cvtColor(m, sroi, cv::COLOR_BGRA2RGBA, 0, stream); } else if (m.type() == CV_8UC3) { cv::cuda::cvtColor(m, sroi, cv::COLOR_BGR2RGBA, 0, stream); + } else if (m.type() == CV_8UC1) { + m.copyTo(sroi, stream); } else { LOG(ERROR) << "Unsupported colour format: " << m.type(); return 0;