Skip to content
Snippets Groups Projects
Commit 3c8f3cf3 authored by Sebastian Hahta's avatar Sebastian Hahta
Browse files

support for new depth channel x265 format

parent 6ba303ab
No related branches found
No related tags found
No related merge requests found
Pipeline #17902 passed
...@@ -246,21 +246,43 @@ class FTLStreamReader: ...@@ -246,21 +246,43 @@ class FTLStreamReader:
warn("frame expected, no image received from decoder") warn("frame expected, no image received from decoder")
if ftl.is_float_channel(self._sp.channel): if ftl.is_float_channel(self._sp.channel):
# TODO: only supports 8 bits per pixel format and 16 bits if (p.flags & ftl.PacketFlags.MappedDepth):
# ()"old format") # New format
#
# NVPipe: (2 * width), high bits in left, low in right # hardcoded constants maxdepth and P
maxdepth = 16
high = img[:,(img.shape[1]//2):,0].astype(np.uint32) << 8 P = (2.0 * 256.0) / 16384.0
low = img[:,:(img.shape[1]//2),0].astype(np.uint32)
img = (high|low).astype(np.float)/1000.0 # use only 8 bits of 10
img = (img >> 2).astype(np.float) / 255
L = img[:,:,0]
Ha = img[:,:,1]
Hb = img[:,:,2]
m = np.floor(4.0 * (L/P) - 0.5).astype(np.int) % 4
L0 = L - ((L-(P / 8.0)) % P) + (P / 4.0) * m.astype(np.float) - (P/8.0)
s = np.zeros(img.shape[:2], dtype=np.float)
np.copyto(s, (P/2.0) * Ha, where=m == 0)
np.copyto(s, (P/2.0) * Hb, where=m == 1)
np.copyto(s, (P/2.0) * (1.0 - Ha), where=m == 2)
np.copyto(s, (P/2.0) * (1.0 - Hb), where=m == 3)
img = (L0+s) * maxdepth
else:
# NvPipe format
high = img[:,(img.shape[1]//2):,0].astype(np.uint32) << 8
low = img[:,:(img.shape[1]//2),0].astype(np.uint32)
img = (high|low).astype(np.float)/1000.0
'''
try: try:
img[img < self._calibration[sp.streamID].min_depth] = 0.0 img[img < self._calibration[sp.streamID].min_depth] = 0.0
img[img > self._calibration[sp.streamID].max_depth] = 0.0 img[img > self._calibration[sp.streamID].max_depth] = 0.0
except KeyError: except KeyError:
warn("no calibration for received frame") warn("no calibration for received frame")
'''
self._frame = img self._frame = img
else: else:
......
...@@ -13,6 +13,10 @@ Packet = namedtuple("Packet", ["codec", "definition", "block_total", ...@@ -13,6 +13,10 @@ Packet = namedtuple("Packet", ["codec", "definition", "block_total",
StreamPacket = namedtuple("StreamPacket", ["timestamp", "streamID", StreamPacket = namedtuple("StreamPacket", ["timestamp", "streamID",
"channel_count", "channel"]) "channel_count", "channel"])
class PacketFlags:
RGB = 0x00000001
MappedDepth = 0x00000002
# components/codecs/include/ftl/codecs/channels.hpp # components/codecs/include/ftl/codecs/channels.hpp
class Channel(IntEnum): class Channel(IntEnum):
None_ = -1 None_ = -1
......
''' '''!
Python wrapper for libde265. Only decoding is (partly) implemented. Python wrapper for libde265. Only decoding is implemented.
Requirements: Requirements:
* libde265 library (libde265.so.0) * libde265 library (libde265.so.0)
* numpy * numpy
* opencv or skimage * opencv (recommended) or skimage
''' '''
try: try:
import cv2 as cv import cv2 as cv
def _resize(img, size): def _resize(img, size):
return cv.resize(img, dsize=tuple(reversed(size)), interpolation=cv.INTER_CUBIC) dst = np.zeros(size, dtype=img.dtype)
cv.resize(img, tuple(reversed(size)), dst, interpolation=cv.INTER_LINEAR)
return dst
except ImportError: except ImportError:
# seems to be much slower than OpenCV resize()
from skimage.transform import resize as resize_skimage from skimage.transform import resize as resize_skimage
def _resize(img, size): def _resize(img, size):
# skimage resize() return dtype float64, convert back to uint8 # skimage resize() return dtype float64, convert back to original type
# order: 0 nn, 1 bilinear, 3 bicubic # order: 0 nn, 1 bilinear, 3 bicubic
return (resize_skimage(img, size, order=3, mode="constant", cval=0) * 255).astype(np.uint8) return (resize_skimage(img, size, order=2, mode="constant", cval=0) * np.iinfo(img.dtype).max).astype(img.dtype)
from warnings import warn from warnings import warn
...@@ -39,6 +43,10 @@ if _threads is None: ...@@ -39,6 +43,10 @@ if _threads is None:
_threads = 1 _threads = 1
################################################################################
# interface and definitions from libde256 api
################################################################################
# error codes copied from header (de265.h) # error codes copied from header (de265.h)
class _libde265error(IntEnum): class _libde265error(IntEnum):
...@@ -155,6 +163,8 @@ libde265.de265_get_image_plane.restype = ctypes.POINTER(ctypes.c_char) ...@@ -155,6 +163,8 @@ libde265.de265_get_image_plane.restype = ctypes.POINTER(ctypes.c_char)
libde265.de265_get_number_of_input_bytes_pending.argtypes = [ctypes.c_void_p] libde265.de265_get_number_of_input_bytes_pending.argtypes = [ctypes.c_void_p]
libde265.de265_get_number_of_input_bytes_pending.restype = ctypes.c_int libde265.de265_get_number_of_input_bytes_pending.restype = ctypes.c_int
################################################################################
class libde265Error(Exception): class libde265Error(Exception):
def __init__(self, code): def __init__(self, code):
super(libde265Error, self).__init__( super(libde265Error, self).__init__(
...@@ -168,7 +178,7 @@ class Decoder: ...@@ -168,7 +178,7 @@ class Decoder:
self._more = ctypes.c_int() self._more = ctypes.c_int()
self._out_stride = ctypes.c_int() self._out_stride = ctypes.c_int()
self._ctx = libde265.de265_new_decoder() self._ctx = libde265.de265_new_decoder()
self._supress_warnings = False self._disable_warnings = False
err = libde265.de265_start_worker_threads(self._ctx, threads) err = libde265.de265_start_worker_threads(self._ctx, threads)
...@@ -182,28 +192,29 @@ class Decoder: ...@@ -182,28 +192,29 @@ class Decoder:
size = (libde265.de265_get_image_height(de265_image, 0), size = (libde265.de265_get_image_height(de265_image, 0),
libde265.de265_get_image_width(de265_image, 0)) libde265.de265_get_image_width(de265_image, 0))
res = np.zeros((*size, 3), dtype=np.uint8) res = np.zeros((*size, 3), dtype=np.uint16)
# libde265: always 420 (???) # libde265: always 420 (???)
# chroma_format = libde265.de265_get_chroma_format(de265_image) chroma_format = libde265.de265_get_chroma_format(de265_image)
if chroma_format != de265_chroma.de265_chroma_420:
raise NotImplementedError("Unsupported chroma format %s" % str(chroma_format))
for c in range(0, 3): for c in range(0, 3):
size_channel = (libde265.de265_get_image_height(de265_image, c), size_channel = (libde265.de265_get_image_height(de265_image, c),
libde265.de265_get_image_width(de265_image, c)) libde265.de265_get_image_width(de265_image, c))
if size_channel[0] > size[0] or size_channel[1] > size[1]: if size_channel[0] > size[0] or size_channel[1] > size[1]:
# Is this possible?
print(size, size_channel)
raise Exception("Channel larger than first channel") raise Exception("Channel larger than first channel")
bpp = libde265.de265_get_bits_per_pixel(de265_image, c) bpp = libde265.de265_get_bits_per_pixel(de265_image, c)
if bpp != 8: if bpp == 8:
raise NotImplementedError("%i-bit format not implemented (TODO)" % bpp) dtype = np.uint8
else:
dtype = np.uint16
img_ptr = libde265.de265_get_image_plane(de265_image, c, self._out_stride) img_ptr = libde265.de265_get_image_plane(de265_image, c, self._out_stride)
# libde: how is 10 bits per pixel returned ch = np.frombuffer(img_ptr[:size_channel[0] * self._out_stride.value], dtype=dtype)
ch = np.frombuffer(img_ptr[:size_channel[0] * size_channel[1]], dtype=np.uint8)
ch.shape = size_channel ch.shape = size_channel
res[:,:,c] = _resize(ch, size) res[:,:,c] = _resize(ch, size)
...@@ -211,7 +222,7 @@ class Decoder: ...@@ -211,7 +222,7 @@ class Decoder:
return res return res
def _warning(self): def _warning(self):
if self._supress_warnings: if self._disable_warnings:
return return
code = libde265.de265_get_warning(self._ctx) code = libde265.de265_get_warning(self._ctx)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment