I am trying to do the ros_wiki tutorial to convert ROS images to OpenCV images, but when I try to compile my catkin workspace I get several pages of errors that all have the following form:
CMakeFiles/image_converter.dir/scripts/image_converter.cpp.o: In function `cv::String::~String()':
image_converter.cpp:(.text._ZN2cv6StringD2Ev[_ZN2cv6StringD5Ev]+0x14): undefined reference to `cv::String::deallocate()'
I've googled around a lot and found various similar problems, but those problems were all fixed by updating the CMakeLists.txt file and the package.xml file, which did not work for me.
Here is an example of one such solution - they all center around including
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
target_link_libraries( your_target ${OpenCV_LIBS} )
in the cmakelists, but I have those already.
My C++ code:
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <string>
#include <iostream>
const std::string wn = "OCV_window";
class ImageConverter
{
ros::NodeHandle nh_;
image_transport::ImageTransport it_;
image_transport::Subscriber image_sub_;
image_transport::Publisher image_pub_;
public:
ImageConverter()
: it_(nh_)
{
image_sub_ = it_.subscribe("/camera/color/image_raw", 1, &ImageConverter::imageCb, this);
image_pub_ = it_.advertise("/image_editor/output_image", 1);
cv::namedWindow(wn);
}
~ImageConverter()
{
cv::destroyWindow(wn);
}
void imageCb(const sensor_msgs::ImageConstPtr& incoming_message)
{
cv_bridge::CvImagePtr cvi;
try
{
cvi = cv_bridge::toCvCopy(incoming_message, sensor_msgs::image_encodings::RGB8);
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("CV_Bridge Exception: %s", e.what());
return;
}
cv::imshow(wn, cvi->image);
cv::waitKey(3);
image_pub_.publish(cvi->toImageMsg());
}
};
int main(int argc, char** argv)
{
ros::init(argc,argv, "Image_Converter");
ImageConverter ic;
ros::spin();
return(0);
}
My cmakelists file:
cmake_minimum_required(VERSION 2.8.3)
project(odom_reporter)
add_compile_options(-std=c++11)
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
nav_msgs
roscpp
rospy
std_msgs
message_generation
image_transport
cv_bridge
sensor_msgs
OpenCV REQUIRED
)
add_service_files(
FILES
HMD.srv
)
catkin_package()
include_directories(
${OpenCV_INCLUDE_DIRS}
${catkin_INCLUDE_DIRS}
)
add_executable (image_converter scripts/image_converter.cpp)
target_link_libraries (image_converter ${OpenCV_LIBS})
My package.xml file:
<?xml version="1.0"?>
<package format="2">
<name>odom_reporter</name>
<version>0.0.0</version>
<description>The odom_reporter package</description>
<maintainer email="calabrnb#mail.uc.edu">Nate Calabrese</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>nav_msgs</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>message_generation</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>OpenCV</build_depend>
<build_export_depend>geometry_msgs</build_export_depend>
<build_export_depend>nav_msgs</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<build_export_depend>message_runtime</build_export_depend>
<build_export_depend>image_transport</build_export_depend>
<build_export_depend>cv_bridge</build_export_depend>
<build_export_depend>sensor_msgs</build_export_depend>
<build_export_depend>OpenCV</build_export_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>nav_msgs</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>message_runtime</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>cv_bridge</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>OpenCV</exec_depend>
<export>
</export>
</package>
That should work, but there's a problem: find_package() only supports finding one package per call.
You're currently trying to find two packages with it, and not finding the second one, OpenCV:
find_package(catkin REQUIRED COMPONENTS
image_transport
cv_bridge
...
)
find_package(OpenCV REQUIRED)
find_package(<package> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[NO_POLICY_SCOPE])
Related
#include<iostream>
#include <SDL_mixer.h>
#include <SDL.h>
using namespace std;
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_AUDIO);
if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
{
cout << "Error: " << Mix_GetError() << std::endl;
}
Mix_Music* song = Mix_LoadMUS("sample.wav");
Mix_PlayMusic(song, 1);
Mix_FreeMusic(song);
song = nullptr;
Mix_Quit();
SDL_Quit();
return 0;
}
I am trying to play a simple song, that I converted to WAV. It is located within the program's folder. I didn't get any errors/warnings when compling and the libraries seem to be linked correctly. On failure, loadMUS returns NULL (which isn't the case) and PlayMusic returns -1 upon failure (which again isn't the case). Yet, when I run the program nothing is heard. This is my first time working with SDL.
To just play a wave file this sample will work with SDL2:
#include <SDL.h>
#include <SDL_audio.h>
int main() {
SDL_Init(SDL_INIT_AUDIO);
SDL_AudioSpec spec{};
Uint8 *audio_buf{};
Uint32 audio_len{};
SDL_LoadWAV("path_to.wav", &spec, &audio_buf, &audio_len);
SDL_AudioSpec ob_spec{};
auto device = SDL_OpenAudioDevice(NULL, 0, &spec, &ob_spec, SDL_AUDIO_ALLOW_ANY_CHANGE);
SDL_QueueAudio(device, audio_buf, audio_len);
SDL_PauseAudioDevice(device, 0);
SDL_Delay(5000);
SDL_CloseAudioDevice(device);
SDL_FreeWAV(audio_buf);
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
BTW to link easy to SDL2 just use CMake with
cmake_minimum_required(VERSION 3.19)
project(sample_sdl VERSION 1.0)
find_package(SDL2 REQUIRED)
add_executable(${PROJECT_NAME} src/main.cpp)
set_property(TARGET ${PROJECT_NAME} PROPERTY LINKER_LANGUAGE CXX)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
target_link_libraries(${PROJECT_NAME} PRIVATE SDL2::SDL2 SDL2::SDL2main)
I'm trying to link my C++ program with static Boost::program_options and dynamic Boost::log libraries.
Here is my CMakeList.txt file:
project(test)
add_executable(testprog "main.cpp")
add_definitions(-DBOOST_ALL_NO_LIB)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS program_options)
target_link_libraries(testprog PRIVATE Boost::program_options)
set(Boost_USE_STATIC_LIBS OFF)
add_definitions(-DBOOST_LOG_DYN_LINK)
find_package(Boost COMPONENTS log)
target_link_libraries(testprog PRIVATE Boost::log)
and my main.cpp file:
#define BOOST_ALL_NO_LIB
#include <iostream>
#include <string>
#include <boost/program_options.hpp>
#include <boost/log/trivial.hpp>
int main(int argc, char* argv[])
{
namespace po = boost::program_options;
po::options_description desc("allowed arguments");
desc.add_options()("log", po::value<std::string>(), "log level");
po::variables_map options;
po::store(po::command_line_parser(argc, argv).options(desc).run(), options);
po::notify(options);
if (options.count("log")) {
std::cout << "log level: " << options["log"].as<std::string>() << std::endl;
}
BOOST_LOG_TRIVIAL(info) << "test message";
return 0;
}
I'm getting boost_filesystem.dll is missing from your computer error.
If I get rid of set(Boost_USE_STATIC_LIBS OFF) line, I'm getting unresolved external symbols boost::log.... Looks like Boost_USE_STATIC_LIBS can be set only once during the configuration time, but I just cannot find the way to tell cmake to split static/dynamic libraries...
Thanks.
I'm trying to get the marker position in an image, but when I compile the program, during linking, I receive several errors indicating undefined reference to Aruco (Marker.cpp:(.text+0x1643): undefined reference to 'aruco::MarkerDetector::detect(cv::Mat const&, std::vector<aruco::Marker, std::allocator<aruco::Marker> >&, cv::Mat, cv::Mat, float, bool)'), I've looked for solutions regarding linking the library but none of them seem to work. This is my CMakeList.txt:
# cmake needs this line
cmake_minimum_required(VERSION 2.8)
# Define project name
project(Pruebas_alg_new)
# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
find_package(OpenCV REQUIRED)
find_package(aruco)
# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS " config: ${OpenCV_DIR}")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " libraries: ${OpenCV_LIBS}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(Marker Marker.cpp)
target_link_libraries(Marker PRIVATE ${OpenCV_LIBS})
And here is the code I'm trying to compile:
#include <iostream>
#include <stdio.h>
#include <opencv2/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/imgcodecs.hpp>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/calib3d.hpp"
#include "opencv2/xfeatures2d.hpp"
#include "Euler.hpp"
#include <aruco/aruco.h>
#include <aruco/markerdetector.h>
#include <aruco/marker.h>
int main(int argc, char **argv)
{
Mat img_scene = imread("/home/javier/pruebas/MasPruebas/Imagenes/Scene.jpg", IMREAD_GRAYSCALE );
if( /*!img_object.data ||*/ !img_scene.data )
{ std::cout<< " --(!) Error reading images " << std::endl;}
Mat CameraMatrix = (Mat_<double>(3,3) << 374.67,0,320.5,0,374.67,180.5,0,0,1);
aruco::MarkerDetector MDetector;
vector<aruco::Marker> Markers;
//DetectorParameters::create()
MDetector.detect(img_scene,Markers);
std::cout<< Markers.size() << std::endl;
// if at least one marker detected
for (unsigned int i = 0; i<Markers.size(); i++)
{Markers[i].draw(img_scene,cv::Scalar(0,0,255),2);}
cv::imshow("out", img_scene);
cv::waitKey(0);
return 0;
}
I am using ROS Kinetic and trying to write a program that would read two videos and publish them on two different topics. But I think I've made some mistake in linking OpenCV libraries. I am getting the following errors.
CMakeFiles/src.dir/src/src.cpp.o: In function `main':
src.cpp:(.text+0x3fd): undefined reference to `cv_bridge::CvImage::toImageMsg() const'
src.cpp:(.text+0x56d): undefined reference to `cv_bridge::CvImage::toImageMsg() const'
collect2: error: ld returned 1 exit status
MultiCamImages/CMakeFiles/src.dir/build.make:165: recipe for target 'MultiCamImages/src' failed
make[2]: *** [MultiCamImages/src] Error 1
CMakeFiles/Makefile2:1089: recipe for target 'MultiCamImages/CMakeFiles/src.dir/all' failed
make[1]: *** [MultiCamImages/CMakeFiles/src.dir/all] Error 2
Makefile:138: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j4 -l4" failed
This is my source file:
#include <ros/ros.h>
#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>
#include <sensor_msgs/image_encodings.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char** argv){
ros::init(argc, argv, "PublishMultiCamImages");
ros::NodeHandle nh;
image_transport::ImageTransport it(nh);
image_transport::Publisher pub1 = it.advertise("/camera/image_raw1", 1);
image_transport::Publisher pub2 = it.advertise("/camera/image_raw2", 1);
cv::Mat im;
cv::String Path1("/home/akanksha/COSLAM_Dataset/EA-01/grayscale/*.jpg");
cv::String Path2("/home/akanksha/COSLAM_Dataset/EA-02/grayscale/*.jpg");
//time = ros::Time::now();
vector<cv::String> fn1;
vector<cv::String> fn2;
cv::glob(Path1,fn1, true); // recurse
cv::glob(Path2,fn2, true);
ros::Rate r(50);
int l1 = fn1.size();
int l2 = fn2.size();
int count1 = 0, count2 = 0;
bool flag;
while(ros::ok()){
flag = true;
if(count1 < l1){
cv::Mat image1 = cv::imread(fn1[count1]);
sensor_msgs::ImagePtr msg1 = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image1).toImageMsg();
pub1.publish(msg1);
count1++;
flag = false;
}
if(count2 < l2){
cv::Mat image2 = cv::imread(fn2[count2]);
sensor_msgs::ImagePtr msg2 = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image2).toImageMsg();
pub2.publish(msg2);
count2++;
flag = false;
}
if(flag)
break;
r.sleep();
}
ros::shutdown();
return 0;
}
This is my CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(MultiCamImages)
find_package(catkin REQUIRED COMPONENTS
roscpp
image_transport
OpenCV
)
# find_package(OpenCV REQUIRED)
set(OpenCV_LIBS opencv_core opencv_imgproc opencv_calib3d opencv_video opencv_features2d opencv_ml opencv_highgui opencv_objdetect)
add_executable(src src/src.cpp)
target_link_libraries(src ${catkin_LIBRARIES} ${OpenCV_LIBS})
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES MultiCamImages
# CATKIN_DEPENDS roscpp
# DEPENDS system_lib
)
include_directories(
${catkin_INCLUDE_DIRS}
)
And this is my pakage.xml
<?xml version="1.0"?>
<package>
<name>MultiCamImages</name>
<version>0.0.0</version>
<description>The MultiCamImages package</description>
<maintainer email="akanksha#todo.todo">akanksha</maintainer>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<run_depend>roscpp</run_depend>
<build_depend>sensor_msgs</build_depend>
<run_depend>sensor_msgs</run_depend>
<build_depend>cv_bridge</build_depend>
<run_depend>cv_bridge</run_depend>
</package>
If you could point out the problem that would be a great help. Thanks!
It doesn't look like you are linking cv_bridge in the cmake file. Maybe you want this:
find_package(catkin REQUIRED COMPONENTS
cv_bridge
roscpp
image_transport
OpenCV
)
Actually the way Joseph uses OpenCV libraries for linking is not right, since OpenCV does not belong to the standard package of ROS as with cv_bridge. In this case, you need to separately use find_package for OpenCV as with boost like this:
find_package(OpenCV REQUIRED)
# Or you may add specific major portion of OpenCV version, e.g., OpenCV3
find_package(OpenCV 3 REQUIRED)
I tried to compile a simple helloWord C++ program with cmake using the ITK library. However I have some difficulties to link with the ITK library and my program doesn't work.
I put my program in the attachment.
helloWorld programme
CMakeLists.txt :
project(HelloWorld)
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
add_executable(HelloWorld HelloWorld.cxx)
target_link_libraries(HelloWorld ${ITK_LIBRAIRIES})
HelloWorld.cxx :
#include "itkImage.h"
#include <iostream>
int main()
{
typedef itk::Image< unsigned short, 3 > ImageType;
ImageType::Pointer image = ImageType::New();
std::cout <<"ITK Hello World !"<< std::endl;
return 0 ;
}
target_link_libraries(HelloWorld ${ITK_LIBRAIRIES})
should be
target_link_libraries(HelloWorld ${ITK_LIBRARIES})