YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
OpenCVGrabber.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4 * SPDX-FileCopyrightText: 2006 Eric Mislivec
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8/*
9 * A YARP frame grabber device driver using OpenCV to implement
10 * image capture from cameras and AVI files.
11 */
12
13#include "OpenCVGrabber.h"
14
15#include <yarp/dev/Drivers.h>
16#include <yarp/dev/PolyDriver.h>
17
18#include <string>
19#include <yarp/os/Property.h>
20#include <yarp/os/Searchable.h>
21#include <yarp/os/Value.h>
22#include <yarp/os/Log.h>
24#include <yarp/os/LogStream.h>
25#include <yarp/sig/Image.h>
26
27#include <cstring> // memcpy
28
29#include <opencv2/core/mat.hpp>
30#include <opencv2/imgproc.hpp>
31
32
38
41using yarp::os::Value;
42
44using yarp::sig::PixelRgb;
45
46using namespace yarp::os;
47using namespace yarp::sig;
48using namespace yarp::dev;
49
50
51namespace {
52YARP_LOG_COMPONENT(OPENCVGRABBER, "yarp.device.openCVGrabber")
53}
54
55
57{
58 if (!parseParams(config)) {
59 return false;
60 }
61
62 // Are we capturing from a file or a camera ?
63 fromFile = (m_movie != "");
64 if (fromFile)
65 {
66 // Try to open a capture object for the file
67 m_cap.open(m_movie.c_str());
68 if (!m_cap.isOpened()) {
69 yCError(OPENCVGRABBER, "Unable to open file '%s' for capture!", m_movie.c_str());
70 return false;
71 }
72 } else
73 {
74 int camera_idx = m_camera;
75 // Try to open a capture object for the first camera
77 if (!m_cap.isOpened()) {
78 yCError(OPENCVGRABBER, "Unable to open camera for capture!");
79 return false;
80 }
81 else
82 {
83 yCInfo(OPENCVGRABBER, "Capturing from camera: %d",camera_idx);
84 }
85
86 if ( m_framerate != -1 ) {
87 m_cap.set(cv::VideoCaptureProperties::CAP_PROP_FPS, m_framerate);
88 }
89 }
90
91 // Extract the desired image size from the configuration if
92 // present, otherwise query the capture device
93 if (!fromFile && m_width > 0) {
94 m_cap.set(cv::VideoCaptureProperties::CAP_PROP_FRAME_WIDTH, m_width);
95 }
96 else {
97 m_width = m_cap.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_WIDTH);
98 }
99
100 if (!fromFile && m_height> 0) {
101 m_cap.set(cv::VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT, m_height);
102 }
103 else {
104 m_height = m_cap.get(cv::VideoCaptureProperties::CAP_PROP_FRAME_HEIGHT);
105 }
106
107 // Ignore capture properties - they are unreliable
108
109 yCInfo(OPENCVGRABBER, "OpenCVGrabber opened");
110 // Success!
111
112 // save our configuration for future reference
113 m_config.fromString(config.toString());
114
115 return true;
116
117}
118
119
129 // Resources will be automatically deinitialized in VideoCapture
130 // destructor
131 return true;
132}
133
134
147 // Must have a capture object
148 if (!m_cap.isOpened()) {
149 image.zero();
150 return false;
151 }
152
153 // Callers may have not initialized the image dimensions (may happen if this device is not wrapped)
154 if (static_cast<int>(image.width()) != m_width || static_cast<int>(image.height()) != m_height) {
155 image.resize(m_width, m_height);
156 }
157
158 // Grab and retrieve a frame,
159 cv::Mat bgr;
160 m_cap.read(bgr);
161
162 if (bgr.empty() && m_loop) {
163 bool ok = open(m_config);
164 if (!ok) {
165 return false;
166 }
167 m_cap.read(bgr);
168 }
169
170 if (bgr.empty()) {
171 image.zero();
172 return false;
173 }
174
175 // Memory allocation occurs at the YARP image object
176 cv::Mat frame(image.height(), image.width(), CV_8UC3, image.getRawImage(), image.getRowSize());
177
178 // Comply with the expected pixel color of the output YARP frame
179 cv::cvtColor(bgr, frame, cv::COLOR_BGR2RGB);
180
181 if (m_transpose) {
182 cv::Mat transposed;
183 cv::transpose(frame, transposed);
184 image.resize(transposed.cols, transposed.rows); // erases previous content
185 frame = cv::Mat(image.height(), image.width(), CV_8UC3, image.getRawImage(), image.getRowSize());
186 transposed.copyTo(frame);
187 }
188
189 if (m_flip_x && m_flip_y) {
190 cv::flip(frame, frame, -1);
191 } else if (m_flip_x) {
192 cv::flip(frame, frame, 0);
193 } else if (m_flip_y) {
194 cv::flip(frame, frame, 1);
195 }
196
197 if (!m_saidSize) {
198 yCDebug(OPENCVGRABBER, "Received image of size %dx%d", frame.cols, frame.rows);
199 m_saidSize = true;
200 }
201
202 // create the timestamp
204
205 if (m_width == 0) {
206 m_width = frame.cols;
207 }
208
209 if (m_height == 0) {
210 m_height = frame.rows;
211 }
212
213 if (fromFile && (frame.cols != (!m_transpose ? m_width : m_height) || frame.rows != (!m_transpose ? m_height : m_width))) {
214 if (!m_saidResize) {
215 yCDebug(OPENCVGRABBER, "Software scaling from %dx%d to %dx%d", frame.cols, frame.rows, m_width, m_height);
216 m_saidResize = true;
217 }
218
219 cv::Mat resized;
220 cv::resize(frame, resized, {m_width, m_height});
221 image.resize(resized.cols, resized.rows); // erases previous content
222 frame = cv::Mat(image.height(), image.width(), CV_8UC3, image.getRawImage(), image.getRowSize());
223 resized.copyTo(frame);
224 }
225
226 yCTrace(OPENCVGRABBER, "%d by %d image", frame.cols, frame.rows);
227
228 return true;
229}
bool parseParams(const yarp::os::Searchable &config) override
Parse the DeviceDriver parameters.
bool fromFile
Whether reading from file or camera.
yarp::os::Property m_config
Saved copy of the device configuration.
bool getImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
Read an image from the grabber.
bool close() override
Close a grabber.
cv::VideoCapture m_cap
OpenCV image capture object.
bool open(yarp::os::Searchable &config) override
Open the DeviceDriver.
yarp::os::Stamp m_laststamp
Interface implemented by all device drivers.
A factory for creating driver objects of a particular type.
Definition Drivers.h:81
Global factory for devices.
Definition Drivers.h:171
A container for a device driver.
Definition PolyDriver.h:23
A mini-server for performing network communication in the background.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
T * read(bool shouldWait=true) override
Read an available object from the port.
A class for storing options and configuration information.
Definition Property.h:33
void fromString(const std::string &txt, bool wipe=true)
Interprets a string as a list of properties.
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual std::string toString() const =0
Return a standard text representation of the content of the object.
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition Stamp.cpp:124
A single value (typically within a Bottle).
Definition Value.h:43
Typed image class.
Definition Image.h:605
#define yCInfo(component,...)
#define yCError(component,...)
#define yCTrace(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
For streams capable of holding different kinds of content, check what they actually have.
An interface to the operating system, including Port based communication.