From 06cf62cc2f12f042d9842b3286aeb7e44c08e606 Mon Sep 17 00:00:00 2001 From: jieshoudaxue <1641395022@qq.com> Date: Tue, 5 Sep 2023 09:54:32 +0800 Subject: [PATCH] [fix] add qr_detector --- qr_detector/CHANGELOG.rst | 8 +++ qr_detector/CMakeLists.txt | 37 ++++++++++ qr_detector/LICENSE | 27 +++++++ qr_detector/README.md | 11 +++ qr_detector/include/qr_detector/detector.h | 37 ++++++++++ .../include/qr_detector/qr_detector_nodelet.h | 29 ++++++++ qr_detector/launch/detector.launch | 24 +++++++ qr_detector/nodelets.xml | 10 +++ qr_detector/package.xml | 24 +++++++ qr_detector/src/detector.cpp | 38 ++++++++++ qr_detector/src/qr_detector_nodelet.cpp | 71 +++++++++++++++++++ 11 files changed, 316 insertions(+) create mode 100644 qr_detector/CHANGELOG.rst create mode 100644 qr_detector/CMakeLists.txt create mode 100644 qr_detector/LICENSE create mode 100644 qr_detector/README.md create mode 100644 qr_detector/include/qr_detector/detector.h create mode 100644 qr_detector/include/qr_detector/qr_detector_nodelet.h create mode 100644 qr_detector/launch/detector.launch create mode 100644 qr_detector/nodelets.xml create mode 100644 qr_detector/package.xml create mode 100644 qr_detector/src/detector.cpp create mode 100644 qr_detector/src/qr_detector_nodelet.cpp diff --git a/qr_detector/CHANGELOG.rst b/qr_detector/CHANGELOG.rst new file mode 100644 index 0000000..3f771e6 --- /dev/null +++ b/qr_detector/CHANGELOG.rst @@ -0,0 +1,8 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package qr_detector +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1.0.0 (2017-05-01) +------------------ +* QR detection wrapper on zbar implemented +* Contributors: Michal Drwiega diff --git a/qr_detector/CMakeLists.txt b/qr_detector/CMakeLists.txt new file mode 100644 index 0000000..e520dec --- /dev/null +++ b/qr_detector/CMakeLists.txt @@ -0,0 +1,37 @@ +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} +) diff --git a/qr_detector/LICENSE b/qr_detector/LICENSE new file mode 100644 index 0000000..206ff2f --- /dev/null +++ b/qr_detector/LICENSE @@ -0,0 +1,27 @@ + * 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. diff --git a/qr_detector/README.md b/qr_detector/README.md new file mode 100644 index 0000000..cf9705e --- /dev/null +++ b/qr_detector/README.md @@ -0,0 +1,11 @@ +## 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. \ No newline at end of file diff --git a/qr_detector/include/qr_detector/detector.h b/qr_detector/include/qr_detector/detector.h new file mode 100644 index 0000000..a44084e --- /dev/null +++ b/qr_detector/include/qr_detector/detector.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include "zbar.h" + +namespace qr_detector { + +struct Tag { + std::string message; + std::vector polygon; +}; + +using Tags = std::vector; + +/** + * 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_; +}; + +} diff --git a/qr_detector/include/qr_detector/qr_detector_nodelet.h b/qr_detector/include/qr_detector/qr_detector_nodelet.h new file mode 100644 index 0000000..0fb37e8 --- /dev/null +++ b/qr_detector/include/qr_detector/qr_detector_nodelet.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include + +#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_; +}; + +} diff --git a/qr_detector/launch/detector.launch b/qr_detector/launch/detector.launch new file mode 100644 index 0000000..775d5de --- /dev/null +++ b/qr_detector/launch/detector.launch @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/qr_detector/nodelets.xml b/qr_detector/nodelets.xml new file mode 100644 index 0000000..c0932d7 --- /dev/null +++ b/qr_detector/nodelets.xml @@ -0,0 +1,10 @@ + + + + + QR detector nodelet. + + + \ No newline at end of file diff --git a/qr_detector/package.xml b/qr_detector/package.xml new file mode 100644 index 0000000..764b08f --- /dev/null +++ b/qr_detector/package.xml @@ -0,0 +1,24 @@ + + qr_detector + 1.0.0 + + QR codes detector based on zbar library (http://zbar.sourceforge.net) + + Michal Drwiega (http://www.mdrwiega.com) + Michal Drwiega + BSD + http://ros.org/wiki/qr_detector + + catkin + + roscpp + nodelet + zbar + sensor_msgs + cv_bridge + image_transport + + + + + \ No newline at end of file diff --git a/qr_detector/src/detector.cpp b/qr_detector/src/detector.cpp new file mode 100644 index 0000000..9a233e5 --- /dev/null +++ b/qr_detector/src/detector.cpp @@ -0,0 +1,38 @@ +#include "qr_detector/detector.h" + +#include + +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; +} + +} diff --git a/qr_detector/src/qr_detector_nodelet.cpp b/qr_detector/src/qr_detector_nodelet.cpp new file mode 100644 index 0000000..97eafd8 --- /dev/null +++ b/qr_detector/src/qr_detector_nodelet.cpp @@ -0,0 +1,71 @@ +#include "qr_detector/qr_detector_nodelet.h" + +#include "pluginlib/class_list_macros.h" +#include +#include +#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("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); + } +} + +}