vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
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
|
||||
|
||||
shape = size.to_numpy()
|
||||
steps = np.asarray([int(m['step']['p'][i]) for i in range(len(shape))], dtype=np.int64)
|
||||
|
||||
ptr = m['data']
|
||||
# either we are default-constructed or sizes are zero
|
||||
if int(ptr) == 0 or np.prod(shape * steps) == 0:
|
||||
self.mat = np.array([])
|
||||
self.view = self.mat
|
||||
return
|
||||
|
||||
# we don't want to show excess brackets
|
||||
if flags.channels() != 1:
|
||||
shape = np.append(shape, flags.channels())
|
||||
steps = np.append(steps, elsize)
|
||||
|
||||
# get the length of contiguous array from data to the last element of the matrix
|
||||
length = 1 + np.sum((shape - 1) * steps) // elsize
|
||||
|
||||
if dtype != np.float16:
|
||||
# read all elements into self.mat
|
||||
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:
|
||||
# read as uint16_t and then reinterpret the bytes as float16
|
||||
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)
|
||||
|
||||
# numpy will do the heavy lifting of strided access
|
||||
self.view = np.lib.stride_tricks.as_strided(self.mat, shape=shape, 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)
|
||||
Reference in New Issue
Block a user