From a50dec88d5e39a24438f9215a2fa4ee4cc6ae3ab Mon Sep 17 00:00:00 2001 From: rogday Date: Tue, 17 Aug 2021 18:23:27 +0300 Subject: [PATCH] Merge pull request #20547 from rogday:gdb_pretty_printer * add gdb rpetty printer for cv::Mat * address review comments --- .../linux_gcc_cmake/linux_gcc_cmake.markdown | 2 +- .../images/example.png | Bin 0 -> 35727 bytes .../linux_gdb_pretty_printer.markdown | 38 ++++ .../linux_install/linux_install.markdown | 2 +- .../table_of_content_introduction.markdown | 1 + samples/gdb/gdbinit | 23 ++ samples/gdb/mat_pretty_printer.py | 212 ++++++++++++++++++ 7 files changed, 276 insertions(+), 2 deletions(-) create mode 100644 doc/tutorials/introduction/linux_gdb_pretty_printer/images/example.png create mode 100644 doc/tutorials/introduction/linux_gdb_pretty_printer/linux_gdb_pretty_printer.markdown create mode 100644 samples/gdb/gdbinit create mode 100644 samples/gdb/mat_pretty_printer.py diff --git a/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown b/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown index eb59fea209..ee3f1eb7f9 100644 --- a/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown +++ b/doc/tutorials/introduction/linux_gcc_cmake/linux_gcc_cmake.markdown @@ -1,7 +1,7 @@ Using OpenCV with gcc and CMake {#tutorial_linux_gcc_cmake} =============================== -@prev_tutorial{tutorial_linux_install} +@prev_tutorial{tutorial_linux_gdb_pretty_printer} @next_tutorial{tutorial_linux_eclipse} | | | diff --git a/doc/tutorials/introduction/linux_gdb_pretty_printer/images/example.png b/doc/tutorials/introduction/linux_gdb_pretty_printer/images/example.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec673dcc21d74eb626b3f9b7a627f029c781873 GIT binary patch literal 35727 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 literal 0 HcmV?d00001 diff --git a/doc/tutorials/introduction/linux_gdb_pretty_printer/linux_gdb_pretty_printer.markdown b/doc/tutorials/introduction/linux_gdb_pretty_printer/linux_gdb_pretty_printer.markdown new file mode 100644 index 0000000000..9d64469920 --- /dev/null +++ b/doc/tutorials/introduction/linux_gdb_pretty_printer/linux_gdb_pretty_printer.markdown @@ -0,0 +1,38 @@ +Using OpenCV with gdb-powered IDEs {#tutorial_linux_gdb_pretty_printer} +===================== + +@prev_tutorial{tutorial_linux_install} +@next_tutorial{tutorial_linux_gcc_cmake} + +| | | +| -: | :- | +| Original author | Egor Smirnov | +| Compatibility | OpenCV >= 4.0 | + +@tableofcontents + +# Capabilities {#tutorial_linux_gdb_pretty_printer_capabilities} + +This pretty-printer can show element type, `is_continuous`, `is_submatrix` flags and (possibly truncated) matrix. It is known to work in Clion, VS Code and gdb. + +![Clion example](images/example.png) + + +# Installation {#tutorial_linux_gdb_pretty_printer_installation} + +Move into `opencv/samples/gdb/`. Place `mat_pretty_printer.py` in a convinient place, rename `gdbinit` to `.gdbinit` and move it into your home folder. Change 'source' line of `.gdbinit` to point to your `mat_pretty_printer.py` path. + +In order to check version of python bundled with your gdb, use the following commands from the gdb shell: + + python + import sys + print(sys.version_info) + end + +If the version of python 3 installed in your system doesn't match the version in gdb, create a new virtual environment with the exact same version, install `numpy` and change the path to python3 in `.gdbinit` accordingly. + + +# Usage {#tutorial_linux_gdb_pretty_printer_usage} + +The fields in a debugger prefixed with `view_` are pseudo-fields added for convinience, the rest are left as is. +If you feel that the number of elements in truncated view is too low, you can edit `mat_pretty_printer.py` - `np.set_printoptions` controlls everything matrix display-related. diff --git a/doc/tutorials/introduction/linux_install/linux_install.markdown b/doc/tutorials/introduction/linux_install/linux_install.markdown index 5083fac282..e69f6ea707 100644 --- a/doc/tutorials/introduction/linux_install/linux_install.markdown +++ b/doc/tutorials/introduction/linux_install/linux_install.markdown @@ -1,7 +1,7 @@ Installation in Linux {#tutorial_linux_install} ===================== -@next_tutorial{tutorial_linux_gcc_cmake} +@next_tutorial{tutorial_linux_gdb_pretty_printer} | | | | -: | :- | diff --git a/doc/tutorials/introduction/table_of_content_introduction.markdown b/doc/tutorials/introduction/table_of_content_introduction.markdown index d1f2aa3ca3..8fa89d7d7f 100644 --- a/doc/tutorials/introduction/table_of_content_introduction.markdown +++ b/doc/tutorials/introduction/table_of_content_introduction.markdown @@ -6,6 +6,7 @@ Introduction to OpenCV {#tutorial_table_of_content_introduction} ##### Linux - @subpage tutorial_linux_install +- @subpage tutorial_linux_gdb_pretty_printer - @subpage tutorial_linux_gcc_cmake - @subpage tutorial_linux_eclipse diff --git a/samples/gdb/gdbinit b/samples/gdb/gdbinit new file mode 100644 index 0000000000..228e8f7023 --- /dev/null +++ b/samples/gdb/gdbinit @@ -0,0 +1,23 @@ +set auto-load local-gdbinit on +set print elements 0 +add-auto-load-safe-path / + +python +# Update GDB's Python paths with the `sys.path` values of the local +# Python installation, whether that is brew'ed Python, a virtualenv, +# or another system python. + +# Convert GDB to interpret in Python + +import os, subprocess, sys + +# Execute a Python using the user's shell and pull out the sys.path (for site-packages) +paths = subprocess.check_output('/usr/bin/python3 -c "import os,sys;print(os.linesep.join(sys.path).strip())"',shell=True).decode("utf-8").split() + +# Extend GDB's Python's search path +sys.path.extend(paths) + +end + + +source /your/path/to/mat_pretty_printer.py diff --git a/samples/gdb/mat_pretty_printer.py b/samples/gdb/mat_pretty_printer.py new file mode 100644 index 0000000000..e6ad2cbde2 --- /dev/null +++ b/samples/gdb/mat_pretty_printer.py @@ -0,0 +1,212 @@ +import gdb +import numpy as np +from enum import Enum + +np.set_printoptions(suppress=True) # prevent numpy exponential notation on print, default False +# np.set_printoptions(threshold=sys.maxsize) + + +def conv(obj, t): + return gdb.parse_and_eval(f'({t})({obj})') + + +def booli(obj): + return conv(str(obj).lower(), 'bool') + + +def stri(obj): + s = f'"{obj}"' + return conv(s.translate(s.maketrans('\n', ' ')), 'char*') + + +class MagicValues(Enum): + MAGIC_VAL = 0x42FF0000 + AUTO_STEP = 0 + CONTINUOUS_FLAG = 1 << 14 + SUBMATRIX_FLAG = 1 << 15 + + +class MagicMasks(Enum): + MAGIC_MASK = 0xFFFF0000 + TYPE_MASK = 0x00000FFF + DEPTH_MASK = 7 + + +class Depth(Enum): + CV_8U = 0 + CV_8S = 1 + CV_16U = 2 + CV_16S = 3 + CV_32S = 4 + CV_32F = 5 + CV_64F = 6 + CV_16F = 7 + + +def create_enum(n): + def make_type(depth, cn): + return depth.value + ((cn - 1) << 3) + defs = [(f'{depth.name}C{i}', make_type(depth, i)) for depth in Depth for i in range(1, n + 1)] + return Enum('Type', defs) + + +Type = create_enum(512) + + +class Flags: + def depth(self): + return Depth(self.flags & MagicMasks.DEPTH_MASK.value) + + def dtype(self): + depth = self.depth() + ret = None + + if depth == Depth.CV_8U: + ret = (np.uint8, 'uint8_t') + elif depth == Depth.CV_8S: + ret = (np.int8, 'int8_t') + elif depth == Depth.CV_16U: + ret = (np.uint16, 'uint16_t') + elif depth == Depth.CV_16S: + ret = (np.int16, 'int16_t') + elif depth == Depth.CV_32S: + ret = (np.int32, 'int32_t') + elif depth == Depth.CV_32F: + ret = (np.float32, 'float') + elif depth == Depth.CV_64F: + ret = (np.float64, 'double') + elif depth == Depth.CV_16F: + ret = (np.float16, 'float16') + + return ret + + def type(self): + return Type(self.flags & MagicMasks.TYPE_MASK.value) + + def channels(self): + return ((self.flags & (511 << 3)) >> 3) + 1 + + def is_continuous(self): + return (self.flags & MagicValues.CONTINUOUS_FLAG.value) != 0 + + def is_submatrix(self): + return (self.flags & MagicValues.SUBMATRIX_FLAG.value) != 0 + + def __init__(self, flags): + self.flags = flags + + def __iter__(self): + return iter({ + 'type': stri(self.type().name), + 'is_continuous': booli(self.is_continuous()), + 'is_submatrix': booli(self.is_submatrix()) + }.items()) + + +class Size: + def __init__(self, ptr): + self.ptr = ptr + + def dims(self): + return int((self.ptr - 1).dereference()) + + def to_numpy(self): + return np.array([int(self.ptr[i]) for i in range(self.dims())], dtype=np.int64) + + def __iter__(self): + return iter({'size': stri(self.to_numpy())}.items()) + + +class Mat: + def __init__(self, m, size, flags): + (dtype, ctype) = flags.dtype() + elsize = np.dtype(dtype).itemsize + + ptr = m['data'] + dataptr = int(ptr) + length = (int(m['dataend']) - dataptr) // elsize + start = (int(m['datastart']) - dataptr) // elsize + + if length == 0: + self.mat = np.array([]) + self.view = self.mat + return + + if dtype != np.float16: + ctype = gdb.lookup_type(ctype) + ptr = ptr.cast(ctype.array(length - 1).pointer()).dereference() + self.mat = np.array([ptr[i] for i in range(length)], dtype=dtype) + else: + u16 = gdb.lookup_type('uint16_t') + ptr = ptr.cast(u16.array(length - 1).pointer()).dereference() + self.mat = np.array([ptr[i] for i in range(length)], dtype=np.uint16) + self.mat = self.mat.view(np.float16) + + steps = np.asarray([int(m['step']['p'][i]) for i in range(size.dims())], dtype=np.int64) + self.view = np.lib.stride_tricks.as_strided(self.mat[start:], shape=size.to_numpy(), strides=steps) + + def __iter__(self): + return iter({'data': stri(self.view)}.items()) + + +class MatPrinter: + """Print a cv::Mat""" + + def __init__(self, mat): + self.mat = mat + + def views(self): + m = self.mat + + flags = Flags(int(m['flags'])) + size = Size(m['size']['p']) + data = Mat(m, size, flags) + + for x in [flags, size, data]: + for k, v in x: + yield 'view_' + k, v + + def real(self): + m = self.mat + + for field in m.type.fields(): + k = field.name + v = m[k] + yield k, v + + # TODO: add an enum in interface.h with all cv::Mat element types and use that instead + # yield 'test', gdb.parse_and_eval(f'(cv::MatTypes)0') + + def children(self): # TODO: hide real members under new child somehow + yield from self.views() + yield from self.real() + + +def get_type(val): + # Get the type. + vtype = val.type + + # If it points to a reference, get the reference. + if vtype.code == gdb.TYPE_CODE_REF: + vtype = vtype.target() + + # Get the unqualified type, stripped of typedefs. + vtype = vtype.unqualified().strip_typedefs() + + # Get the type name. + typename = vtype.tag + + return typename + + +def mat_printer(val): + typename = get_type(val) + + if typename is None: + return None + + if str(typename) == 'cv::Mat': + return MatPrinter(val) + + +gdb.pretty_printers.append(mat_printer)