diff --git a/include/sv_camera.h b/include/sv_camera.h new file mode 100644 index 0000000..a432e0e --- /dev/null +++ b/include/sv_camera.h @@ -0,0 +1,79 @@ +#ifndef __SV_CAMERA__ +#define __SV_CAMERA__ + +#include "opencv2/opencv.hpp" + +namespace sv +{ + +enum class CameraType : int +{ + // 未知相机 + NONE = 0X00001000, + // 标准opencv框架下的相机 + WEBCAM = 0X00001001, + V4L2CAM = 0X00001002, + // 视频文件 + VIDEOFILE = 0X00002001, + // 普通流媒体相机 + STREAMING = 0X00004001, + // 普通的MIPI-CSI相机 + MIPI = 0X00008001, + // 进行了传输优化适配的相机 + G1 = 0X00010001, + Q10 = 0X00010002, + GX40 = 0X00010003, + MC1 = 0X00010004, + // 虚拟的相机设备 主要仿真接入 + VIRTUAL = 0X00020001, +}; + +class Camera +{ +private: + void *dev; + +public: + // 构建时根据相机类型实例化对应的相机类 + // timeOut: 相机连接超时时间;超过该时间没有读取到新的帧,则认为相机失去连接 单位ms + Camera(CameraType type, int timeOut = 500); + + // 基本配置 必须调用下述的一个接口后才能open + bool setStream(const std::string &ip, int port); + bool setName(const std::string &name); + bool setIndex(int index); + // 基础功能 + bool open(void); + bool read(cv::Mat &image); + bool readNoBlock(cv::Mat &image); + void release(void); + + // 属性配置 + void setWH(int width, int height); + void setFps(int fps); + void setBrightness(double brightness); + void setContrast(double contrast); + void setSaturation(double saturation); + void setHue(double hue); + void setExposure(double exposure); + + // 获取属性 + bool isActive(void); + CameraType getType(void); + std::string getName(void); + + int getW(void); + int getH(void); + int getExpectFps(void); + double getFps(void); + double getBrightness(void); + double getContrast(void); + double getSaturation(void); + double getHue(void); + double getExposure(void); + + ~Camera(); +}; + +} +#endif diff --git a/video_io/sv_camera.cpp b/video_io/sv_camera.cpp new file mode 100644 index 0000000..6d8b28d --- /dev/null +++ b/video_io/sv_camera.cpp @@ -0,0 +1,179 @@ +#include "sv_camera_privately.h" +#include "sv_camera.h" + +#include +#include + +typedef sv_p::CameraBase *(*cameraCreat)(int timeOut); +static std::map svCameraList = + { + {sv::CameraType::NONE, nullptr}, + {sv::CameraType::WEBCAM, nullptr}, + {sv::CameraType::V4L2CAM, nullptr}, + {sv::CameraType::VIDEOFILE, nullptr}, + {sv::CameraType::STREAMING, nullptr}, + {sv::CameraType::MIPI, nullptr}, + {sv::CameraType::G1, nullptr}, + {sv::CameraType::Q10, nullptr}, + {sv::CameraType::GX40, nullptr}, + {sv::CameraType::MC1, nullptr}, + {sv::CameraType::VIRTUAL, nullptr}}; + +static sv_p::CameraBase *svCreatCamera(sv::CameraType type, int timeOut) +{ + std::map::iterator temp = svCameraList.find(type); + if (temp != svCameraList.end()) + { + return temp->second(timeOut); + } + return nullptr; +} + +sv::Camera::Camera(CameraType type, int timeOut) +{ + this->dev = svCreatCamera(type,timeOut); +} + +sv::Camera::~Camera() +{ + // 休眠50ms 以便能退出线程 + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + delete (sv_p::CameraBase *)dev; +} + +sv_p::CameraBase::~CameraBase() +{ + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + readThreadHandle = readThreadHandle == 0 ? 0 : pthread_cancel(readThreadHandle); + release(); +} + +bool sv::Camera::setStream(const std::string &ip, int port) +{ + return ((sv_p::CameraBase *)dev)->setStream(ip, port); +} + +bool sv::Camera::setName(const std::string &name) +{ + return ((sv_p::CameraBase *)dev)->setName(name); +} + +bool sv::Camera::setIndex(int index) +{ + return ((sv_p::CameraBase *)dev)->setIndex(index); +} + +bool sv::Camera::open(void) +{ + return ((sv_p::CameraBase *)dev)->open(); +} + +bool sv::Camera::read(cv::Mat &image) +{ + return ((sv_p::CameraBase *)dev)->read(image); +} + +bool sv::Camera::readNoBlock(cv::Mat &image) +{ + return ((sv_p::CameraBase *)dev)->readNoBlock(image); +} + +void sv::Camera::release(void) +{ + ((sv_p::CameraBase *)dev)->release(); +} + +void sv::Camera::setWH(int width, int height) +{ + ((sv_p::CameraBase *)dev)->setWH(width, height); +} + +void sv::Camera::setFps(int fps) +{ + ((sv_p::CameraBase *)dev)->setFps(fps); +} + +void sv::Camera::setBrightness(double brightness) +{ + ((sv_p::CameraBase *)dev)->setBrightness(brightness); +} + +void sv::Camera::setContrast(double contrast) +{ + ((sv_p::CameraBase *)dev)->setContrast(contrast); +} + +void sv::Camera::setSaturation(double saturation) +{ + ((sv_p::CameraBase *)dev)->setSaturation(saturation); +} + +void sv::Camera::setHue(double hue) +{ + ((sv_p::CameraBase *)dev)->setHue(hue); +} + +void sv::Camera::setExposure(double exposure) +{ + ((sv_p::CameraBase *)dev)->setExposure(exposure); +} + +bool sv::Camera::isActive(void) +{ + return ((sv_p::CameraBase *)dev)->isActive(); +} + +sv::CameraType sv::Camera::getType(void) +{ + return ((sv_p::CameraBase *)dev)->getType(); +} + +std::string sv::Camera::getName(void) +{ + return ((sv_p::CameraBase *)dev)->getName(); +} + +int sv::Camera::getW(void) +{ + return ((sv_p::CameraBase *)dev)->getW(); +} + +int sv::Camera::getH(void) +{ + return ((sv_p::CameraBase *)dev)->getH(); +} + +int sv::Camera::getExpectFps(void) +{ + return ((sv_p::CameraBase *)dev)->getExpectFps(); +} + +double sv::Camera::getFps(void) +{ + return ((sv_p::CameraBase *)dev)->getFps(); +} + +double sv::Camera::getBrightness(void) +{ + return ((sv_p::CameraBase *)dev)->getBrightness(); +} + +double sv::Camera::getContrast(void) +{ + return ((sv_p::CameraBase *)dev)->getContrast(); +} + +double sv::Camera::getSaturation(void) +{ + return ((sv_p::CameraBase *)dev)->getSaturation(); +} + +double sv::Camera::getHue(void) +{ + return ((sv_p::CameraBase *)dev)->getHue(); +} + +double sv::Camera::getExposure(void) +{ + return ((sv_p::CameraBase *)dev)->getExposure(); +} \ No newline at end of file diff --git a/video_io/sv_camera_def.cpp b/video_io/sv_camera_def.cpp new file mode 100644 index 0000000..aff8029 --- /dev/null +++ b/video_io/sv_camera_def.cpp @@ -0,0 +1,136 @@ +#include "sv_camera_privately.h" + +sv_p::CameraBase::CameraBase(int timeOut) +{ + this->_timeOut = timeOut; +} + +void sv_p::CameraBase::readThread(void) +{ + int count = 0; + while (this->cap.isOpened()) + { + if (this->cap.grab()) + { + std::lock_guard locker(this->frameMutex); + this->cap.retrieve(this->imageBuff); + this->frameEmpty.notify_all(); + count = 0; + isGot = true; + } + else + { + count++; + if (count > this->_timeOut) + { + this->cap.release(); + // 抛出异常 并返回 + throw std::runtime_error("SpireCV (101) Camera has offline, check CAMERA!"); + return; + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +#define PARAM_SET_CHECK(param, value) param = (value > 0 ? value : param) + +void sv_p::CameraBase::setWH(int width, int height) +{ + if (!this->cap.isOpened()) + { + PARAM_SET_CHECK(this->_width, width); + PARAM_SET_CHECK(this->_height, height); + } +} + +void sv_p::CameraBase::setFps(int fps) +{ + PARAM_SET_CHECK(this->_fps, fps); + if (this->cap.isOpened()) + { + this->cap.set(cv::CAP_PROP_FPS, fps); + } +} + +void sv_p::CameraBase::setBrightness(double brightness) +{ + PARAM_SET_CHECK(this->_brightness, brightness); + if (this->cap.isOpened()) + { + this->cap.set(cv::CAP_PROP_BRIGHTNESS, brightness); + } +} + +void sv_p::CameraBase::setContrast(double contrast) +{ + PARAM_SET_CHECK(this->_contrast, contrast); + if (this->cap.isOpened()) + { + this->cap.set(cv::CAP_PROP_CONTRAST, contrast); + } +} + +void sv_p::CameraBase::setSaturation(double saturation) +{ + PARAM_SET_CHECK(this->_saturation, saturation); + if (this->cap.isOpened()) + { + this->cap.set(cv::CAP_PROP_SATURATION, saturation); + } +} + +void sv_p::CameraBase::setHue(double hue) +{ + PARAM_SET_CHECK(this->_hue, hue); + if (this->cap.isOpened()) + { + this->cap.set(cv::CAP_PROP_HUE, hue); + } +} + +void sv_p::CameraBase::setExposure(double exposure) +{ + PARAM_SET_CHECK(this->_exposure, exposure); + if (this->cap.isOpened()) + { + this->cap.set(cv::CAP_PROP_EXPOSURE, exposure); + } +} + +bool sv_p::CameraBase::open(void) +{ +} + +bool sv_p::CameraBase::read(cv::Mat &image) +{ + bool ret = false; + std::lock_guard locker(this->frameMutex); + if (this->frameEmpty.wait_for(this->frameMutex, std::chrono::milliseconds(this->_timeOut)) == std::cv_status::no_timeout) + { + // 获取图像 + this->imageBuff.copyTo(image); + ret = true; + } + return ret; +} + +bool sv_p::CameraBase::readNoBlock(cv::Mat &image) +{ + bool ret = false; + std::lock_guard locker(this->frameMutex); + if (this->isGot) + { + this->imageBuff.copyTo(image); + isGot = false; + } + return ret; +} + +void sv_p::CameraBase::release(void) +{ + if (this->cap.isOpened()) + { + this->cap.release(); + } +} \ No newline at end of file diff --git a/video_io/sv_camera_privately.h b/video_io/sv_camera_privately.h new file mode 100644 index 0000000..4160179 --- /dev/null +++ b/video_io/sv_camera_privately.h @@ -0,0 +1,84 @@ +#ifndef __SV_CAMERA_PRIVATELY__ +#define __SV_CAMERA_PRIVATELY__ + +#include "opencv2/opencv.hpp" +#include +#include +#include +#include +#include "sv_camera.h" + +namespace sv_p +{ + +class CameraBase +{ +private: + // 图像的属性 + int _width = 1280; + int _height = 720; + int _fps = 30; + + double _brightness = -1; + double _contrast = -1; + double _saturation = -1; + double _hue = -1; + double _exposure = -1; + + int _timeOut = 500; + // 内部状态 + double fpsCurr = -1; + bool isGot = false; + // 内部变量 + cv::Mat imageBuff; + cv::VideoCapture cap; + std::mutex frameMutex; + std::condition_variable_any frameEmpty; + std::thread::native_handle_type readThreadHandle = 0; + + // 获取图像的线程 在这个线程中查询、提取图像 + virtual void readThread(void); + +public: + // 属性设置的接口 + virtual void setWH(int width, int height); + // 基本属性 至少实现1个 + virtual bool setStream(const std::string &ip, uint16_t port) { return false; } + virtual bool setName(const std::string &name) { return false; } + virtual bool setIndex(int index) { return false; } + + // 扩展属性设置 默认调用opencv的实现 + virtual void setFps(int fps); + virtual void setBrightness(double brightness); + virtual void setContrast(double contrast); + virtual void setSaturation(double saturation); + virtual void setHue(double hue); + virtual void setExposure(double exposure); + + // 属性获取的接口 + virtual sv::CameraType getType(void) { return sv::CameraType::NONE; } + virtual std::string getName(void) { return "\0"; }; + + virtual bool isActive(void) { return (readThreadHandle == 0 ? false : true); } + int getW(void) { return _width; } + int getH(void) { return _height; } + int getExpectFps(void) { return _fps; } + double getFps(void) { return fpsCurr; } + double getBrightness(void) { return _brightness; } + double getContrast(void) { return _contrast; } + double getSaturation(void) { return _saturation; } + double getHue(void) { return _hue; } + double getExposure(void) { return _exposure; } + + // 功能接口函数 + virtual bool open(void); + virtual bool read(cv::Mat &image); + virtual bool readNoBlock(cv::Mat &image); + virtual void release(void); + + CameraBase(int timeOut); + ~CameraBase(); +}; + +} +#endif \ No newline at end of file