Robotics StackExchange | Archived questions

Sensor image convert and comparision using opencv

Hello All, I want to compare two(or more) consecutive image to detect movement within a range. For example, if there is anything in front of kinect camera within 60cm then it will detect and then just tell me if the object is moving or stationary. I repeat, I do not need to track any object, do not need to detect any pattern. Just need ato know if anything is moving infront of the camera within a range. I am using ros indigo, ubuntu 14.04 and having kinect cam. I am subscribing the topic /camera/depth/imageraw and getting image of type sensormsgs::Image. So now I want to compare the two image. If there is a difference in the images then the decision is that there is something moving in front of the camera. I want to use opencv image comparison feature.

edit 1: I used another node which subscribed /camera/depth/points , and from there i detected if there is something in front of camera within 60cm range. Then i published a boolean flag. Using this node below I was trying to know if there is something within the range, it will tell us if the object is static or moving. But now I want to do it in the same node below as I came to know /camera/depth/imageraw gives image with depth data and I can get it using opencv function int depth = imagecur.at(cv::Point(j,i));

but somehow I am not getting it exactly. Like if there is nothing moving in front of camera, i get the response something is moving. Because in each frame there is difference of values. My question is, if nothing is moving infront of camera, then why the data array are not identical for sequential images ?

I am going to update the codes below,

include

include

include "std_msgs/String.h"

include "geometry_msgs/Twist.h"

include

include

include

include

include

include

include

include

include

include

include

include

include

//Store all constants for image encodings in the enc namespace to be used later. namespace enc = sensormsgs::imageencodings;

using namespace::std; using namespace cv;

sensormsgs::Image imgprevious, imgcurrent, imgprimary; stdmsgs::Bool checkmovingobj , obstaclefound, ismovingobs; bool checkmovingobs= true;

ros::Publisher pub, dec_pub;

double scalelinear, scaleangular; void deccallback(const stdmsgs::Bool::ConstPtr& msg) { checkmovingobs = msg->data; } void callback(const sensor_msgs::Image::ConstPtr& msg){

 if(check_moving_obs)
 {
     if(img_previous.data.size() == 0)
     {
         img_previous = *msg;
         img_primary = *msg;
     }
     else
         {img_previous = img_current;}
    img_current = *msg;

    cout<<"------------------------current image info :---------:"<<img_current.data.size()<<"\n";
    cout<<"------------------------Height :---------:"<<img_current.height<<"\n";
    cout<<"------------------------Width :---------:" <<img_current.width<<"\n";

    cout<<"------------------------previous image info :---------:"<<img_previous.data.size()<<"\n";
    cout<<"------------------------Height :---------:"<<img_previous.height<<"\n";
    cout<<"------------------------Width :---------:" <<img_previous.width<<"\n";


        //Convert from the ROS image message to a CvImage suitable for working with OpenCV for processing
            cv_bridge::CvImagePtr cv_ptr_prev, cv_ptr_cur;
            cv::Mat image_cur, image_pre, differenceImage;
            //thresholded difference image (for use in findContours() function)
            cv::Mat thresholdImage;

            try
            {

                //Always copy, returning a mutable CvImage
                //OpenCV expects color images to use BGR channel order.
                cv_ptr_cur = cv_bridge::toCvCopy(msg, enc::TYPE_16UC1);//cv_bridge::toCvCopy(img_current, enc::BGR8);
                cv_ptr_prev = cv_bridge::toCvCopy(img_previous, enc::TYPE_16UC1);


                image_cur = cv_ptr_cur->image;
                image_pre = cv_ptr_prev->image;
                int count_diff=0;
                bool motion_detected = false;

                //perform frame differencing with the sequential images.
                cv::absdiff(image_cur,image_pre,differenceImage);
                cout<<"~~~~~~~~~~~~~~~~~~~~~~difference image info :---------:"<<differenceImage.total()<<"\n";
                for(int j=0; j<image_cur.rows; ++j)
                {
                    if(count_diff > 150) //this is just a random try to give a threshhold value. 
                    {
                        break;
                    }
                        for(int i=0; i<image_cur.cols; ++i)
                        {
                            int depth = image_cur.at<short int>(cv::Point(j,i));
                            if(depth < 0.6)
                            {
                                if(image_cur.at<cv::Vec3b>(j,i) != image_pre.at<cv::Vec3b>(j,i))
                                {
                                    cout<<"i : "<<i<<" ... j : "<<j<<"\n";
                                    cout<<"iamge curr : "<< image_cur.at<cv::Vec3b>(j,i)<<"\n";
                                    cout<<"iamge prev : "<< image_pre.at<cv::Vec3b>(j,i)<<"\n";
                                    count_diff++;
                                }

                                if(count_diff > 150)
                                {
                                    motion_detected = true;
                                    break;
                                }
                            }
                        }
                }
                if(motion_detected)
                {
                    cout<<"------------------------something is moving stop and wait---------"<<"\n";
                }

                //threshold intensity image at a given sensitivity value
                //cv::threshold(differenceImage,thresholdImage, 20,255,cv::THRESH_BINARY);
                //show the difference image and threshold image
                //cv::imshow("Difference Image",differenceImage);
                //cv::imshow("Threshold Image", thresholdImage);

                //imshow("Frame1",image_pre);

            }
            catch (cv_bridge::Exception& e)
            {
                //if there is an error during conversion, display it
                ROS_ERROR("cv_bridge exception: %s", e.what());
                return;
            }
       //pub.publish( msg_decission);
    }
 sleep(1);//use sleep if you want to delay loop.

}

int main(int argc, char** argv) { ros::init(argc, argv,"listenerdepthcomparer"); ros::NodeHandle nh; nh.param("scalelinear", scalelinear, 1.0); nh.param("scaleangular", scaleangular, 1.0); ros::Subscriber sub = nh.subscribe("/camera/depth/imageraw", 1, callback); //ros::Subscriber sub = nh.subscribe<sensormsgs::Image>("/camera/depthregistered/imageraw", 1, callback);

ros::Subscriber decsub = nh.subscribe<stdmsgs::Bool>("obstacleDetectionDecision", 1, dec_callback);

decpub = nh.advertise<geometrymsgs::Twist>("/cmdvel", 1, true); //ros::Subscriber sub = nh.subscribe<sensormsgs::PointCloud2>("/camera/depth/points", 1, chatterCallback); //kinect ros::spin(); }


Can anyone please help me what is wrong here....?

Asked by rasoo on 2016-10-17 10:04:20 UTC

Comments

Organise your question better so it is easy for us to read and help you

Asked by patrchri on 2016-10-17 16:54:34 UTC

It looks like you aren't including cv_bridge in your CMakeLists.txt- it should be in find_package. You could post your CMakeLists.txt here as well.

Asked by lucasw on 2016-10-18 15:33:55 UTC

Thanks @lucasw for your important observation. I added the line find_package(OpenCV 2 REQUIRED) But now its a new problem. My source is not building and it is hang. I have to restart my laptop. I guess now the installed version is different from openCV 2. But I cuold not solve the issue yet.

Asked by rasoo on 2016-10-18 20:25:22 UTC

Find catkin and any catkin packages

find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg message_generation pcl_conversions pcl_ros tf
) find_package(PCL REQUIRED)

find_package(OpenCV 2 REQUIRED)

Asked by rasoo on 2016-10-18 20:25:37 UTC

Adding cv_bridge to the other find_package catkin components will include opencv, it doesn't need to be in a separate find_package.

Asked by lucasw on 2016-10-19 07:02:10 UTC

Thank you once again for your valuable response. I changed it as per your suggestion. But still the program is not compiling. Can you please have look at the part below in the next comment and please suggest if i need any change. Because listener_depthImage_comparer.cpp is the file where i used it

Asked by rasoo on 2016-10-19 08:08:04 UTC

add_executable(listener_depthImage_compare src/listener_depthImage_compare.cpp) target_link_libraries(listener_depthImage_compare ${catkin_LIBRARIES} ) add_dependencies(listener_depthImage_compare beginner_tutorials_generate_messages_cpp)

I am confused about the add_dependecies section.

Asked by rasoo on 2016-10-19 08:08:43 UTC

generate_messages(DEPENDENCIES std_msgs) find_package(catkin REQUIRED COMPONENTS sensor_msgs cv_bridge image_transport
roscpp rospy std_msgs genmsg message_generation pcl_conversions pcl_ros tf
)

Asked by rasoo on 2016-10-19 08:12:52 UTC

Put your entire CMakeLists.txt in to the question so it is easy to read.

Asked by lucasw on 2016-10-20 07:18:21 UTC

hello Lucas, thanks for your concern. Somehow I manage to solve the problem. There was no error but it was not compiling.So I created a whole new project and put the packages one by one and it successfully compiled. Your previous suggestion was really helpful. Adding cv_bridge is working. :)

Asked by rasoo on 2016-10-20 08:24:54 UTC

I have edited my question. Can you please have a look on it. :) thanks in advance.

Asked by rasoo on 2016-10-20 08:41:08 UTC

Answers