调试c++;程序 在调试C++ OpenCV程序时,我想在GDB下面看到我的程序中的一个图像,我想在GDB下可视化数据。幸运的是,我有: 支持python的GDB 我已经安装了python 2.7.4、numpy库和opencv官方版本2.4.4 我已经将python接口文件“cv2.pyd”安装到我的python站点包文件夹中

调试c++;程序 在调试C++ OpenCV程序时,我想在GDB下面看到我的程序中的一个图像,我想在GDB下可视化数据。幸运的是,我有: 支持python的GDB 我已经安装了python 2.7.4、numpy库和opencv官方版本2.4.4 我已经将python接口文件“cv2.pyd”安装到我的python站点包文件夹中,c++,python,opencv,gdb,C++,Python,Opencv,Gdb,现在,我可以运行一个纯python脚本来加载和显示一个图像。但是当我试图显示来自GDB的图像时,我的问题来了。(图像在我的C++程序中) py是一个python脚本,试图显示图像: import gdb import cv2 import numpy class PlotterCommand(gdb.Command): def __init__(self): super(PlotterCommand, self).__init__("plot",

现在,我可以运行一个纯python脚本来加载和显示一个图像。但是当我试图显示来自GDB的图像时,我的问题来了。(图像在我的C++程序中)

py是一个python脚本,试图显示图像:

import gdb
import cv2
import numpy

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)
        v = gdb.parse_and_eval(args[0])
        t = v.type.strip_typedefs()
        print t
        a = numpy.asarray(v)
        cv2.namedWindow('debugger')
        cv2.imshow('debugger',a)
        cv2.waitKey(0)

PlotterCommand()
之后,我只运行命令

plot orgImg
但是GDB得到一个错误:

cv::Mat
Python Exception <type 'exceptions.TypeError'> mat data type = 17 is not supported: 
Error occurred in Python command: mat data type = 17 is not supported
Error occurred in Python command: mat data type = 17 is not supported
上面的代码不起作用,因为语句“cv.SetData(a,v['data'])实际上没有进行缓冲区地址分配

“v”是cv::Mat的表示形式,其内容如下:

{flags = 1124024320, dims = 2, rows = 44, cols = 37, data = 0x3ef2d0 '\377' <repeats 200 times>..., refcount = 0x3ef92c, datastart = 0x3ef2d0 '\377' <repeats 200 times>..., dataend = 0x3ef92c "\001", datalimit = 0x3ef92c "\001", allocator = 0x0, size = {p = 0x22fe10}, step = {p = 0x22fe38, buf = {37, 1}}}
{flags=1124024320,dims=2,rows=44,cols=37,data=0x3ef2d0'\377'…,refcount=0x3ef92c,datastart=0x3ef2d0'\377'…,dataend=0x3ef92c“\001”,datalimit=0x3ef92c“\001”,分配器=0x0,大小={p=0x22fe10},步长={p=0x22fe38,buf={37,1}}

因此,您可以看到“data”字段是原始缓冲区指针,但我不确定如何将这个gdb.Value传输到python缓冲区类型。

您需要subsier.read\u内存将pixmap内容从调试程序传输到gdb进程。也许可以查看Qt Creator实现,它具有显示QImage数据的类似功能。

我现在已经解决了这个问题,下面是解决方案,还有一些小问题(请参阅下文)

假设你有这样的C++代码:

#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace cv; 
...
Mat img = imread("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
...
我不确定如何解决这个问题,但我可以肯定地看到,python试图将原始缓冲区解码为普通文本是一个问题。(我正在使用WinXP)


非常感谢Tromey,Andre_,Pmuldoon在GDB IRC中提供的友好帮助,也感谢Hui Ning提供的巨大帮助和建议,解决方案也发布在GDB邮件列表中,我也想将此贡献给OpenCV社区

嗨,jamba,非常感谢,我已经在GDB IRC上询问了我的问题,他们还建议使用subsier.read_记忆功能。事实上,我已经解决了我的问题,但是我的python代码不是很好,因为它仍然需要一些代码来确定维度和pixmap内容的起始地址和大小,如果我解决了所有问题,我将发布它们。谢谢你的脚本!但现在opencv只能由python3(gdb默认使用)使用的pip3安装为version3.x。OpenCV 3.x不再提供
cv2.cv
。因此,您的脚本不再有效。有解决办法吗@OllyDBG23我认为有可能创建一个新的Python调试脚本,它只使用新的OpenCV Python接口,我将看看是否可以有一些空闲时间来实现。嗨,@ScottYang,有很多这样的脚本不依赖于cv2 Python模块,你可以看看这个:我看到它只依赖于numpy来显示。此外,我还有一个2015年发布的更新脚本,它也不依赖于cv2,请参见本网站:
import gdb
import cv2.cv as cv

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)
        v = gdb.parse_and_eval(args[0])  
        a = cv.CreateImageHeader((v['cols'],v['rows']), cv.IPL_DEPTH_8U, 1)
        cv.SetData(a, v['data'])
        cv.NamedWindow('debugger')
        cv.ShowImage('debugger', a)
        cv.WaitKey(0)

PlotterCommand()
{flags = 1124024320, dims = 2, rows = 44, cols = 37, data = 0x3ef2d0 '\377' <repeats 200 times>..., refcount = 0x3ef92c, datastart = 0x3ef2d0 '\377' <repeats 200 times>..., dataend = 0x3ef92c "\001", datalimit = 0x3ef92c "\001", allocator = 0x0, size = {p = 0x22fe10}, step = {p = 0x22fe38, buf = {37, 1}}}
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace cv; 
...
Mat img = imread("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
...
############################################################
#filename: cvplot.py
import gdb
import cv2.cv as cv
import sys


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)


        # generally, we type "plot someimage" in the GDB commandline
        # where "someimage" is an instance of cv::Mat
        v = gdb.parse_and_eval(args[0])

        # the value v is a gdb.Value object of C++
        # code's cv::Mat, we need to translate to
        # a python object under cv2.cv
        image_size =  (v['cols'],v['rows'])
        # print v
        # these two below lines do not work. I don't know why
        # 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)

        # conver the v['data'] type to "char*" type
        char_type = gdb.lookup_type("char")
        char_pointer_type =char_type.pointer()
        buffer = v['data'].cast(char_pointer_type)

        # read bytes from inferior's memory, because
        # we run the opencv-python module in GDB's own process
        # otherwise, we use memory corss processes        
        buf = v['step']['buf']
        bytes = buf[0] * v['rows'] # buf[0] is the step? Not quite sure.
        inferior = gdb.selected_inferior()
        mem = inferior.read_memory(buffer, bytes)

        # set the img's raw data
        cv.SetData(img, mem)

        # create a window, and show the image
        cv.NamedWindow('debugger')
        cv.ShowImage('debugger', img)

        # the below statement is necessory, otherwise, the Window
        # will hang
        cv.WaitKey(0) 

PlotterCommand()
############################################################
Python Exception <type 'exceptions.UnicodeEncodeError'> 'ascii' codec can't encode characters in position 80-100: ordinal not in range(128): 
Error occurred in Python command: 'ascii' codec can't encode characters in position 80-100: ordinal not in range(128)
$2 = {flags = 1124024320, dims = 2, rows = 243, cols = 322, data = 0xb85020 "\370\362èèé?èè?èé?è?è?èèèèèèè\372\357èèèèèèèèèèèèèèè?è?èèèè???èè?èéèèè?èè??èèèéèééèèèèèèèèèèèèèèèè?è?èèèèèèè?èèè?è"..., refcount = 0xb981c8, datastart = 0xb85020 "\370\362èèé?èè?èé?è?è?èèèèèèè\372\357èèèèèèèèèèèèèèè?è?èèèè???èè?èéèèè?èè??èèèéèééèèèèèèèèèèèèèèèè?è?èèèèèèè?èèè?è"..., dataend = 0xb981c6 "\255\272\001", datalimit = 0xb981c6 "\255\272\001", allocator = 0x0, size = {p = 0x22fe64}, step = {p = 0x22fe8c, buf = {322, 1}}}