Merge pull request #11 from Jieshoudaxue/dev

[feat] add qr_detector in robot_vison
This commit is contained in:
界首大学
2023-09-07 10:07:46 +08:00
committed by GitHub
16 changed files with 169 additions and 293 deletions
-8
View File
@@ -1,8 +0,0 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package qr_detector
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1.0.0 (2017-05-01)
------------------
* QR detection wrapper on zbar implemented
* Contributors: Michal Drwiega
-37
View File
@@ -1,37 +0,0 @@
cmake_minimum_required(VERSION 2.8.11)
project(qr_detector)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}")
find_package(catkin REQUIRED COMPONENTS
roscpp nodelet sensor_msgs cv_bridge image_transport)
catkin_package(
INCLUDE_DIRS include
LIBRARIES qr_detector_nodelet
CATKIN_DEPENDS roscpp nodelet sensor_msgs cv_bridge image_transport
)
find_library(ZBAR_LIBRARIES NAMES zbar)
include_directories(include ${catkin_INCLUDE_DIRS})
add_library(qr_detector_nodelet src/qr_detector_nodelet.cpp src/detector.cpp)
target_link_libraries(qr_detector_nodelet zbar ${catkin_LIBRARIES})
install(TARGETS qr_detector_nodelet
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION})
install(DIRECTORY launch
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
install(FILES nodelets.xml
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)
-27
View File
@@ -1,27 +0,0 @@
* Software License Agreement (BSD License)
*
* Copyright (c) 2017-, Michal Drwiega (drwiega.michal@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-11
View File
@@ -1,11 +0,0 @@
## qr_detector
The QR codes detector based on zbar library (http://zbar.sourceforge.net), dedicated to ROS systems.
Installation of zbar library on Ubuntu
`sudo apt install libzbar-dev`
Subscribes:
- **/image** (sensor_msgs/Image) - the topic with RGB images which contains QR codes.
Publishes:
- **/qr_codes** (std_msgs/String) - message from each detected QR code is published as a string.
@@ -1,37 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include "zbar.h"
namespace qr_detector {
struct Tag {
std::string message;
std::vector<cv::Point> polygon;
};
using Tags = std::vector<Tag>;
/**
* Main QR codes detector class
*/
class Detector {
public:
Detector();
~Detector() = default;
/**
* Detects tags in image.
*
* @param[in] image - image with qr tags
* @param[in] timeout - max time for tags detection in ms
*/
Tags detect(const cv::Mat& image, size_t timeout = 100);
protected:
zbar::ImageScanner scanner_;
};
}
@@ -1,29 +0,0 @@
#pragma once
#include <ros/ros.h>
#include <nodelet/nodelet.h>
#include <image_transport/image_transport.h>
#include "qr_detector/detector.h"
namespace qr_detector {
class QrDetectorNodelet : public nodelet::Nodelet {
public:
QrDetectorNodelet();
virtual ~QrDetectorNodelet();
private:
void onInit() override;
void connectCallback();
void disconnectCallback();
void imageCallback(const sensor_msgs::ImageConstPtr& image);
ros::NodeHandle nh_;
image_transport::ImageTransport it_;
image_transport::Subscriber img_subscriber_;
ros::Publisher tags_publisher_;
Detector detector_;
};
}
-24
View File
@@ -1,24 +0,0 @@
<package format="2">
<name>qr_detector</name>
<version>1.0.0</version>
<description>
QR codes detector based on zbar library (http://zbar.sourceforge.net)
</description>
<author email="drwiega.michal@gmail.com">Michal Drwiega (http://www.mdrwiega.com)</author>
<maintainer email="drwiega.michal@gmail.com">Michal Drwiega</maintainer>
<license>BSD</license>
<url type="website">http://ros.org/wiki/qr_detector</url>
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>nodelet</depend>
<depend>zbar</depend>
<depend>sensor_msgs</depend>
<depend>cv_bridge</depend>
<depend>image_transport</depend>
<export>
<nodelet plugin="${prefix}/nodelets.xml"/>
</export>
</package>
-38
View File
@@ -1,38 +0,0 @@
#include "qr_detector/detector.h"
#include <cv_bridge/cv_bridge.h>
namespace qr_detector {
Detector::Detector() : scanner_()
{
scanner_.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
}
Tags Detector::detect(const cv::Mat& image, size_t timeout)
{
cv::Mat grayImg;
cv::cvtColor(image, grayImg, CV_BGR2GRAY);
const auto width = image.cols;
const auto height = image.rows;
zbar::Image img(width, height, "Y800", grayImg.data, width * height);
scanner_.scan(img);
Tags tags;
for (auto s = img.symbol_begin(); s != img.symbol_end(); ++s)
{
Tag tag;
tag.message = s->get_data();
for(int i = 0; i < s->get_location_size(); i++) {
tag.polygon.push_back(cv::Point(s->get_location_x(i), s->get_location_y(i)));
}
tags.push_back(tag);
}
return tags;
}
}
-71
View File
@@ -1,71 +0,0 @@
#include "qr_detector/qr_detector_nodelet.h"
#include "pluginlib/class_list_macros.h"
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include "std_msgs/String.h"
PLUGINLIB_EXPORT_CLASS(qr_detector::QrDetectorNodelet, nodelet::Nodelet);
namespace qr_detector {
QrDetectorNodelet::QrDetectorNodelet()
: it_(nh_)
{ }
QrDetectorNodelet::~QrDetectorNodelet()
{
img_subscriber_.shutdown();
}
void QrDetectorNodelet::onInit()
{
nh_ = getNodeHandle();
tags_publisher_ = nh_.advertise<std_msgs::String>("qr_codes", 10,
std::bind(&QrDetectorNodelet::connectCallback, this),
std::bind(&QrDetectorNodelet::disconnectCallback, this));
NODELET_INFO_STREAM("Initializing nodelet... [" << nh_.getNamespace() << "]");
}
void QrDetectorNodelet::connectCallback()
{
if (!img_subscriber_ && tags_publisher_.getNumSubscribers() > 0)
{
NODELET_INFO("Connecting to image topic.");
img_subscriber_ = it_.subscribe("image", 1, &QrDetectorNodelet::imageCallback, this);
}
}
void QrDetectorNodelet::disconnectCallback()
{
if (tags_publisher_.getNumSubscribers() == 0)
{
NODELET_INFO("Unsubscribing from image topic.");
img_subscriber_.shutdown();
}
}
void QrDetectorNodelet::imageCallback(const sensor_msgs::ImageConstPtr &image)
{
cv_bridge::CvImageConstPtr cv_image;
try {
cv_image = cv_bridge::toCvShare(image, sensor_msgs::image_encodings::BGR8);
}
catch (cv_bridge::Exception& e) {
ROS_ERROR("cv_bridge exception: %s", e.what());
return;
}
auto tags = detector_.detect(cv_image->image, 10);
for (auto& tag : tags)
{
std_msgs::String msg;
msg.data = tag.message;
tags_publisher_.publish(msg);
}
}
}
+13 -5
View File
@@ -3,6 +3,7 @@ project(robot_vision)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}")
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
@@ -11,6 +12,9 @@ find_package(catkin REQUIRED COMPONENTS
cv_bridge
image_transport
roscpp
nodelet
cv_bridge
image_transport
rospy
sensor_msgs
std_msgs
@@ -108,10 +112,9 @@ generate_messages(
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES robot_vision
# CATKIN_DEPENDS cv_bridge image_transport roscpp rospy sensor_msgs std_msgs
# DEPENDS system_lib
INCLUDE_DIRS include
LIBRARIES qr_detector_nodelet
CATKIN_DEPENDS roscpp nodelet sensor_msgs cv_bridge image_transport
)
###########
@@ -120,8 +123,10 @@ catkin_package(
## Specify additional locations of header files
## Your package locations should be listed before other locations
find_library(ZBAR_LIBRARIES NAMES zbar)
include_directories(
# include
include
${catkin_INCLUDE_DIRS}
)
@@ -129,6 +134,8 @@ include_directories(
# add_library(${PROJECT_NAME}
# src/${PROJECT_NAME}/robot_vision.cpp
# )
add_library(qr_detector_nodelet src/qr_detector_nodelet.cpp)
## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
@@ -154,6 +161,7 @@ include_directories(
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
target_link_libraries(qr_detector_nodelet zbar ${catkin_LIBRARIES})
#############
## Install ##
Binary file not shown.
@@ -0,0 +1,81 @@
#pragma once
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include <ros/ros.h>
#include <nodelet/nodelet.h>
#include <cv_bridge/cv_bridge.h>
#include <image_transport/image_transport.h>
#include <zbar.h>
namespace qr_detector {
struct QrTag {
std::string qr_msg;
std::vector<cv::Point> square_apex_vector;
};
using QrTags = std::vector<QrTag>;
class QrDetector {
public:
QrDetector() {
scanner_.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);
}
QrTags detect(const cv::Mat& image) {
cv::Mat gray_img;
cv::cvtColor(image, gray_img, CV_BGR2GRAY);
const uint64_t width = image.cols;
const uint64_t height = image.rows;
zbar::Image img(width, height, "Y800", gray_img.data, width*height);
scanner_.scan(img);
QrTags tags;
for (auto s = img.symbol_begin(); s != img.symbol_end(); ++s) {
QrTag tag;
tag.qr_msg = s->get_data();
for (int i = 0; i < s->get_location_size(); i++) {
tag.square_apex_vector.push_back(cv::Point(s->get_location_x(i), s->get_location_y(i)));
}
tags.push_back(tag);
}
return tags;
}
private:
zbar::ImageScanner scanner_;
};
class QrDetectorNodelet : public nodelet::Nodelet {
public:
QrDetectorNodelet();
virtual ~QrDetectorNodelet();
void onInit() override;
private:
void DownstreamConnectCb();
void DownstreamDisconnectCb();
void ImageCb(const sensor_msgs::ImageConstPtr& image);
private:
ros::NodeHandle nh_;
image_transport::ImageTransport it_;
image_transport::Subscriber img_sub_;
ros::Publisher qr_pub_;
QrDetector detector_;
};
}
@@ -11,7 +11,8 @@
<node pkg="nodelet"
type="nodelet"
name="qr_detector"
args="standalone qr_detector/qr_detector_nodelet">
output="screen"
args="standalone robot_vision/qr_detector_nodelet">
<remap from="image" to="usb_cam/image_raw"/>
</node>
@@ -1,6 +1,6 @@
<library path="lib/libqr_detector_nodelet">
<class name="qr_detector/qr_detector_nodelet"
<class name="robot_vision/qr_detector_nodelet"
type="qr_detector::QrDetectorNodelet"
base_class_type="nodelet::Nodelet">
<description>
+10 -4
View File
@@ -52,26 +52,32 @@
<build_depend>cv_bridge</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>nodelet</build_depend>
<build_depend>zbar</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>rospy</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>cv_bridge</build_export_depend>
<build_export_depend>image_transport</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>nodelet</build_export_depend>
<build_export_depend>zbar</build_export_depend>
<build_export_depend>image_transport</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>sensor_msgs</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>cv_bridge</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>nodelet</exec_depend>
<exec_depend>zbar</exec_depend>
<exec_depend>image_transport</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>sensor_msgs</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 -->
<nodelet plugin="${prefix}/nodelets.xml"/>
</export>
</package>
+62
View File
@@ -0,0 +1,62 @@
#include "qr_detector/qr_detector_nodelet.h"
#include <pluginlib/class_list_macros.h>
#include <cv_bridge/cv_bridge.h>
#include <sensor_msgs/image_encodings.h>
#include <std_msgs/String.h>
PLUGINLIB_EXPORT_CLASS(qr_detector::QrDetectorNodelet, nodelet::Nodelet);
namespace qr_detector {
QrDetectorNodelet::QrDetectorNodelet() : it_(nh_) {
ROS_INFO("QrDetectorNodelet Constructor");
}
QrDetectorNodelet::~QrDetectorNodelet() {
img_sub_.shutdown();
ROS_INFO("QrDetectorNodelet Destructor");
}
void QrDetectorNodelet::onInit() {
nh_ = getNodeHandle();
qr_pub_ = nh_.advertise<std_msgs::String>("/qr_codes", 10,
std::bind(&QrDetectorNodelet::DownstreamConnectCb, this),
std::bind(&QrDetectorNodelet::DownstreamDisconnectCb, this));
ROS_INFO("init qr detector nodelet, nodehand name %s", nh_.getNamespace().c_str());
}
void QrDetectorNodelet::DownstreamConnectCb() {
if (!img_sub_ && qr_pub_.getNumSubscribers() > 0) {
img_sub_ = it_.subscribe("image", 1, &QrDetectorNodelet::ImageCb, this);
ROS_INFO("subscribe image topic from usb_cam");
}
}
void QrDetectorNodelet::DownstreamDisconnectCb() {
if (qr_pub_.getNumSubscribers() == 0) {
img_sub_.shutdown();
ROS_INFO("unsubscibe image topic");
}
}
void QrDetectorNodelet::ImageCb(const sensor_msgs::ImageConstPtr& image) {
cv_bridge::CvImageConstPtr cv_image;
try {
cv_image = cv_bridge::toCvShare(image, sensor_msgs::image_encodings::BGR8);
} catch (cv_bridge::Exception& e) {
ROS_ERROR("cv_bridge exception %s", e.what());
return;
}
QrTags qr_tags = detector_.detect(cv_image->image);
for (auto& qr_tag : qr_tags) {
std_msgs::String msg;
msg.data = qr_tag.qr_msg;
qr_pub_.publish(msg);
}
}
}