Ask Your Question
0

Splitting side-by-side video into stereo/left stereo/right

asked 2019-02-11 13:16:50 -0600

dcurtis gravatar image

I am experimenting with a cheap stereo webcam (ELP-960P2CAM-V90-VC https://www.amazon.com/gp/product/B07... ) that publishes the stereo image as a single side-by-side image that is double wide. It is trivial with OpenCV/Numpy to split out the left and right images as array slices. From searching around here it seems that it should be simple to write a small node that reads /dev/videoN and republishes on stereo/left/* and stereo/right/* image and camera_info topics. Yet, it does not seem that this node exists, nor is sXs video supported by libuvc_camera.

Does anyone have pointers to something that I have missed? Might it make sense to add this functionality directly to libuvc_camera?

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2019-02-11 14:32:17 -0600

I made a node a while ago for almost exactly the same task, except mine only re-published either the left or the right but not both. Here is a quick copy paste of my node, you should be able to modify it fairly easily so it achieves what you what.

#include <ros/ros.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <image_transport/image_transport.h>

// global controlling which half of the image will be re-published
std::string side;

// size of the output image
int outputWidth, outputHeight;

image_transport::Publisher rePublisher;

// Image capture callback
void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
    // get double camera image
    cv_bridge::CvImagePtr cvImg = cv_bridge::toCvCopy(msg, "rgb8");
    cv::Mat image = cvImg->image;

    // if there are any subscribers to the topic then publish image on it
    if (rePublisher.getNumSubscribers() > 0)
    {
        // define the relevant rectangle to crop
        cv::Rect ROI;
        ROI.y = 0;
        ROI.width = image.cols / 2;
        ROI.height = image.rows;
        if (side == "left")
            ROI.x = 0;
        else
            ROI.x = image.cols / 2;

        // crop image and publish
        cv::Mat croppedImage = cv::Mat(image, ROI);

        cv::Mat scaledImage;
        cv::resize(croppedImage,
                   scaledImage,
                   cv::Size(outputWidth, outputHeight) );

        cv_bridge::CvImage cvImage;
        cvImage.image = scaledImage;
        cvImage.encoding = "bgr8";
        rePublisher.publish(cvImage.toImageMsg());
    }
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "half_image_publisher_node");
    ros::NodeHandle nh("~");

    image_transport::ImageTransport it(nh);

    // load node settings
    std::string inputTopic, outputTopic;
    nh.param("image_side", side, std::string("left"));
    nh.param("input_topic", inputTopic, std::string("not_set"));
    nh.param("output_topic", outputTopic, std::string("not_set"));
    nh.param("width", outputWidth, 640);
    nh.param("height", outputHeight, 480);

    // register publisher and subscriber
    ros::Subscriber imageSub = nh.subscribe(inputTopic.c_str(), 2, &imageCallback);

    rePublisher = it.advertise(outputTopic.c_str(), 1);

    // run node until cancelled
    ros::spin();
}
edit flag offensive delete link more

Comments

Thanks, looks great! Should be an easy mod.

dcurtis gravatar imagedcurtis ( 2019-02-11 20:41:44 -0600 )edit
1

answered 2019-02-25 19:27:11 -0600

dcurtis gravatar image

My first whack at a stereo splitter node is at: https://github.com/dbc/side_x_side_st...

Lightly tested with one of the cheap stereo USB cameras I have been testing. Image rescaling has not been tested.

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2019-02-11 13:16:50 -0600

Seen: 181 times

Last updated: Feb 25 '19