WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
CvSink.hpp
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <stdint.h>
8
9#include <string_view>
10
11#include <opencv2/core/mat.hpp>
12
13#include "wpi/cs/ImageSink.hpp"
14#include "wpi/cs/cscore_raw.hpp"
16#include "wpi/util/RawFrame.hpp"
17
18namespace wpi::cs {
19
20/**
21 * A sink for user code to accept video frames as OpenCV images.
22 *
23 * This is not dependent on any opencv binary ABI, and can be used
24 * with versions of most versions of OpenCV.
25 */
26class CvSink : public ImageSink {
27 public:
28 CvSink() = default;
29 CvSink(const CvSink& sink) : ImageSink{sink}, pixelFormat{sink.pixelFormat} {}
30
31 /**
32 * Create a sink for accepting OpenCV images.
33 *
34 * <p>WaitForFrame() must be called on the created sink to get each new
35 * image.
36 *
37 * @param name Source name (arbitrary unique identifier)
38 * @param pixelFormat The pixel format to read
39 */
40 explicit CvSink(std::string_view name, wpi::util::PixelFormat pixelFormat =
43 this->pixelFormat = pixelFormat;
44 }
45
46 /**
47 * Wait for the next frame and get the image.
48 * Times out (returning 0) after timeout seconds.
49 * The provided image will have the pixelFormat this class was constructed
50 * with.
51 *
52 * @return Frame time, or 0 on error (call GetError() to obtain the error
53 * message); the frame time is in the same time base as
54 * wpi::util::Now(), and is in 1 us increments.
55 */
56 [[nodiscard]]
57 uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225) {
58 cv::Mat tmpnam;
59 auto retVal = GrabFrameDirect(tmpnam);
60 if (retVal <= 0) {
61 return retVal;
62 }
63 tmpnam.copyTo(image);
64 return retVal;
65 }
66
67 /**
68 * Wait for the next frame and get the image. May block forever.
69 * The provided image will have the pixelFormat this class was constructed
70 * with.
71 *
72 * @return Frame time, or 0 on error (call GetError() to obtain the error
73 * message); the frame time is in the same time base as
74 * wpi::util::Now(), and is in 1 us increments.
75 */
76 [[nodiscard]]
77 uint64_t GrabFrameNoTimeout(cv::Mat& image) {
78 cv::Mat tmpnam;
79 auto retVal = GrabFrameNoTimeoutDirect(tmpnam);
80 if (retVal <= 0) {
81 return retVal;
82 }
83 tmpnam.copyTo(image);
84 return retVal;
85 }
86
87 /**
88 * Wait for the next frame and get the image.
89 * Times out (returning 0) after timeout seconds.
90 * The provided image will have the pixelFormat this class was constructed
91 * with. The data is backed by data in the CvSink. It will be invalidated by
92 * any grabFrame*() call on the sink.
93 *
94 * @return Frame time, or 0 on error (call GetError() to obtain the error
95 * message); the frame time is in the same time base as
96 * wpi::util::Now(), and is in 1 us increments.
97 */
98 [[nodiscard]]
99 uint64_t GrabFrameDirect(cv::Mat& image, double timeout = 0.225) {
100 rawFrame.height = 0;
101 rawFrame.width = 0;
102 rawFrame.stride = 0;
103 rawFrame.pixelFormat = static_cast<int>(pixelFormat);
104 auto timestamp =
105 GrabSinkFrameTimeout(m_handle, rawFrame, timeout, &m_status);
106 if (m_status != CS_OK) {
107 return 0;
108 }
109 image =
110 cv::Mat{rawFrame.height, rawFrame.width,
111 GetCvFormat(static_cast<WPI_PixelFormat>(rawFrame.pixelFormat)),
112 rawFrame.data, static_cast<size_t>(rawFrame.stride)};
113 return timestamp;
114 }
115
116 /**
117 * Wait for the next frame and get the image. May block forever.
118 * The provided image will have the pixelFormat this class was constructed
119 * with. The data is backed by data in the CvSink. It will be invalidated by
120 * any grabFrame*() call on the sink.
121 *
122 * @return Frame time, or 0 on error (call GetError() to obtain the error
123 * message); the frame time is in the same time base as
124 * wpi::util::Now(), and is in 1 us increments.
125 */
126 [[nodiscard]]
127 uint64_t GrabFrameNoTimeoutDirect(cv::Mat& image) {
128 rawFrame.height = 0;
129 rawFrame.width = 0;
130 rawFrame.stride = 0;
131 rawFrame.pixelFormat = static_cast<int>(pixelFormat);
132 auto timestamp = GrabSinkFrame(m_handle, rawFrame, &m_status);
133 if (m_status != CS_OK) {
134 return 0;
135 }
136 image =
137 cv::Mat{rawFrame.height, rawFrame.width,
138 GetCvFormat(static_cast<WPI_PixelFormat>(rawFrame.pixelFormat)),
139 rawFrame.data, static_cast<size_t>(rawFrame.stride)};
140 return timestamp;
141 }
142
143 /**
144 * Wait for the next frame and get the image.
145 * Times out (returning 0) after timeout seconds.
146 * The provided image will have the pixelFormat this class was constructed
147 * with. The data is backed by data in the CvSink. It will be invalidated by
148 * any grabFrame*() call on the sink.
149 *
150 * <p>If lastFrameTime is provided and non-zero, the sink will fill image with
151 * the first frame from the source that is not equal to lastFrameTime. If
152 * lastFrameTime is zero, the time of the current frame owned by the CvSource
153 * is used, and this function will block until the connected CvSource provides
154 * a new frame.
155 *
156 * @return Frame time, or 0 on error (call GetError() to obtain the error
157 * message); the frame time is in the same time base as
158 * wpi::util::Now(), and is in 1 us increments.
159 */
160 [[nodiscard]]
161 uint64_t GrabFrameDirectLastTime(cv::Mat& image, uint64_t lastFrameTime,
162 double timeout = 0.225) {
163 rawFrame.height = 0;
164 rawFrame.width = 0;
165 rawFrame.stride = 0;
166 rawFrame.pixelFormat = static_cast<int>(pixelFormat);
167 auto timestamp = GrabSinkFrameTimeoutLastTime(m_handle, rawFrame, timeout,
168 lastFrameTime, &m_status);
169 if (m_status != CS_OK) {
170 return 0;
171 }
172 image =
173 cv::Mat{rawFrame.height, rawFrame.width,
174 GetCvFormat(static_cast<WPI_PixelFormat>(rawFrame.pixelFormat)),
175 rawFrame.data, static_cast<size_t>(rawFrame.stride)};
176 return timestamp;
177 }
178
179 /**
180 * Get the last time a frame was grabbed. This uses the same time base as
181 * wpi::util::Now().
182 *
183 * @return Time in 1 us increments.
184 */
185 [[nodiscard]]
186 uint64_t LastFrameTime() {
187 return rawFrame.timestamp;
188 }
189
190 /**
191 * Get the time source for the timestamp the last frame was grabbed at.
192 *
193 * @return Time source
194 */
195 [[nodiscard]]
197 return static_cast<WPI_TimestampSource>(rawFrame.timestampSrc);
198 }
199
200 private:
201 constexpr int GetCvFormat(WPI_PixelFormat pixelFormat) {
202 int type = 0;
203 switch (pixelFormat) {
204 case WPI_PIXFMT_YUYV:
206 case WPI_PIXFMT_Y16:
207 case WPI_PIXFMT_UYVY:
208 type = CV_8UC2;
209 break;
210 case WPI_PIXFMT_BGR:
211 type = CV_8UC3;
212 break;
213 case WPI_PIXFMT_BGRA:
214 type = CV_8UC4;
215 break;
216 case WPI_PIXFMT_GRAY:
217 case WPI_PIXFMT_MJPEG:
218 default:
219 type = CV_8UC1;
220 break;
221 }
222 return type;
223 }
224
225 wpi::util::RawFrame rawFrame;
226 wpi::util::PixelFormat pixelFormat;
227};
228
229} // namespace wpi::cs
WPI_PixelFormat
Pixel formats.
Definition PixelFormat.h:10
@ WPI_PIXFMT_YUYV
Definition PixelFormat.h:13
@ WPI_PIXFMT_Y16
Definition PixelFormat.h:17
@ WPI_PIXFMT_UYVY
Definition PixelFormat.h:18
@ WPI_PIXFMT_BGRA
Definition PixelFormat.h:19
@ WPI_PIXFMT_MJPEG
Definition PixelFormat.h:12
@ WPI_PIXFMT_GRAY
Definition PixelFormat.h:16
@ WPI_PIXFMT_RGB565
Definition PixelFormat.h:14
@ WPI_PIXFMT_BGR
Definition PixelFormat.h:15
WPI_TimestampSource
Timestamp metadata.
Definition RawFrame.h:36
@ name
Definition base.h:690
uint64_t GrabFrameDirect(cv::Mat &image, double timeout=0.225)
Wait for the next frame and get the image.
Definition CvSink.hpp:99
CvSink(const CvSink &sink)
Definition CvSink.hpp:29
CvSink(std::string_view name, wpi::util::PixelFormat pixelFormat=wpi::util::PixelFormat::kBGR)
Create a sink for accepting OpenCV images.
Definition CvSink.hpp:40
WPI_TimestampSource LastFrameTimeSource()
Get the time source for the timestamp the last frame was grabbed at.
Definition CvSink.hpp:196
uint64_t GrabFrameNoTimeoutDirect(cv::Mat &image)
Wait for the next frame and get the image.
Definition CvSink.hpp:127
uint64_t LastFrameTime()
Get the last time a frame was grabbed.
Definition CvSink.hpp:186
uint64_t GrabFrameDirectLastTime(cv::Mat &image, uint64_t lastFrameTime, double timeout=0.225)
Wait for the next frame and get the image.
Definition CvSink.hpp:161
uint64_t GrabFrameNoTimeout(cv::Mat &image)
Wait for the next frame and get the image.
Definition CvSink.hpp:77
uint64_t GrabFrame(cv::Mat &image, double timeout=0.225)
Wait for the next frame and get the image.
Definition CvSink.hpp:57
CvSink()=default
CS_Sink m_handle
Definition VideoSink.hpp:229
CS_Status m_status
Definition VideoSink.hpp:228
@ CS_OK
Definition cscore_c.h:56
uint64_t GrabSinkFrameTimeout(CS_Sink sink, WPI_RawFrame &image, double timeout, CS_Status *status)
CS_Sink CreateRawSink(std::string_view name, bool isCv, CS_Status *status)
uint64_t GrabSinkFrame(CS_Sink sink, WPI_RawFrame &image, CS_Status *status)
uint64_t GrabSinkFrameTimeoutLastTime(CS_Sink sink, WPI_RawFrame &image, double timeout, uint64_t lastFrameTime, CS_Status *status)
CameraServer (cscore) namespace.
Definition CvSource.hpp:15
PixelFormat
Pixel formats.
Definition PixelFormat.hpp:14
@ kBGR
Definition PixelFormat.hpp:19
Definition RawFrame.hpp:20