mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-24 01:31:46 +00:00
Add raw sources and sinks to cscore (#1670)
In some cases, we don't want the cv requirement to get an image, for instance interop with other versions of opencv This enables getting a raw image, and handling conversions from the user side.
This commit is contained in:
committed by
Peter Johnson
parent
7de9477347
commit
fb1239a2ad
@@ -20,8 +20,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct CvMat;
|
||||
|
||||
/**
|
||||
* @defgroup cscore_c_api cscore C API
|
||||
*
|
||||
@@ -128,7 +126,8 @@ enum CS_SourceKind {
|
||||
CS_SOURCE_UNKNOWN = 0,
|
||||
CS_SOURCE_USB = 1,
|
||||
CS_SOURCE_HTTP = 2,
|
||||
CS_SOURCE_CV = 4
|
||||
CS_SOURCE_CV = 4,
|
||||
CS_SOURCE_RAW = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -144,7 +143,12 @@ enum CS_HttpCameraKind {
|
||||
/**
|
||||
* Sink kinds
|
||||
*/
|
||||
enum CS_SinkKind { CS_SINK_UNKNOWN = 0, CS_SINK_MJPEG = 2, CS_SINK_CV = 4 };
|
||||
enum CS_SinkKind {
|
||||
CS_SINK_UNKNOWN = 0,
|
||||
CS_SINK_MJPEG = 2,
|
||||
CS_SINK_CV = 4,
|
||||
CS_SINK_RAW = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Listener event kinds
|
||||
@@ -351,8 +355,6 @@ char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status);
|
||||
* @defgroup cscore_opencv_source_cfunc OpenCV Source Functions
|
||||
* @{
|
||||
*/
|
||||
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
|
||||
CS_Status* status);
|
||||
void CS_NotifySourceError(CS_Source source, const char* msg, CS_Status* status);
|
||||
void CS_SetSourceConnected(CS_Source source, CS_Bool connected,
|
||||
CS_Status* status);
|
||||
@@ -415,9 +417,6 @@ int CS_GetMjpegServerPort(CS_Sink sink, CS_Status* status);
|
||||
*/
|
||||
void CS_SetSinkDescription(CS_Sink sink, const char* description,
|
||||
CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
|
||||
double timeout, CS_Status* status);
|
||||
char* CS_GetSinkError(CS_Sink sink, CS_Status* status);
|
||||
void CS_SetSinkEnabled(CS_Sink sink, CS_Bool enabled, CS_Status* status);
|
||||
/** @} */
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
namespace cv {
|
||||
class Mat;
|
||||
} // namespace cv
|
||||
|
||||
namespace wpi {
|
||||
class json;
|
||||
} // namespace wpi
|
||||
@@ -286,7 +282,6 @@ std::vector<std::string> GetHttpCameraUrls(CS_Source source, CS_Status* status);
|
||||
* @defgroup cscore_opencv_source_func OpenCV Source Functions
|
||||
* @{
|
||||
*/
|
||||
void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status);
|
||||
void NotifySourceError(CS_Source source, const wpi::Twine& msg,
|
||||
CS_Status* status);
|
||||
void SetSourceConnected(CS_Source source, bool connected, CS_Status* status);
|
||||
@@ -312,6 +307,7 @@ CS_Sink CreateCvSink(const wpi::Twine& name, CS_Status* status);
|
||||
CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@@ -356,9 +352,6 @@ int GetMjpegServerPort(CS_Sink sink, CS_Status* status);
|
||||
*/
|
||||
void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
|
||||
CS_Status* status);
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, cv::Mat& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
|
||||
CS_Status* status);
|
||||
std::string GetSinkError(CS_Sink sink, CS_Status* status);
|
||||
wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
|
||||
CS_Status* status);
|
||||
@@ -429,18 +422,4 @@ std::vector<std::string> GetNetworkInterfaces();
|
||||
|
||||
} // namespace cs
|
||||
|
||||
/**
|
||||
* @defgroup cscore_cpp_opencv_special cscore C functions taking a cv::Mat*
|
||||
*
|
||||
* These are needed for specific interop implementations.
|
||||
* @{
|
||||
*/
|
||||
extern "C" {
|
||||
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeoutCpp(CS_Sink sink, cv::Mat* image,
|
||||
double timeout, CS_Status* status);
|
||||
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status);
|
||||
} // extern "C"
|
||||
/** @} */
|
||||
|
||||
#endif // CSCORE_CSCORE_CPP_H_
|
||||
|
||||
205
cscore/src/main/native/include/cscore_cv.h
Normal file
205
cscore/src/main/native/include/cscore_cv.h
Normal file
@@ -0,0 +1,205 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_CSCORE_CV_H_
|
||||
#define CSCORE_CSCORE_CV_H_
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
#ifdef CSCORE_CSCORE_RAW_CV_H_
|
||||
#error "Cannot include both cscore_cv.h and cscore_raw_cv.h in the same file"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "cscore_oo.h" // NOLINT(build/include_order)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { // NOLINT(build/include_order)
|
||||
#endif
|
||||
|
||||
struct CvMat;
|
||||
|
||||
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
|
||||
CS_Status* status);
|
||||
|
||||
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
|
||||
double timeout, CS_Status* status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "cscore_oo.h"
|
||||
|
||||
namespace cv {
|
||||
class Mat;
|
||||
} // namespace cv
|
||||
|
||||
namespace cs {
|
||||
|
||||
/**
|
||||
* @defgroup cscore_cpp_opencv_special cscore C functions taking a cv::Mat*
|
||||
*
|
||||
* These are needed for specific interop implementations.
|
||||
* @{
|
||||
*/
|
||||
extern "C" {
|
||||
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status);
|
||||
uint64_t CS_GrabSinkFrameTimeoutCpp(CS_Sink sink, cv::Mat* image,
|
||||
double timeout, CS_Status* status);
|
||||
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status);
|
||||
} // extern "C"
|
||||
/** @} */
|
||||
|
||||
void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, cv::Mat& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
|
||||
CS_Status* status);
|
||||
|
||||
/**
|
||||
* A source for user code to provide OpenCV images as video frames.
|
||||
* These sources require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, include "cscore_raw_cv.h" instead, and
|
||||
* include your Mat header before that header.
|
||||
*/
|
||||
class CvSource : public ImageSource {
|
||||
public:
|
||||
CvSource() = default;
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
void PutFrame(cv::Mat& image);
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as OpenCV images.
|
||||
* These sinks require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, include "cscore_raw_cv.h" instead, and
|
||||
* include your Mat header before that header.
|
||||
*/
|
||||
class CvSink : public ImageSink {
|
||||
public:
|
||||
CvSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
*
|
||||
* <p>WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit CvSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225) const;
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
|
||||
};
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
m_handle = CreateCvSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
|
||||
int width, int height, int fps) {
|
||||
m_handle =
|
||||
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::PutFrame(cv::Mat& image) {
|
||||
m_status = 0;
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name) {
|
||||
m_handle = CreateCvSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrame(cv::Mat& image, double timeout) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrameNoTimeout(cv::Mat& image) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CSCORE_CSCORE_CV_H_
|
||||
@@ -28,7 +28,7 @@ namespace cs {
|
||||
*/
|
||||
|
||||
// Forward declarations so friend declarations work correctly
|
||||
class CvSource;
|
||||
class ImageSource;
|
||||
class VideoEvent;
|
||||
class VideoSink;
|
||||
class VideoSource;
|
||||
@@ -37,7 +37,7 @@ class VideoSource;
|
||||
* A source or sink property.
|
||||
*/
|
||||
class VideoProperty {
|
||||
friend class CvSource;
|
||||
friend class ImageSource;
|
||||
friend class VideoEvent;
|
||||
friend class VideoSink;
|
||||
friend class VideoSource;
|
||||
@@ -617,43 +617,13 @@ class AxisCamera : public HttpCamera {
|
||||
};
|
||||
|
||||
/**
|
||||
* A source for user code to provide OpenCV images as video frames.
|
||||
* A base class for single image providing sources.
|
||||
*/
|
||||
class CvSource : public VideoSource {
|
||||
class ImageSource : public VideoSource {
|
||||
protected:
|
||||
ImageSource() = default;
|
||||
|
||||
public:
|
||||
CvSource() = default;
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
void PutFrame(cv::Mat& image);
|
||||
|
||||
/**
|
||||
* Signal sinks that an error has occurred. This should be called instead
|
||||
* of NotifyFrame when an error occurs.
|
||||
@@ -979,37 +949,13 @@ class MjpegServer : public VideoSink {
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as OpenCV images.
|
||||
* A base class for single image reading sinks.
|
||||
*/
|
||||
class CvSink : public VideoSink {
|
||||
class ImageSink : public VideoSink {
|
||||
protected:
|
||||
ImageSink() = default;
|
||||
|
||||
public:
|
||||
CvSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
*
|
||||
* <p>WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit CvSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
* Set sink description.
|
||||
*
|
||||
@@ -1017,27 +963,6 @@ class CvSink : public VideoSink {
|
||||
*/
|
||||
void SetDescription(const wpi::Twine& description);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225) const;
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
|
||||
|
||||
/**
|
||||
* Get error string. Call this if WaitForFrame() returns 0 to determine
|
||||
* what the error is.
|
||||
|
||||
@@ -378,37 +378,22 @@ inline AxisCamera::AxisCamera(const wpi::Twine& name,
|
||||
std::initializer_list<T> hosts)
|
||||
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
m_handle = CreateCvSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
|
||||
int width, int height, int fps) {
|
||||
m_handle =
|
||||
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::PutFrame(cv::Mat& image) {
|
||||
m_status = 0;
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::NotifyError(const wpi::Twine& msg) {
|
||||
inline void ImageSource::NotifyError(const wpi::Twine& msg) {
|
||||
m_status = 0;
|
||||
NotifySourceError(m_handle, msg, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::SetConnected(bool connected) {
|
||||
inline void ImageSource::SetConnected(bool connected) {
|
||||
m_status = 0;
|
||||
SetSourceConnected(m_handle, connected, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSource::SetDescription(const wpi::Twine& description) {
|
||||
inline void ImageSource::SetDescription(const wpi::Twine& description) {
|
||||
m_status = 0;
|
||||
SetSourceDescription(m_handle, description, &m_status);
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateProperty(const wpi::Twine& name,
|
||||
VideoProperty::Kind kind,
|
||||
int minimum, int maximum,
|
||||
int step, int defaultValue,
|
||||
@@ -419,7 +404,7 @@ inline VideoProperty CvSource::CreateProperty(const wpi::Twine& name,
|
||||
minimum, maximum, step, defaultValue, value, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
int minimum, int maximum,
|
||||
int step, int defaultValue,
|
||||
int value) {
|
||||
@@ -429,7 +414,7 @@ inline VideoProperty CvSource::CreateIntegerProperty(const wpi::Twine& name,
|
||||
minimum, maximum, step, defaultValue, value, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
bool defaultValue,
|
||||
bool value) {
|
||||
m_status = 0;
|
||||
@@ -438,7 +423,7 @@ inline VideoProperty CvSource::CreateBooleanProperty(const wpi::Twine& name,
|
||||
0, 1, 1, defaultValue ? 1 : 0, value ? 1 : 0, &m_status)};
|
||||
}
|
||||
|
||||
inline VideoProperty CvSource::CreateStringProperty(const wpi::Twine& name,
|
||||
inline VideoProperty ImageSource::CreateStringProperty(const wpi::Twine& name,
|
||||
const wpi::Twine& value) {
|
||||
m_status = 0;
|
||||
auto prop = VideoProperty{CreateSourceProperty(
|
||||
@@ -449,14 +434,14 @@ inline VideoProperty CvSource::CreateStringProperty(const wpi::Twine& name,
|
||||
}
|
||||
|
||||
|
||||
inline void CvSource::SetEnumPropertyChoices(
|
||||
inline void ImageSource::SetEnumPropertyChoices(
|
||||
const VideoProperty& property, wpi::ArrayRef<std::string> choices) {
|
||||
m_status = 0;
|
||||
SetSourceEnumPropertyChoices(m_handle, property.m_handle, choices, &m_status);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void CvSource::SetEnumPropertyChoices(const VideoProperty& property,
|
||||
inline void ImageSource::SetEnumPropertyChoices(const VideoProperty& property,
|
||||
std::initializer_list<T> choices) {
|
||||
std::vector<std::string> vec;
|
||||
vec.reserve(choices.size());
|
||||
@@ -575,36 +560,17 @@ inline void MjpegServer::SetDefaultCompression(int quality) {
|
||||
quality, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name) {
|
||||
m_handle = CreateCvSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline CvSink::CvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSink::SetDescription(const wpi::Twine& description) {
|
||||
inline void ImageSink::SetDescription(const wpi::Twine& description) {
|
||||
m_status = 0;
|
||||
SetSinkDescription(m_handle, description, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrame(cv::Mat& image, double timeout) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t CvSink::GrabFrameNoTimeout(cv::Mat& image) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline std::string CvSink::GetError() const {
|
||||
inline std::string ImageSink::GetError() const {
|
||||
m_status = 0;
|
||||
return GetSinkError(m_handle, &m_status);
|
||||
}
|
||||
|
||||
inline void CvSink::SetEnabled(bool enabled) {
|
||||
inline void ImageSink::SetEnabled(bool enabled) {
|
||||
m_status = 0;
|
||||
SetSinkEnabled(m_handle, enabled, &m_status);
|
||||
}
|
||||
|
||||
234
cscore/src/main/native/include/cscore_raw.h
Normal file
234
cscore/src/main/native/include/cscore_raw.h
Normal file
@@ -0,0 +1,234 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_CSCORE_RAW_H_
|
||||
#define CSCORE_CSCORE_RAW_H_
|
||||
|
||||
#include "cscore_c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "cscore_oo.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Raw Frame
|
||||
*/
|
||||
typedef struct CS_RawFrame {
|
||||
char* data;
|
||||
int dataLength;
|
||||
int pixelFormat;
|
||||
int width;
|
||||
int height;
|
||||
int totalData;
|
||||
} CS_RawFrame;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup cscore_raw_cfunc Raw Image Functions
|
||||
* @{
|
||||
*/
|
||||
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize);
|
||||
void CS_FreeRawFrameData(CS_RawFrame* frame);
|
||||
|
||||
uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* rawImage,
|
||||
CS_Status* status);
|
||||
uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* rawImage,
|
||||
double timeout, CS_Status* status);
|
||||
|
||||
CS_Sink CS_CreateRawSink(const char* name, CS_Status* status);
|
||||
|
||||
CS_Sink CS_CreateRawSinkCallback(const char* name, void* data,
|
||||
void (*processFrame)(void* data,
|
||||
uint64_t time),
|
||||
CS_Status* status);
|
||||
|
||||
void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image,
|
||||
CS_Status* status);
|
||||
|
||||
CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode,
|
||||
CS_Status* status);
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace cs {
|
||||
|
||||
struct RawFrame : public CS_RawFrame {
|
||||
RawFrame() {
|
||||
data = nullptr;
|
||||
dataLength = 0;
|
||||
pixelFormat = CS_PIXFMT_UNKNOWN;
|
||||
width = 0;
|
||||
height = 0;
|
||||
totalData = 0;
|
||||
}
|
||||
|
||||
~RawFrame() { CS_FreeRawFrameData(this); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup cscore_raw_func Raw Image Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
|
||||
CS_Status* status);
|
||||
|
||||
CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status);
|
||||
CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame,
|
||||
CS_Status* status);
|
||||
|
||||
void PutSourceFrame(CS_Source source, const CS_RawFrame& image,
|
||||
CS_Status* status);
|
||||
uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status);
|
||||
uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout,
|
||||
CS_Status* status);
|
||||
|
||||
/**
|
||||
* A source for user code to provide video frames as raw bytes.
|
||||
*
|
||||
* This is a complex API, most cases should use CvSource.
|
||||
*/
|
||||
class RawSource : public ImageSource {
|
||||
public:
|
||||
RawSource() = default;
|
||||
|
||||
/**
|
||||
* Create a raw frame source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
RawSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create a raw frame source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
RawSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Put a raw image and notify sinks.
|
||||
*
|
||||
* @param image raw frame image
|
||||
*/
|
||||
void PutFrame(RawFrame& image);
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as raw bytes.
|
||||
*
|
||||
* This is a complex API, most cases should use CvSource.
|
||||
*/
|
||||
class RawSink : public ImageSink {
|
||||
public:
|
||||
RawSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting raw images.
|
||||
*
|
||||
* <p>GrabFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit RawSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting raws images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
RawSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(RawFrame& image, double timeout = 0.225) const;
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(RawFrame& image) const;
|
||||
};
|
||||
|
||||
inline RawSource::RawSource(const wpi::Twine& name, const VideoMode& mode) {
|
||||
m_handle = CreateRawSource(name, mode, &m_status);
|
||||
}
|
||||
|
||||
inline RawSource::RawSource(const wpi::Twine& name,
|
||||
VideoMode::PixelFormat format, int width,
|
||||
int height, int fps) {
|
||||
m_handle =
|
||||
CreateRawSource(name, VideoMode{format, width, height, fps}, &m_status);
|
||||
}
|
||||
|
||||
inline void RawSource::PutFrame(RawFrame& image) {
|
||||
m_status = 0;
|
||||
PutSourceFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
inline RawSink::RawSink(const wpi::Twine& name) {
|
||||
m_handle = CreateRawSink(name, &m_status);
|
||||
}
|
||||
|
||||
inline RawSink::RawSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame) {
|
||||
m_handle = CreateRawSinkCallback(name, processFrame, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t RawSink::GrabFrame(RawFrame& image, double timeout) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
|
||||
}
|
||||
|
||||
inline uint64_t RawSink::GrabFrameNoTimeout(RawFrame& image) const {
|
||||
m_status = 0;
|
||||
return GrabSinkFrame(m_handle, image, &m_status);
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CSCORE_CSCORE_RAW_H_
|
||||
218
cscore/src/main/native/include/cscore_raw_cv.h
Normal file
218
cscore/src/main/native/include/cscore_raw_cv.h
Normal file
@@ -0,0 +1,218 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2015-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CSCORE_CSCORE_RAW_CV_H_
|
||||
#define CSCORE_CSCORE_RAW_CV_H_
|
||||
|
||||
#ifdef CSCORE_CSCORE_CV_H_
|
||||
#error "Cannot include both cscore_cv.h and cscore_raw_cv.h in the same file"
|
||||
#endif
|
||||
|
||||
#include "cscore_raw.h"
|
||||
|
||||
namespace cs {
|
||||
/**
|
||||
* A source for using the raw frame API to provide opencv images.
|
||||
*
|
||||
* If you are using the WPILib OpenCV builds, do not use this, and
|
||||
* instead include "cscore_cv.h" to get a more performant version.
|
||||
*
|
||||
* This is not dependent on any opencv binary ABI, and can be used
|
||||
* with versions of OpenCV that are not 3. If using OpenCV 3, use
|
||||
* CvSource.
|
||||
*/
|
||||
class RawCvSource : public RawSource {
|
||||
public:
|
||||
RawCvSource() = default;
|
||||
|
||||
/**
|
||||
* Create a Raw OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
RawCvSource(const wpi::Twine& name, const VideoMode& mode);
|
||||
|
||||
/**
|
||||
* Create a Raw OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
RawCvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
|
||||
int width, int height, int fps);
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
void PutFrame(cv::Mat& image);
|
||||
|
||||
private:
|
||||
RawFrame rawFrame;
|
||||
};
|
||||
|
||||
/**
|
||||
* A sink for user code to accept raw video frames as OpenCV images.
|
||||
*
|
||||
* If you are using the WPILib OpenCV builds, do not use this, and
|
||||
* instead include "cscore_cv.h" to get a more performant version.
|
||||
*
|
||||
* This is not dependent on any opencv binary ABI, and can be used
|
||||
* with versions of OpenCV that are not 3. If using OpenCV 3, use
|
||||
* CvSink.
|
||||
*/
|
||||
class RawCvSink : public RawSink {
|
||||
public:
|
||||
RawCvSink() = default;
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
*
|
||||
* <p>WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
explicit RawCvSink(const wpi::Twine& name);
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images in a separate thread.
|
||||
*
|
||||
* <p>A thread will be created that calls WaitForFrame() and calls the
|
||||
* processFrame() callback each time a new frame arrives.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param processFrame Frame processing function; will be called with a
|
||||
* time=0 if an error occurred. processFrame should call GetImage()
|
||||
* or GetError() as needed, but should not call (except in very
|
||||
* unusual circumstances) WaitForImage().
|
||||
*/
|
||||
RawCvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeout(cv::Mat& image);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameDirect(cv::Mat& image, double timeout = 0.225);
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 8-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in the same time base as wpi::Now(),
|
||||
* and is in 1 us increments.
|
||||
*/
|
||||
uint64_t GrabFrameNoTimeoutDirect(cv::Mat& image);
|
||||
|
||||
private:
|
||||
RawFrame rawFrame;
|
||||
};
|
||||
|
||||
inline RawCvSource::RawCvSource(const wpi::Twine& name, const VideoMode& mode)
|
||||
: RawSource{name, mode} {}
|
||||
|
||||
inline RawCvSource::RawCvSource(const wpi::Twine& name,
|
||||
VideoMode::PixelFormat format, int width,
|
||||
int height, int fps)
|
||||
: RawSource{name, format, width, height, fps} {}
|
||||
|
||||
inline void RawCvSource::PutFrame(cv::Mat& image) {
|
||||
m_status = 0;
|
||||
rawFrame.data = reinterpret_cast<char*>(image.data);
|
||||
rawFrame.width = image.cols;
|
||||
rawFrame.height = image.rows;
|
||||
rawFrame.totalData = image.total() * image.channels;
|
||||
rawFrame.pixelFormat = image.channels == 3 ? CS_PIXFMT_BGR : CS_PIXFMT_GRAY;
|
||||
PutSourceFrame(m_handle, rawFrame, &m_status);
|
||||
}
|
||||
|
||||
inline RawCvSink::RawCvSink(const wpi::Twine& name) : RawSink{name} {}
|
||||
|
||||
inline RawCvSink::RawCvSink(const wpi::Twine& name,
|
||||
std::function<void(uint64_t time)> processFrame)
|
||||
: RawSink{name, processFrame} {}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrame(cv::Mat& image, double timeout) {
|
||||
cv::Mat tmpMat;
|
||||
auto retVal = GrabFrameDirect(tmpMat);
|
||||
if (retVal <= 0) {
|
||||
return retVal;
|
||||
}
|
||||
tmpMat.copyTo(image);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrameNoTimeout(cv::Mat& image) {
|
||||
cv::Mat tmpMat;
|
||||
auto retVal = GrabFrameNoTimeoutDirect(tmpMat);
|
||||
if (retVal <= 0) {
|
||||
return retVal;
|
||||
}
|
||||
tmpMat.copyTo(image);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrameDirect(cv::Mat& image, double timeout) {
|
||||
rawFrame.height = 0;
|
||||
rawFrame.width = 0;
|
||||
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
|
||||
m_status = RawSink::GrabFrame(rawFrame, timeout);
|
||||
if (m_status <= 0) return m_status;
|
||||
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
|
||||
return m_status;
|
||||
}
|
||||
|
||||
inline uint64_t RawCvSink::GrabFrameNoTimeoutDirect(cv::Mat& image) {
|
||||
rawFrame.height = 0;
|
||||
rawFrame.width = 0;
|
||||
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
|
||||
m_status = RawSink::GrabFrameNoTimeout(rawFrame);
|
||||
if (m_status <= 0) return m_status;
|
||||
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
|
||||
return m_status;
|
||||
}
|
||||
|
||||
} // namespace cs
|
||||
|
||||
#endif // CSCORE_CSCORE_RAW_CV_H_
|
||||
Reference in New Issue
Block a user