Robotics StackExchange | Archived questions

Error linking to OpenCV DNN Library

I'm writing a Publisher-Subscriber node to run a face detection program using the images from my webcam. I am trying to use the OpenCV DNN module. The problem is, whenever I try to catkin_make my project, the following is output on the console:

pedrosc@PEDROSC:~/robotics$ catkin_make
Base path: /home/pedrosc/robotics
Source space: /home/pedrosc/robotics/src
Build space: /home/pedrosc/robotics/build
Devel space: /home/pedrosc/robotics/devel
Install space: /home/pedrosc/robotics/install
####
#### Running command: "make cmake_check_build_system" in "/home/pedrosc/robotics/build"
####
####
#### Running command: "make -j8 -l8" in "/home/pedrosc/robotics/build"
####
[ 50%] Linking CXX executable /home/pedrosc/robotics/src/artrack/src/artrack_imgproc
CMakeFiles/artrack_imgproc.dir/src/artrack_imgproc.cpp.o: In function `ImageProcessor::ImageProcessor()':
artrack_imgproc.cpp:(.text._ZN14ImageProcessorC2Ev[_ZN14ImageProcessorC5Ev]+0xdd): undefined reference to `cv::dnn::experimental_dnn_v2::Net::Net()'
artrack_imgproc.cpp:(.text._ZN14ImageProcessorC2Ev[_ZN14ImageProcessorC5Ev]+0x622): undefined reference to `cv::dnn::experimental_dnn_v2::Net::~Net()'
CMakeFiles/artrack_imgproc.dir/src/artrack_imgproc.cpp.o: In function `ImageProcessor::~ImageProcessor()':
artrack_imgproc.cpp:(.text._ZN14ImageProcessorD2Ev[_ZN14ImageProcessorD5Ev]+0x53): undefined reference to `cv::dnn::experimental_dnn_v2::Net::~Net()'
artrack_imgproc.cpp:(.text._ZN14ImageProcessorD2Ev[_ZN14ImageProcessorD5Ev]+0xd4): undefined reference to `cv::dnn::experimental_dnn_v2::Net::~Net()'
collect2: error: ld returned 1 exit status
artrack/CMakeFiles/artrack_imgproc.dir/build.make:229: recipe for target '/home/pedrosc/robotics/src/artrack/src/artrack_imgproc' failed
make[2]: *** [/home/pedrosc/robotics/src/artrack/src/artrack_imgproc] Error 1
CMakeFiles/Makefile2:477: recipe for target 'artrack/CMakeFiles/artrack_imgproc.dir/all' failed
make[1]: *** [artrack/CMakeFiles/artrack_imgproc.dir/all] Error 2
Makefile:138: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j8 -l8" failed

I have successfully installed OpenCV 3.4.5 (since the one included with ROS Kinetic is version 3.0.0 and it doesn't have the files I need). Here is my CMakeLists.txt file:

cmake_minimum_required(VERSION 2.8.3)
project(artrack)
find_package(catkin REQUIRED COMPONENTS
    roscpp 
    rospy
    std_msgs
    message_generation
    image_transport
    geometry_msgs
    ardrone_autonomy
)

find_package(OpenCV 3.4.5 REQUIRED)
find_package(uvc_camera REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(cv_bridge REQUIRED)

include_directories(
    ${catkin_INCLUDE_DIRS}
    ${uvc_camera_INCLUDE_DIRS}
    ${cv_bridge_INCLUDE_DIRS}
    ${sensor_msgs_INCLUDE_DIRS}
    ${OpenCV_INCLUDE_DIRS}
)


add_executable(artrack_imgproc src/artrack_imgproc.cpp)
target_link_libraries(artrack_imgproc 
    ${catkin_LIBRARIES}
    ${uvc_camera_LIBRARIES}
    ${cv_bridge_LIBRARIES}
    ${sensors_msgs_LIBRARIES}
    ${OpenCV_LIBRARIES}
)
set_target_properties(artrack_imgproc PROPERTIES RUNTIME_OUTPUT_DIRECTORY ~/robotics/src/artrack/src)


catkin_package(CATKIN_DEPENDS
    message_runtime
    sensor_msgs
    image_transport
    cv_bridge
    geometry_msgs
)

And the .cpp file for the node:

//////////////////////////////////////////////////////////////////////////////////////////////////////
//  
//  ImageProcessor 
//  
//  Node source code for the processing of the image. It uses neural networks to detect faces,
//  then tracks the detected face using a tracking algorithm. It publishes the coordinates of
//  the centroid of the face. This node also handles the GUI elements of the main window of 
//  the project.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/core.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/utils/trace.hpp>
#include <iostream>

using namespace cv;
using namespace cv::dnn;
using namespace std;

static const std::string OPENCV_WINDOW = "OpenCV Image Window";

//Image Processor Class

class ImageProcessor
{
  //Object declarations for the ROS elements
  ros::NodeHandle nh_;

  image_transport::ImageTransport it_;
  image_transport::Subscriber image_sub_;
  image_transport::Publisher image_pub_;

  //Object initialization for neural network
  cv::dnn::Net net;

  //Variables
  uint16_t columns = 0, rows = 0;
  uint16_t detections[];


public:
  ImageProcessor()
    : it_(nh_)
  {

    //Assign publisher and subscriber to receive image and output it

    image_sub_        = it_.subscribe("imageinput", 1, &ImageProcessor::imagePr, this);
    image_pub_        = it_.advertise("/artrack/output_video", 1);


    //Initializing an OpenCV Window

    cv::namedWindow(OPENCV_WINDOW);

    //Initializing strings containing paths for the prototxt and caffemodel files

    cv::String modelTxt = "/home/pedrosc/robotics/src/artrack/src/deploy.prototxt.txt";
    cv::String modelBin = "/home/pedrosc/robotics/src/artrack/src/res10_300x300_ssd_iter_140000.caffemodel";

    //Initializing and configuring the neural network

    try {
        net = cv::dnn::readNetFromCaffe(modelTxt, modelBin);
    }
    catch (cv::Exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        if (net.empty())
        {
            std::cerr << "Can't load network by using the following files: " << std::endl;
            std::cerr << "prototxt:   " << modelTxt << std::endl;
            std::cerr << "caffemodel: " << modelBin << std::endl;
            exit(-1);
        }
    }

  }

  ~ImageProcessor()
  {
    cv::destroyWindow(OPENCV_WINDOW);
  }

  void imagePr(const sensor_msgs::ImageConstPtr& msg)
  {

    //Convert ROS Message Image into OpenCV Image

    cv_bridge::CvImagePtr cv_ptr;
    try
    {
      cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
    }
    catch (cv_bridge::Exception& e)
    {
      ROS_ERROR("cv_bridge exception: %s", e.what());
      return;
    }

    //Assigning converted image into a Mat variable 
    cv::Mat original = cv_ptr->image;

    //Extracting original dimensions
    columns = original.cols;
    rows = original.rows;

    //Creating a blob and resizing the input
    //cv::Mat inputBlob = cv::dnn::blobFromImage(original, 1.0f, cv::Size(300, 300), cv::Scalar(104, 177, 123), false);

    //Input and run the blob through the neural network
    //net.setInput(inputBlob);
    //cv::Mat detections = net.forward();

    //Display results
    cv::imshow(OPENCV_WINDOW, original);
    cv::waitKey(3);
  }

};

//Main

int main(int argc, char** argv)
{

  //Initialize ROS Node called imageProcessor
  ros::init(argc, argv, "imageProcessor");

  //Initialize a new object called ip, class ImageProcessor
  ImageProcessor ip;

  //"Loop" the ROS cycle
  ros::spin();

  return 0;
}

Any help would be really appreciated!!!!

Asked by pedrosc97 on 2019-01-08 16:28:17 UTC

Comments

Answers

Hi, I also have a problem like you with the OpenCV 3.4.1 and trying to use DNN with ROS. But I managed to solve it, by adding the cv_bridge from source to my workspace and modify the CMakelists to use the same local OpenCV version.

The problem is caused by cv_bridge which use the OpenCV 3 from ROS instead of our local version. Hope it works!


This is my CMakelists

cmake_minimum_required(VERSION 2.8.3)
project(dnn_detector)

add_compile_options(-std=c++11)

find_package(catkin REQUIRED COMPONENTS
    roscpp
    roslib
    std_msgs
    sensor_msgs
    geometry_msgs
    dynamic_reconfigure
    cv_bridge
    image_transport
    message_generation
    )

find_package(Boost REQUIRED COMPONENTS thread)

set(OpenCV_DIR "/usr/local/share/OpenCV/")
find_package(OpenCV 3.4.1 REQUIRED)
find_package(yaml-cpp REQUIRED)

################################################################################
# Declare catkin specific configuration to be passed to dependent projects
##################################################################################
catkin_package(
    INCLUDE_DIRS include
    CATKIN_DEPENDS
    roscpp
    roslib
    std_msgs
    sensor_msgs
    geometry_msgs
    dynamic_reconfigure
    cv_bridge
    image_transport
    message_runtime
    DEPENDS Boost OpenCV
    )

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
    include
    ${OpenCV_INCLUDE_DIRS}
    ${catkin_INCLUDE_DIRS}
    ${Boost_INCLUDE_DIRS}
    ${YAML_CPP_INCLUDE_DIR}
    )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(${PROJECT_NAME}_node dnn_detector_node.cpp
    src/dnn_detector.cpp
    )

## Add cmake target dependencies of the executable
## same as for the library above
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS} dnn_detector_generate_messages_cpp)

## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}_node
    ${catkin_LIBRARIES}
    ${OpenCV_LIBS}
    ${Boost_LIBRARIES}
    ${YAML_CPP_LIBRARIES}
    )

Asked by haritsahm on 2019-02-05 22:23:49 UTC

Comments