opencv 관련 패키지 설치
$ sudo apt-get install ros-melodic-opencv*
$ sudo apt-get install ros-melodic-usb-cam
$ sudo apt-get install ros-melodic-cv-bridge
$ sudo apt-get install ros-melodic-cv-camera
test_publisher.cpp
#include "cv_bridge/cv_bridge.h"
#include "opencv2/opencv.hpp"
#include "image_transport/image_transport.h"
#include "iostream"
#include "vector"
#include "opencv2/highgui/highgui.hpp"
#include "ros/ros.h" // 로스 관련 헤더 포함
#include "std_msgs/UInt8MultiArray.h"
using namespace std;
#define pb push_back
int main(int argc, char **argv){
//int argc = 전달되는 데이터 개수
//char **argv = 실제 전달되는 데이터, 첫 번째 문자열은 프로그램의 실행 경로
ros::init(argc, argv, "image_publish");
//ros 초기화하면서 노드 이름 정함
ros::NodeHandle n;
// 노드를 제어할 핸들 생성
ros::Publisher imPublisher = n.advertise<std_msgs::UInt8MultiArray>("camera_image", 3);
cv::VideoCapture cap(0); // 0번 캠 연결
cv::Mat frame;
while(ros::ok()){
cap >> frame; // frame에 현재 이미지 저장
if(!frame.empty()){
cv::imshow("frame", frame); // 원본 이미지 띄우기
/* 원본 영상 압축
압축하면 영상을 publish하는데 걸리는 시간이 줄어든다고 함.*/
vector<uchar> encode;
vector<int> encode_param;
/* 압축률 */
encode_param.pb(CV_IMWRITE_JPEG_QUALITY);
encode_param.pb(20);
// frame: 이미지, encode: 압축한 이미지를 담을 벡터, endcode_param: 압축률
cv::imencode(".jpg", frame, encode, encode_param);
cv::Mat decode = cv::imdecode(encode,1); // 압축 이미지 디코딩
cv::imshow("decode", decode); // 압축된 이미지 띄우기
/* cv::imencode()로 압축된 이미지는 unsigned char 타입의 array */
std_msgs::UInt8MultiArray msgArray;
msgArray.data.clear();
msgArray.data.resize(encode.size());
std::copy(encode.begin(), encode.end(), msgArray.data.begin());
imPublisher.publish(msgArray); // 이미지 publish
cv::waitKey(1);
}
ros::spinOnce();
}
return 0;
}
test_subscriber.cpp
#include "ros/ros.h"
#include "opencv2/opencv.hpp"
#include "image_transport/image_transport.h"
#include "opencv2/highgui/highgui.hpp"
#include "vector"
#include "cv_bridge/cv_bridge.h"
#include "std_msgs/UInt8MultiArray"
void callback(const std_msgs::UInt8MultiArray::ConstPtr& msg){
// 메시지를 수신했을 때 호출될 콜백 함수
try{
cv::Mat frame = cv::imdecode(msg->data,1);
cv::imshow("subscribe_view", frame);
cv::waitKey(1);
}
catch(cv_bridge::Exception& e){
ROS_ERROR("cannot decode image");
}
}
int main(int argc, char **argv){
ros::init(argc, argv, "image_subscribe");
cv::namedWindow("subscribe_view");
ros::NodeHandle n;
ros::Subscriber imSubscriber = n.subscribe("camera_image",3,callback);
ros::spin(); // 계속 대기하면서 메시지 받는 즉시 콜백 요청하고 다음 메시지 기다림
cv::destroyWindow("subscribe_view");
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(test) #패키지 이름
find_package(catkin REQUIRED COMPONENTS
**cv_bridge
image_transport
sensor_msgs
std_msgs**
roscpp #패키지 생성할 때 정해준 의존 패키지
)
**find_package(OpenCV REQUIRED)**
**catkin_package(
INCLUDE_DIRS include
LIBRARIES opencv
CATKIN_DEPENDS roscpp cv_bridge image_transport sensor_msgs std_msgs
# DEPENDS system_lib
)**
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
${catkin_INCLUDE_DIRS}
**${OpenCV_INCLUDE_DIRS}**
)
add_executable(image_publisher src/test_publisher.cpp)
add_executable(image_listener src/test_subscriber.cpp)
target_link_libraries(image_publisher
${catkin_LIBRARIES}
**${OpenCV_LIBRARIES}**
)
target_link_libraries(image_listener
${catkin_LIBRARIES}
**${OpenCV_LIBRARIES}**
)
package.xml
<?xml version="1.0"?>
<package format="2">
<name>test</name>
<version>0.0.0</version>
<description>The test package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
<maintainer email="[email protected]">minkyeong</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website"><http://wiki.ros.org/test></url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="[email protected]">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<!-- <build_export_depend>message_generation</build_export_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<!-- <exec_depend>message_runtime</exec_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
**<build_depend>cv_bridge</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>std_msgs</build_depend>**
<build_export_depend>roscpp</build_export_depend>
**<build_export_depend>cv_bridge</build_export_depend>
<build_export_depend>sensor_msgs</build_export_depend>
<build_export_depend>image_transport</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>**
<exec_depend>roscpp</exec_depend>
**<exec_depend>cv_bridge</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>std_msgs</exec_depend>**
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
실행하기
~/catkin_ws/src/test$ catkin build
~/catkin_ws/src/test$ rosrun test image_publisher
~/catkin_ws/src/test$ rosrun test image_listener