Last active
July 19, 2020 06:08
-
-
Save anug7/4b35f5a827a0e76b5b74902c96f619bb to your computer and use it in GitHub Desktop.
View cv::Mat in GDB.. Based on https://sourceware.org/legacy-ml/gdb/2013-04/msg00104.html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
OpenCV Mat viewer in GDB | |
""" | |
import gdb | |
import cv2 | |
import numpy as np | |
class PlotterCommand(gdb.Command): | |
""" | |
Plotter command class with gdb command base class | |
""" | |
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]) | |
cmd = "" | |
if len(args) > 1: | |
cmd = args[1] | |
CV_CN_MAX = 512 | |
CV_CN_SHIFT = 3 | |
CV_MAT_CN_MASK = (CV_CN_MAX - 1) << CV_CN_SHIFT | |
flags = v['flags'] | |
# Mat.channels() will work only the method is used in the code | |
# otherwise the function is not generated for the template | |
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 | |
if depth == cv2.CV_8U: | |
dtype = np.uint8 | |
elif depth == cv2.CV_8S: | |
dtype = np.int8 | |
elif depth == cv2.CV_16U: | |
dtype = np.uint16 | |
elif depth == cv2.CV_16S: | |
dtype = np.int16 | |
elif depth == cv2.CV_16S: | |
dtype = np.int16 | |
elif depth == cv2.CV_32F: | |
dtype = np.float32 | |
elif depth == cv2.CV_64F: | |
dtype = np.float64 | |
# conver the v['data'] type to "char*" type | |
char_type = gdb.lookup_type("char") | |
char_pointer_type = char_type.pointer() | |
gbuffer = 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'] | |
cbytes = buf[0] * v['rows'] # buf[0] is the step? Not quite sure. | |
inferior = gdb.selected_inferior() | |
mem = inferior.read_memory(gbuffer, cbytes) | |
img = np.frombuffer(mem, dtype) | |
if channel != 1: | |
img = img.reshape((v['cols'], v['rows'], channel)) | |
else: | |
img = img.reshape((v['rows'], v['cols'])) | |
if cmd == "": | |
cv2.namedWindow('debugger') | |
cv2.imshow('debugger', img) | |
# the below statement is necessory, otherwise, the Window | |
# will hang | |
cv2.waitKey(0) | |
elif cmd == "print": | |
print(img) | |
PlotterCommand() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: inside gdb
source cv_plotter.py
plot img # displays image in opencv Window
plot img print # prints the image. Useful for seeing pixel values