You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决ROS与OpenCV生成棋盘图时的内存不足错误?

解决ROS+OpenCV生成棋盘图时的内存不足与崩溃问题

嘿,我看了你用ROS和OpenCV生成棋盘图时遇到的内存不足问题,结合你的代码和错误信息,找到了几个关键问题,咱们一步步来解决:

1. 最致命的问题:空指针非法访问

你代码里声明了cv_bridge::CvImagePtr frame;但完全没给它分配内存,直接就去调用frame->image,这会直接触发非法内存访问,也就是你看到的内存错误。CvImagePtr是个智能指针,得先给它绑定一个实际的cv_bridge::CvImage对象才行。

2. 命令行参数处理太粗糙

你直接把argv[1]这类字符串转成int,不仅不安全,还没检查参数够不够——要是用户启动节点时没传够3个参数,程序直接就崩了。另外,argv里存的是字符串,得用atoi或者stoi来转成整数类型。

3. 棋盘绘制逻辑全错了

  • Rect(i,j)这写法不对,OpenCV的Rect需要四个参数:x坐标、y坐标、宽度、高度,你只传俩,会导致Rect的宽高是随机垃圾值,直接访问超出图像范围的内存,这也是内存报错的原因之一。
  • 你在每个像素都切换颜色,最后画出来的根本不是棋盘格,而是全灰的图,逻辑完全错了。棋盘格应该按固定大小的格子来交替颜色。
  • cv::Mat img(x,y,CV_8UC3,...)这里搞反了尺寸顺序,OpenCV的Mat构造是行数(高度)在前,列数(宽度)在后,你把x和y放反的话,图像尺寸会完全不符合预期。

修复后的完整代码

下面是修正后的代码,我加了详细注释,你可以直接用:

#include "ros/ros.h"
#include <opencv2/highgui/highgui.hpp>
#include <image_transport/image_transport.h>
#include <sensor_msgs/image_encodings.h>
#include <cv_bridge/cv_bridge.h>

using namespace cv;

int main(int argc , char **argv){
    // 先检查命令行参数够不够,不够直接提示用法
    if(argc != 4){
        ROS_ERROR("启动命令格式不对!应该是: %s <图像宽度> <图像高度> <格子大小>", argv[0]);
        return 1;
    }

    ros::init(argc , argv ,"cb_publisher");
    ros::NodeHandle n("~");
    image_transport::ImageTransport it(n);
    // 提前初始化发布者
    image_transport::Publisher pub_image_raw = it.advertise("image" , 1);

    // 安全转换命令行参数为整数
    int img_width = atoi(argv[1]);
    int img_height = atoi(argv[2]);
    int grid_size = atoi(argv[3]);

    // 检查参数是不是合法的正整数
    if(img_width <=0 || img_height <=0 || grid_size <=0){
        ROS_ERROR("所有参数都得是正整数啊!");
        return 1;
    }

    // 创建空白图像,注意尺寸顺序是高度、宽度
    cv::Mat img(img_height, img_width, CV_8UC3, cv::Scalar(0,0,0));
    bool is_white = false;

    // 按格子大小绘制棋盘格
    for(int y=0; y<img_height; y+=grid_size){
        // 每一行开始时切换起始颜色,让相邻行的格子错开
        is_white = !is_white;
        for(int x=0; x<img_width; x+=grid_size){
            // 定义当前格子的ROI区域
            cv::Rect roi(x, y, grid_size, grid_size);
            // 给ROI区域设置颜色,白/黑交替
            img(roi).setTo(is_white ? cv::Scalar(255,255,255) : cv::Scalar(0,0,0));
            // 切换颜色,下一个格子用相反颜色
            is_white = !is_white;
        }
    }

    // 初始化cv_bridge的智能指针,终于不用空指针啦
    cv_bridge::CvImagePtr frame = cv_bridge::CvImagePtr(new cv_bridge::CvImage());
    frame->header.frame_id = "chessboard"; // 设置坐标系ID,符合ROS规范
    frame->encoding = sensor_msgs::image_encodings::BGR8; // 图像编码,OpenCV默认是BGR
    frame->image = img; // 把生成的棋盘图赋值给它

    ros::Rate loop_rate(10);
    while(ros::ok()){
        frame->header.stamp = ros::Time::now(); // 每次发布都更新时间戳
        pub_image_raw.publish(frame->toImageMsg());
        ros::spinOnce();
        loop_rate.sleep();
    }
    return 0;
}

修复的关键点说明

  • 加了参数校验:不管是参数数量还是参数值的合法性都做了检查,避免用户误操作导致崩溃。
  • 正确初始化了CvImagePtr:通过new创建了实际的CvImage对象,彻底解决空指针问题。
  • 重写了棋盘绘制逻辑:按固定大小的格子逐块绘制,相邻格子和行交替颜色,生成标准棋盘格。
  • 修正了图像尺寸顺序:符合OpenCV的Mat构造规则,图像尺寸不再混乱。
  • 符合ROS规范:给消息加了坐标系ID和时间戳,这是ROS节点的良好实践。

内容的提问来源于stack exchange,提问作者ShivamPR21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:02:24