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
Branches
Tags
No related merge requests found
Pipeline #17902 passed
......@@ -246,21 +246,43 @@ class FTLStreamReader:
warn("frame expected, no image received from decoder")
if ftl.is_float_channel(self._sp.channel):
# TODO: only supports 8 bits per pixel format and 16 bits
# ()"old format")
#
# NVPipe: (2 * width), high bits in left, low in right
if (p.flags & ftl.PacketFlags.MappedDepth):
# New format
# hardcoded constants maxdepth and P
maxdepth = 16
P = (2.0 * 256.0) / 16384.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:
img[img < self._calibration[sp.streamID].min_depth] = 0.0
img[img > self._calibration[sp.streamID].max_depth] = 0.0
except KeyError:
warn("no calibration for received frame")
'''
self._frame = img
else:
......
......@@ -13,6 +13,10 @@ Packet = namedtuple("Packet", ["codec", "definition", "block_total",
StreamPacket = namedtuple("StreamPacket", ["timestamp", "streamID",
"channel_count", "channel"])
class PacketFlags:
RGB = 0x00000001
MappedDepth = 0x00000002
# components/codecs/include/ftl/codecs/channels.hpp
class Channel(IntEnum):
None_ = -1
......
'''
Python wrapper for libde265. Only decoding is (partly) implemented.
'''!
Python wrapper for libde265. Only decoding is implemented.
Requirements:
* libde265 library (libde265.so.0)
* numpy
* opencv or skimage
* opencv (recommended) or skimage
'''
try:
import cv2 as cv
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:
# seems to be much slower than OpenCV resize()
from skimage.transform import resize as resize_skimage
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
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
......@@ -39,6 +43,10 @@ if _threads is None:
_threads = 1
################################################################################
# interface and definitions from libde256 api
################################################################################
# error codes copied from header (de265.h)
class _libde265error(IntEnum):
......@@ -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.restype = ctypes.c_int
################################################################################
class libde265Error(Exception):
def __init__(self, code):
super(libde265Error, self).__init__(
......@@ -168,7 +178,7 @@ class Decoder:
self._more = ctypes.c_int()
self._out_stride = ctypes.c_int()
self._ctx = libde265.de265_new_decoder()
self._supress_warnings = False
self._disable_warnings = False
err = libde265.de265_start_worker_threads(self._ctx, threads)
......@@ -182,28 +192,29 @@ class Decoder:
size = (libde265.de265_get_image_height(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 (???)
# 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):
size_channel = (libde265.de265_get_image_height(de265_image, c),
libde265.de265_get_image_width(de265_image, c))
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")
bpp = libde265.de265_get_bits_per_pixel(de265_image, c)
if bpp != 8:
raise NotImplementedError("%i-bit format not implemented (TODO)" % bpp)
if bpp == 8:
dtype = np.uint8
else:
dtype = np.uint16
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] * size_channel[1]], dtype=np.uint8)
ch = np.frombuffer(img_ptr[:size_channel[0] * self._out_stride.value], dtype=dtype)
ch.shape = size_channel
res[:,:,c] = _resize(ch, size)
......@@ -211,7 +222,7 @@ class Decoder:
return res
def _warning(self):
if self._supress_warnings:
if self._disable_warnings:
return
code = libde265.de265_get_warning(self._ctx)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment