ROS2+OpenCV综合应用--9. AprilTag标签码识别

1. 简介

Apriltag是一种常用于机器视觉中的编码标志,它具有较高的识别率和可靠性,可用于各种任务,包括增强现实、机器人和相机校准。

2. 启动

2.1 程序启动前的准备

本次apriltag标签码使用的是TAG36H11格式,出厂已配套相关标签码,并贴在积木块上,需要将积木块拿出来放置到摄像头画面下识别。

2.2 程序说明

程序启动后,摄像头捕获到图像,将标签码放入摄像头画面,系统会识别并框出标签码的四个顶点,并显示标签码的ID号。

2.3 程序启动

打开一个终端输入以下指令进入docker,

./docker_ros2.sh

出现以下界面就是进入docker成功

在docker终端输入以下命令启动程序

ros2 run yahboomcar_apriltag apriltag_identify

3. 源码

python 复制代码
#!/usr/bin/env python3
# encoding: utf-8
import cv2 as cv
import time
from dt_apriltags import Detector
from yahboomcar_apriltag.vutils import draw_tags
import logging
import yahboomcar_apriltag.logger_config as logger_config
import rclpy
from rclpy.node import Node
from std_msgs.msg import String, Float32MultiArray
​
class ApriltagIdentify(Node):
    def __init__(self):
        super().__init__('apriltag_identify_node')
        logger_config.setup_logger()
        self.image = None
        self.at_detector = Detector(searchpath=['apriltags'],
                                    families='tag36h11',
                                    nthreads=8,
                                    quad_decimate=2.0,
                                    quad_sigma=0.0,
                                    refine_edges=1,
                                    decode_sharpening=0.25,
                                    debug=0)
        
        # AprilTag positions
        self.publisher_ = self.create_publisher(Float32MultiArray, 'apriltag_positions', 10)
        # AprilTag ID
        self.single_tag_id_publisher_ = self.create_publisher(String, 'single_apriltag_id', 10)
​
    def getApriltagPosMsg(self, image):
        self.image = cv.resize(image, (640, 480))
        msg = Float32MultiArray()
        try:
            tags = self.at_detector.detect(cv.cvtColor(
                self.image, cv.COLOR_BGR2GRAY), False, None, 0.025)
            tags = sorted(tags, key=lambda tag: tag.tag_id)
            if len(tags) > 0:
                for tag in tags:
                    point_x = tag.center[0]
                    point_y = tag.center[1]
                    (a, b) = (round(((point_x - 320) / 4000), 5),
                            round(((480 - point_y) / 3000) * 0.7+0.15, 5))
                    msg.data.extend([tag.tag_id, a, b])
​
                self.image = draw_tags(self.image, tags, corners_color=(
                    0, 0, 255), center_color=(0, 255, 0))
        except Exception as e:
            logging.info('getApriltagPosMsg e = {}'.format(e))
        
        return self.image, msg
​
    def getSingleApriltagID(self, image):
        self.image = cv.resize(image, (640, 480))
        tagId = ""
        try:
            tags = self.at_detector.detect(cv.cvtColor(
                self.image, cv.COLOR_BGR2GRAY), False, None, 0.025)
            tags = sorted(tags, key=lambda tag: tag.tag_id)
            if len(tags) == 1:
                tagId = str(tags[0].tag_id)
                self.image = draw_tags(self.image, tags, corners_color=(
                    0, 0, 255), center_color=(0, 255, 0))
        except Exception as e:
            logging.info('getSingleApriltagID e = {}'.format(e))
        
        return self.image, tagId
​
    def detect_and_publish(self):
        capture = cv.VideoCapture(0)
        capture.set(cv.CAP_PROP_FRAME_WIDTH, 640)
        capture.set(cv.CAP_PROP_FRAME_HEIGHT, 480)
​
        t_start = time.time()
        m_fps = 0
        try:
            while capture.isOpened():
                action = cv.waitKey(10) & 0xFF
                if action == ord('q'):
                    break
                ret, img = capture.read()
                img, data = self.getApriltagPosMsg(img)
                
                # AprilTag positions
                self.publisher_.publish(data)
                
                # AprilTag ID
                _, single_tag_id = self.getSingleApriltagID(img)
                if single_tag_id:
                    single_tag_msg = String()
                    single_tag_msg.data = single_tag_id
                    self.single_tag_id_publisher_.publish(single_tag_msg)
​
                m_fps += 1
                fps = m_fps / (time.time() - t_start)
                if (time.time() - t_start) >= 2000:
                    t_start = time.time()
                    m_fps = fps
                text = "FPS: " + str(int(fps))
                cv.putText(img, text, (20, 30), cv.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 1)
                cv.imshow('img', img)
        except Exception as e:
            logging.error('Exception occurred: {}'.format(e))
        finally:
            capture.release()
            cv.destroyAllWindows()
​
def main(args=None):
    rclpy.init(args=args)
    apriltag_identify = ApriltagIdentify()
    try:
        apriltag_identify.detect_and_publish()
    except KeyboardInterrupt:
        pass
​
if __name__ == '__main__':
    main()
相关推荐
搞科研的小刘选手8 小时前
【国际生态学协会主办】2026年生态环境与人工智能国际学术会议(ICAIEE 2026)
人工智能·生态环境·学术会议·会议推荐
笨鸟先飞,勤能补拙8 小时前
AI 赋能网络安全领域深度剖析
网络·人工智能·windows·安全·web安全·网络安全·github
小鸟你好啊8 小时前
搭建基于 Solon AI 的 Streamable MCP 服务并部署至阿里云百炼
人工智能·阿里云·云计算
Summer-Bright8 小时前
深度 | Agent框架大洗牌:AutoGen退场后的新秩序
人工智能·ai·语言模型·ai软件
ThsPool8 小时前
【遥感学习整理 02】ENVI遥感图像处理基础:从数据读取到遥感信息产品
图像处理·人工智能·学习
非凸科技9 小时前
非凸智能APP
人工智能
土星云SaturnCloud9 小时前
抽水蓄能设备智慧运营:基于土星云边缘计算实现机组全生命周期预测性维护
服务器·人工智能·ai·边缘计算
江畔柳前堤9 小时前
系统的本质——从LTI系统到神经网络
人工智能·深度学习·神经网络·机器学习·计算机视觉·数据挖掘·语音识别
HackTwoHub9 小时前
轻量化AI渗透武器库|ARTEX自主攻防系统、资产梳理、漏洞挖掘、链路分析全流程智能化落地
人工智能·安全·web安全·网络安全·系统安全·网络攻击模型·安全架构
中电金信9 小时前
WAIC 2026媒体聚焦:中电金信的AI工程化思考与实践
人工智能