Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for cv::VideoCapture #2

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions camera_base.orogen
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,14 @@ task_context "Task" do
argument('type', '/camera/double_attrib/CamAttrib', 'type')
end

# Task using OpenCV video caputre
task_context "VideoCapture" do
subclasses "camera_base::Task"
needs_configuration

periodic 0.02
end

# Task to pre-process images before used by other components
task_context "Preprocess" do
reports :PROCESSING_ERROR
Expand Down Expand Up @@ -208,3 +216,5 @@ task_context "Preprocess" do

port_driven
end


226 changes: 226 additions & 0 deletions tasks/VideoCapture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
/* Generated from orogen/lib/orogen/templates/tasks/Task.cpp */

#include "VideoCapture.hpp"
#include <camera_interface/CamInterface.h>
#include <opencv2/videoio.hpp>

using namespace camera;
using namespace camera_base;

// links the opencv interface to the CamInterface
class CamVideoCapture :public camera::CamInterface
{
public:
virtual ~CamVideoCapture(){};
virtual int listCameras(std::vector<CamInfo> &cam_infos)const
{
return 0;
}
virtual void openCamera(std::string camera_name)
{
frame_available = false;
if(!capture.open(camera_name))
throw std::runtime_error("cannot open camera");
capture.set(cv::CAP_PROP_CONVERT_RGB,1);
}
virtual bool isOpen()const
{
return capture.isOpened();
}
virtual bool close()
{
capture = cv::VideoCapture();
return true;
}
virtual bool grab(const GrabMode mode = SingleFrame, const int buffer_len=1)
{
// changing grab mode is not supported
return true;
}
virtual bool retrieveFrame(base::samples::frame::Frame &frame,const int timeout=1000)
{
base::Time time = base::Time::now();
do
{
if(isFrameAvailable())
{
// create copy because we are not allowed to modify internal
// buffer
frame_available = false;
if(capture.retrieve(image))
{
frame_helper::FrameHelper::copyMatToFrame(image,frame);
frame.time = time;
frame.frame_status = base::samples::frame::STATUS_VALID;
return true;
}
}
usleep(100);
}
while((base::Time::now()-time).toMilliseconds() <= timeout);
return false;
}
virtual bool isFrameAvailable()
{
if(!frame_available)
frame_available = capture.grab();
return frame_available;
}

virtual bool setFrameSettings(const base::samples::frame::frame_size_t size,
const base::samples::frame::frame_mode_t mode,
const uint8_t color_depth,
const bool resize_frames)
{
base::samples::frame::Frame frame(0,0,color_depth,mode);
// this does not work for video streams and some cameras!
// capture.set(cv::CAP_PROP_FRAME_WIDTH,size.width);
// capture.set(cv::CAP_PROP_FRAME_HEIGHT,size.height);
// capture.set(cv::CAP_PROP_FORMAT,frame_helper::FrameHelper::getOpenCvType(frame));
return true;
}
bool isAttribAvail(const int_attrib::CamAttrib attrib)
{
switch(attrib)
{
case int_attrib::GainValue:
return true;
default:
return false;
}
return true;
}
bool isAttribAvail(const double_attrib::CamAttrib attrib)
{
switch(attrib)
{
case double_attrib::FrameRate:
return true;
default:
return false;
}
return true;
}
bool isAttribAvail(const enum_attrib::CamAttrib attrib)
{
return false;
}
bool setAttrib(const int_attrib::CamAttrib attrib,const int value)
{
switch(attrib)
{
case int_attrib::GainValue:
capture.set(cv::CAP_PROP_GAIN,value);
break;
default:
return false;
}
return true;
}
bool setAttrib(const double_attrib::CamAttrib attrib,const double value)
{
switch(attrib)
{
case double_attrib::FrameRate:
capture.set(cv::CAP_PROP_FPS,value);
break;
default:
return false;
}
return true;
}
int getAttrib(const int_attrib::CamAttrib attrib)
{
switch(attrib)
{
case int_attrib::GainValue:
return capture.get(cv::CAP_PROP_GAIN);
default:
return false;
}
return true;
}
double getAttrib(const double_attrib::CamAttrib attrib)
{
switch(attrib)
{
case double_attrib::FrameRate:
return capture.get(cv::CAP_PROP_FPS);
default:
return false;
}
return true;
}

private:
cv::VideoCapture capture;
cv::Mat image;
bool frame_available;
};

//CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
//CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
//CAP_PROP_FORMAT Format of the Mat objects returned by retrieve() .
//CAP_PROP_CONTRAST Contrast of the image (only for cameras).
//CAP_PROP_SATURATION Saturation of the image (only for cameras).
//CAP_PROP_HUE Hue of the image (only for cameras).
//CAP_PROP_EXPOSURE Exposure (only for cameras).
//

VideoCapture::VideoCapture(std::string const& name)
: VideoCaptureBase(name)
{
}

VideoCapture::VideoCapture(std::string const& name, RTT::ExecutionEngine* engine)
: VideoCaptureBase(name, engine)
{
}

VideoCapture::~VideoCapture()
{
}


void VideoCapture::processImage()
{
// resize output otherwise processing goes crazy
// this is needed because the size is not always known at the beginning
base::samples::frame::Frame *frame_ptr = output_frame.write_access();
frame_ptr->init(camera_frame->size.width,camera_frame->size.height,camera_frame->data_depth,_output_format.get());
output_frame.reset(frame_ptr);
Task::processImage();
}

bool VideoCapture::configureHook()
{
if (! VideoCaptureBase::configureHook())
return false;

CamVideoCapture* camera = new CamVideoCapture();
camera->openCamera(_camera_id.value());
cam_interface = camera;
return true;
}
bool VideoCapture::startHook()
{
if (! VideoCaptureBase::startHook())
return false;
return true;
}
void VideoCapture::updateHook()
{
VideoCaptureBase::updateHook();
}
void VideoCapture::errorHook()
{
VideoCaptureBase::errorHook();
}
void VideoCapture::stopHook()
{
VideoCaptureBase::stopHook();
}
void VideoCapture::cleanupHook()
{
VideoCaptureBase::cleanupHook();
}
109 changes: 109 additions & 0 deletions tasks/VideoCapture.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/* Generated from orogen/lib/orogen/templates/tasks/Task.hpp */

#ifndef CAMERA_BASE_VIDEOCAPTURE_TASK_HPP
#define CAMERA_BASE_VIDEOCAPTURE_TASK_HPP

#include "camera_base/VideoCaptureBase.hpp"

namespace camera_base{

/*! \class VideoCapture
* \brief The task context provides and requires services. It uses an ExecutionEngine to perform its functions.
* Essential interfaces are operations, data flow ports and properties. These interfaces have been defined using the oroGen specification.
* In order to modify the interfaces you should (re)use oroGen and rely on the associated workflow.
* Task using OpenCV video caputre
* \details
* The name of a TaskContext is primarily defined via:
\verbatim
deployment 'deployment_name'
task('custom_task_name','camera_base::VideoCapture')
end
\endverbatim
* It can be dynamically adapted when the deployment is called with a prefix argument.
*/
class VideoCapture : public VideoCaptureBase
{
friend class VideoCaptureBase;
protected:
virtual void processImage();

public:
/** TaskContext constructor for VideoCapture
* \param name Name of the task. This name needs to be unique to make it identifiable via nameservices.
* \param initial_state The initial TaskState of the TaskContext. Default is Stopped state.
*/
VideoCapture(std::string const& name = "camera_base::VideoCapture");

/** TaskContext constructor for VideoCapture
* \param name Name of the task. This name needs to be unique to make it identifiable for nameservices.
* \param engine The RTT Execution engine to be used for this task, which serialises the execution of all commands, programs, state machines and incoming events for a task.
*
*/
VideoCapture(std::string const& name, RTT::ExecutionEngine* engine);

/** Default deconstructor of VideoCapture
*/
~VideoCapture();

/** This hook is called by Orocos when the state machine transitions
* from PreOperational to Stopped. If it returns false, then the
* component will stay in PreOperational. Otherwise, it goes into
* Stopped.
*
* It is meaningful only if the #needs_configuration has been specified
* in the task context definition with (for example):
\verbatim
task_context "TaskName" do
needs_configuration
...
end
\endverbatim
*/
bool configureHook();

/** This hook is called by Orocos when the state machine transitions
* from Stopped to Running. If it returns false, then the component will
* stay in Stopped. Otherwise, it goes into Running and updateHook()
* will be called.
*/
bool startHook();

/** This hook is called by Orocos when the component is in the Running
* state, at each activity step. Here, the activity gives the "ticks"
* when the hook should be called.
*
* The error(), exception() and fatal() calls, when called in this hook,
* allow to get into the associated RunTimeError, Exception and
* FatalError states.
*
* In the first case, updateHook() is still called, and recover() allows
* you to go back into the Running state. In the second case, the
* errorHook() will be called instead of updateHook(). In Exception, the
* component is stopped and recover() needs to be called before starting
* it again. Finally, FatalError cannot be recovered.
*/
void updateHook();

/** This hook is called by Orocos when the component is in the
* RunTimeError state, at each activity step. See the discussion in
* updateHook() about triggering options.
*
* Call recover() to go back in the Runtime state.
*/
void errorHook();

/** This hook is called by Orocos when the state machine transitions
* from Running to Stopped after stop() has been called.
*/
void stopHook();

/** This hook is called by Orocos when the state machine transitions
* from Stopped to PreOperational, requiring the call to configureHook()
* before calling start() again.
*/
void cleanupHook();
};
}

#endif