Hello i am trying to convert a ros2 topic which named “/serit” to a v4l2 virtual camera which named “/dev/video4”
i have writen this code
#include <opencv2/opencv.hpp>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <errno.h>
#include <cstring>
using namespace std;
using namespace cv;
bool writeToV4L2VirtualCamera(cv::Mat& image, const char* device = "/dev/video4") {
// Open the V4L2 device
int fd = open(device, O_RDWR);
if (fd == -1) {
std::cerr << "Error: Could not open V4L2 device. Error code: " << errno << std::endl;
return false;
}
// Get the current format of the device
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
if (ioctl(fd, VIDIOC_G_FMT, &fmt) == -1) {
std::cerr << "Error: Could not get format. Error code: " << errno << std::endl;
close(fd);
return false;
}
// Print the current format
std::cout << "Current format - Width: " << fmt.fmt.pix.width
<< ", Height: " << fmt.fmt.pix.height
<< ", Pixelformat: " << (char*)&fmt.fmt.pix.pixelformat
<< ", Field: " << fmt.fmt.pix.field << std::endl;
// Convert the image to the format required by V4L2
cv::Mat yuv_image;
cv::cvtColor(image, yuv_image, cv::COLOR_BGR2YUV_I420);
// Write the image data to the device
size_t bufferSize = yuv_image.total() * yuv_image.elemSize();
if (write(fd, yuv_image.data, bufferSize) == -1) {
std::cerr << "Error: Could not write to V4L2 device. Error code: " << errno << " - " << strerror(errno) << std::endl;
close(fd);
return false;
}
// Close the device
close(fd);
return true;
}
class ImageSubscriber : public rclcpp::Node {
public:
ImageSubscriber() : Node("image_subscriber") {
subscription_ = this->create_subscription<sensor_msgs::msg::Image>(
"/serit", 10, std::bind(&ImageSubscriber::listener_callback, this, std::placeholders::_1));
}
private:
void listener_callback(const sensor_msgs::msg::Image::SharedPtr msg) {
cv::Mat cv_image = cv_bridge::toCvCopy(msg, "bgr8")->image;
// Specify new size directly
cv::Size newSize(640, 480); // Example: resize to 640x480
cv::Mat resizedImage;
cv::resize(cv_image, resizedImage, newSize);
if (!writeToV4L2VirtualCamera(resizedImage)) {
std::cerr << "Error: Failed to write image to V4L2 device" << std::endl;
}
imshow("Image", resizedImage);
waitKey(1);
namedWindow("Image", WINDOW_KEEPRATIO);
}
rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_;
};
int main(int argc, char* argv[]) {
rclcpp::init(argc, argv);
auto node = std::make_shared<ImageSubscriber>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
but it didn’t worked out
i got this error:
Current format - Width: 640, Height: 480, Pixelformat: YU12, Field: 1
Error: Could not write to V4L2 device. Error code: 22 - Invalid argument
Error: Failed to write image to V4L2 device
at every image that i am trying to convert
can you help me out please
onvert a ros2 topic which named “/serit” to a v4l2 virtual camera which named “/dev/video4”
New contributor
Metehan SOYLU is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.