当调试c ++程序时,GDB cv :: Mat python对象问题 [英] GDB cv::Mat python object issue when debugging a c++ program

查看:970
本文介绍了当调试c ++程序时,GDB cv :: Mat python对象问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

会调试一个c ++ OpenCV程序,我想在我的程序在GDB下看到一个图像,我的意思是我想要可视化GDB下的数据。幸运的是我有:1,GDB与python支持; 2,我已经安装了python 2.7.4,numpy库和opencv官方版本2.4.4; 3,我已经安装了python接口文件cv2.pyd到我的python的网站包文件夹。

will debugging a c++ OpenCV program, I'd like to see a image in my program under GDB, I mean I would like to visualize the data under GDB. Luckily I have: 1, GDB with python support; 2, I have installed python 2.7.4, numpy library, and opencv official release 2.4.4; 3, I have installed the python interface file "cv2.pyd" to my python's site-packages folder.

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

Now, I can run a pure python script which load and show an image. But my issue comes when I try to show an image from GDB. (The image is in my C++ program)

#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace cv; 
...
Mat orgImg = imread("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);

然后我设置一个断点,然后GDB命中断点,我在GDB的命令中运行这样的命令行

Then I set a breakpoint after that, then GDB hit the breakpoint, I run such command in GDB's command line

source test.py

test.py是一个试图显示图片的python脚本:

The test.py is a python script which try to show an image:

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会收到一个错误:

But GDB get an error:

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

你看,GDB下的python对象是cv :: Mat,但是不能转换为正确的python对象显示。任何人都可以帮助我?感谢。

You see, the python object under GDB is "cv::Mat", but it can not to converted to a correct python object to show. Anyone can help me? Thanks.

编辑:
我尝试创建一个更简单的脚本,使用cv(不是cv2),但它仍然不工作:

I try to create a more simple script which use cv (not cv2), but it still not work:

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()

上面的代码不能工作,因为语句cv.SetData(a,v ['data'])不会真正做缓冲区地址分配。

The above code does not work as the statement "cv.SetData(a, v['data'])" does not really do an buffer address assignment.

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

The "v" is a representation of cv::Mat, which has the contents:

{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}}}

所以,你看到data字段是原始缓冲区指针, 'm不知道如何将这个gdb.Value转换为python缓冲区类型。

So, you see the "data" field is the raw buffer pointer, but I'm not sure how to transfer this gdb.Value to a python buffer type.

推荐答案

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

Suppose you have such C++ code:

#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace cv; 
...
Mat img = imread("1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
...

在GDB中调试这些代码时,在内存数据img看起来像。感谢GDB和OpenCV,他们都有Python接口,所以这里是python漂亮脚本(我发布了GPLv3下的脚本代码)

When debugging those code under GDB, I would like to see how the in memory data "img" looks like. Thanks to GDB and OpenCV, both of them have Python interface, so here is the python pretty script (I released the script code under GPLv3)

在这之前,你需要
1,启用python的GDB
2,OpenCV python接口(在Windows下,它是一个文件cv2.pyd)
3,安装python,numpy

Before that, you need 1, GDB with python enabled 2, OpenCV python interface (under Windows, it is one file cv2.pyd) 3, install python, numpy

############################################################
#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()
############################################################

上面的脚本添加了一个新的GDB命令plot data cv :: Mat。
现在,你可以简单地输入:源cvplot.py装载这个脚本GDB,然后键入:暗算img可以显示CV ::垫在OpenCV中的窗口,让GDB继续,只需关闭调试器窗口。

The script above add a new GDB command "plot" to show the in memory data cv::Mat. Now, you can simply type: "source cvplot.py" to load this script to GDB, then type: "plot img" to show the cv::Mat in OpenCV's Window, to let GDB continue, just close the debugger window.

BTW:我发现一个问题,如果我取消注释#打印v在脚本源,然后这个脚本会抱怨这样的消息, p>

BTW: I found one issue, if I uncomment "# print v" in the script source, then this script will complain such message and abort:

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)

但是如果我直接在GDB的命令行中运行命令print img ,它表明:

But if I run the command "print img" directly in the GDB's command line, it shows:

$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}}}

确定如何解决这个,但肯定我可以看到这是一些问题,python试图解码原始缓冲区到正常的文本。 (我用的WinXP)

I'm not sure how to fix this, but surely I can see it was some issue that python try to decode the raw buffer to normal text. (I'm using WinXP)

非常感谢Tromey,Andre_,Pmuldoon他们在GDB IRC热心帮助,也感谢许宁的大力帮助和建议,解决方案还发布在GDB中的maillist 发布在GDB maillist ,我也想可视化作出贡献这OpenCV的社区内存OpenCV图像或来自GDB漂亮打印机的矩阵

Many thanks to Tromey, Andre_, Pmuldoon for their kind help in GDB IRC, also thanks to Hui Ning for great help and suggestion, the solution also posted in GDB maillist Post in GDB maillist, also I would like to contribute this to OpenCV communityVisualize in memory OpenCV image or matrix from GDB pretty printers

这篇关于当调试c ++程序时,GDB cv :: Mat python对象问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆