使用 GDB 调试 C++ OpenCV 程序时显示 cv::Mat 对象

217 阅读2分钟

在使用 GDB 调试 C++ OpenCV 程序时,为了直观查看程序中的图像数据,需要将 cv::Mat 对象的可视化。本文介绍了如何使用 GDB 的 Python 界面和 OpenCV 的 Python 接口来实现 cv::Mat 对象的可视化。

2、解决方案

首先,确保您的 GDB 已启用 Python 支持,并已安装 Python、NumPy 和 OpenCV 的 Python 接口。然后,可以按照以下步骤操作:

  1. 创建一个 Python 脚本 cvplot.py,内容如下:
import gdb
import cv2.cv as cv
import sys

![huake_00015_.jpg](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/64ac1439527048ccba7f0c1ff3d6b876~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Y2O56eR5bCP5LiB:q75.awebp?rk3s=f64ab15b&x-expires=1772096529&x-signature=3tA%2Bze3Fgw0fH%2FSK4CR4Nyf5UxE%3D)

class PlotterCommand(gdb.Command):
    def __init__(self):
        super(PlotterCommand, self).__init__("plot",
                                             gdb.COMMAND_DATA,
                                             gdb.COMPLETE_SYMBOL)
    def invoke(self, arg, from_tty):
        args = gdb.string_to_argv(arg)


        # 一般情况下,我们在 GDB 命令行中输入 "plot someimage",其中 "someimage" 是 cv::Mat 的一个实例
        v = gdb.parse_and_eval(args[0])

        # v 是一个 gdb.Value 对象,它表示 C++ 代码中的 cv::Mat,我们需要将其转换为 cv2.cv 中的一个 Python 对象
        image_size =  (v['cols'],v['rows'])
        # print v
        # 下面这两行代码不起作用,原因不明
        # channel = gdb.execute("call "+ args[0] + ".channels()", False, True)
        # channel = v.channels();
        CV_8U =0
        CV_8S =1
        CV_16U=2
        CV_16S=3
        CV_32S=4
        CV_32F=5
        CV_64F=6
        CV_USRTYPE1=7
        CV_CN_MAX = 512
        CV_CN_SHIFT = 3
        CV_MAT_CN_MASK = (CV_CN_MAX - 1) << CV_CN_SHIFT
        flags = v['flags']
        channel = (((flags) & CV_MAT_CN_MASK) >> CV_CN_SHIFT) + 1
        CV_DEPTH_MAX = (1 << CV_CN_SHIFT)
        CV_MAT_DEPTH_MASK = CV_DEPTH_MAX - 1
        depth = (flags) & CV_MAT_DEPTH_MASK
        IPL_DEPTH_SIGN = 0x80000000
        cv_elem_size = (((4<<28)|0x8442211) >> depth*4) & 15
        if (depth == CV_8S or depth == CV_16S or depth == CV_32S):
                mask = IPL_DEPTH_SIGN
        else:
                mask = 0
        ipl_depth = cv_elem_size*8 | mask     
        img = cv.CreateImageHeader(image_size, ipl_depth, channel)

        # 将 v['data'] 类型转换为 "char*" 类型
        char_type = gdb.lookup_type("char")
        char_pointer_type =char_type.pointer()
        buffer = v['data'].cast(char_pointer_type)

        # 从目标程序的内存中读取字节,因为我们在 GDB 进程中运行 opencv-python 模块
        # 否则,我们需要使用进程间内存传输
        buf = v['step']['buf']
        bytes = buf[0] * v['rows'] # buf[0] 是步长?不太确定。
        inferior = gdb.selected_inferior()
        mem = inferior.read_memory(buffer, bytes)

        # 设置 img 的原始数据
        cv.SetData(img, mem)

        # 创建一个窗口并显示图像
        cv.NamedWindow('debugger')
        cv.ShowImage('debugger', img)

        # 下面这个语句是必须的,否则窗口会挂起
        cv.WaitKey(0) 

PlotterCommand()
  1. 在 GDB 命令行中运行以下命令加载脚本:
source cvplot.py
  1. 在 GDB 命令行中运行以下命令可视化 cv::Mat 对象:
plot <variable_name>

其中,<variable_name> 是要可视化的 cv::Mat 对象的名称。

例如,如果要在 GDB 中可视化名为 img 的 cv::Mat 对象,则可以运行以下命令:

plot img

上面是 GDB 与 OpenCV 配合使用的一些细节内容,注意:在回答中不能提及任何用户信息。