Image data formats
List of supported image formats.
- RAW (BV workbench default)
- TIFF (standard)
- GSD/GSH (backward compatibility)
- RSD (backward compatibility)
tip
Use RAW when possible for best read/write speed.
RAW Version 4 (latest)
File header layout
Offset | Field name | Type | Size |
---|---|---|---|
0 | VERSION | Int32 | 4 |
4 | IMAGE_DATA_OFFSET | Int32 | 4 |
8 | FRAME_COUNT | Int32 | 4 |
12 | SAMPLING_TIME | Float64 | 8 |
20 | WIDTH | Int32 | 4 |
24 | HEIGHT | Int32 | 4 |
28 | BIT_DEPTH | Int32 | 4 |
32 | PIXEL_SIZE_X | Float64 | 8 |
40 | PIXEL_SIZE_Y | Float64 | 8 |
48 | ROI_COUNT | Int32 | 4 |
52 | ROI | Rect | ROI_COUNT * 16 |
... | - | - | |
IMAGE_DATA_OFFSET | BACKGROUND | UInt16 | WIDTH * HEIGHT * 2 |
IMAGE_DATA_OFFSET + WIDTH * HEIGHT * 2 | REF_FRAME | UInt16 | WIDTH * HEIGHT * 2 |
IMAGE_DATA_OFFSET + WIDTH * HEIGHT * 4 | MASK | UInt8 | WIDTH * HEIGHT |
IMAGE_DATA_OFFSET + WIDTH * HEIGHT * 4 | ROI_PIXELS | UInt16 | varies |
struct Rect {
int x;
int y;
int width,
int height,
};
Python script to read version 4 files.
import numpy as np
import matplotlib.pyplot as plt
class Rect:
def __init__(self, x : int, y: int, w: int, h: int):
self.x = x
self.y = y
self.w = w
self.h = h
def __str__(self):
return f"X : {x}, Y : {y}, W : {w}, H : {h}"
# open file
f = open("test_v4.raw",'rb')
try:
version = np.fromfile(f, dtype=np.uint32, count=1)[0]
print(f"Version : {version}")
image_data_offset = np.fromfile(f, dtype=np.uint32, count=1)[0]
print(f"Image data offset : {image_data_offset}")
frame_count = np.fromfile(f, dtype=np.uint32, count=1)[0]
print(f"Frame count : {frame_count}")
sampling_time = np.fromfile(f, dtype=np.float64, count=1)[0]
print(f"Sampling rate : {sampling_time/1000} ms ({1/sampling_time} FPS)")
# read image dimensions
width = np.fromfile(f, dtype=np.uint32, count=1)[0]
height = np.fromfile(f, dtype=np.uint32, count=1)[0]
print(f"Image size : {width} x {height}")
bit_depth = np.fromfile(f, dtype=np.uint32, count=1)[0]
print(f"Bit depth : {bit_depth}")
dx = np.fromfile(f, dtype=np.float64, count=1)[0]
dy = np.fromfile(f, dtype=np.float64, count=1)[0]
print(f"Image scale : {dx} x {dy} mm^2/px^2")
# read image region definitions
roi_count = np.fromfile(f, dtype=np.uint32, count=1)[0]
print(f"ROI count : {roi_count}")
regions = []
for i in range(roi_count):
temp = np.fromfile(f, dtype=np.uint32, count=4)
x = temp[0]
y = temp[1]
w = temp[2]
h = temp[3]
regions.append(Rect(x, y, w, h))
print("Regions : ")
for r in regions:
print(r)
# read background
f.seek(image_data_offset)
background = np.fromfile(f, dtype=np.uint16, count=width*height)
background = background.reshape(height,width)
#plt.figure(0)
#plt.title("background image")
#plt.imshow(background)
# read ref frame
refFrame = np.fromfile(f, dtype=np.uint16, count=width*height)
refFrame = refFrame.reshape(height, width)
#plt.figure(1)
#plt.title("reference image (F0)")
#plt.imshow(refFrame)
# read mask
maskImg = np.fromfile(f, dtype=np.uint8, count=width*height)
maskImg = maskImg.reshape(height,width)
#plt.figure(2)
#plt.title("mask")
#plt.imshow(maskImg)
# read first frame
region0_size = regions[0].w * regions[0].h
frame0_region0 = np.fromfile(f, dtype=np.uint16, count=region0_size)
frame0_region0 = frame0_region0.reshape(regions[0].h, regions[0].w)
plt.figure(3)
plt.title("image 0 region 0")
plt.imshow(frame0_region0)
plt.show()
# If images contain multiple regions, data is ordered as
# frame0_region0,
# frame0_region1,
# ...
# frame0_regionN,
# frame1_region0,
# frame1_region1,
# ...
# frame1_regionN,
# frameN_region0,
# ...
finally:
f.close()
RAW Version 3 (BV Workbench 2)
Python script to read version 3 and earlier files, which had embedded XML.
import numpy as np
import lxml.etree
import matplotlib.pyplot as plt
class Rect:
def __init__(self, x : int, y: int, w: int, h: int):
self.x = x
self.y = y
self.w = w
self.h = h
def __str__(self):
return f"X : {x}, Y : {y}, W : {w}, H : {h}"
f = open("test_v3.raw",'rb')
try:
version = np.fromfile(f, dtype=np.uint32, count=1)[0]
print(f"Version : {version}")
# read metadata size and offset
metadataSize = np.fromfile(f, dtype=np.uint32, count=1)[0]
metadataOffset = 12
if version >= 3:
f.seek(8)
roiDataSize = np.fromfile(f, dtype=np.uint32, count=1)[0]
print ("ROI data size : " + str(roiDataSize))
metadataOffset = 16
#read XML and create element tree
f.seek(metadataOffset)
xmlStr = f.read(metadataSize).decode("utf-8")
root = lxml.etree.fromstring(xmlStr)
# read image dimensions
width = int(root.find('Image/Width').text)
height = int(root.find('Image/Height').text)
print(f"Image size : {width} x {height}")
# read image region definitions
regions = []
for child in root.find('Image/Regions'):
x = int(child.find('X').text)
y = int(child.find('Y').text)
w = int(child.find('Width').text)
h = int(child.find('Height').text)
regions.append(Rect(x, y, w, h))
print("Regions : ")
for r in regions:
print(r)
bit_depth = int(root.find('Image/BitDepth').text)
frame_count = int(root.find('Acquisition/NumberOfFrames').text)
print(f"Bit depth : {bit_depth}")
print(f"Frame count : {frame_count}")
if version <= 2:
f.seek(8)
elif version >= 3:
f.seek(12)
# read image data offset
imgOffset = np.fromfile(f, dtype=np.uint32, count=1)[0]
# read background image to numpy array
f.seek(imgOffset)
background = np.fromfile(f, dtype=np.uint16, count=width*height)
background = background.reshape(height,width)
#plt.figure(0)
#plt.title("background image")
#plt.imshow(background)
if (version >= 2):
# read the reference (F0) frame
refImg = np.fromfile(f, dtype=np.uint16, count=width*height)
refImg = refImg.reshape(height,width)
#plt.figure(1)
#plt.title("reference image")
#plt.imshow(refImg)
# read the binary mask
mask = np.fromfile(f, dtype=np.uint8, count=width*height)
mask = mask.reshape(height,width)
#plt.figure(2)
#plt.title("mask")
#plt.imshow(mask)
region0_size = regions[0].w * regions[0].h
frame0_region0 = np.fromfile(f, dtype=np.uint16, count=region0_size)
frame0_region0 = frame0_region0.reshape(regions[0].h, regions[0].w)
plt.figure(3)
plt.title("image 0 region 0")
plt.imshow(frame0_region0)
plt.show()
# If images contain multiple regions, data is ordered as
# frame0_region0,
# frame0_region1,
# ...
# frame0_regionN,
# frame1_region0,
# frame1_region1,
# ...
# frame1_regionN,
# frameN_region0,
# ...
finally:
f.close()
TIFF
Images can be stored to/read from multi-page TIFF (revision 6.0) files.
When larger than 4GB, the BigTIFF format is used.
GSD
For backward compatibility with BV Analyzer.
- Images are stored as 14-bit diff values.
- Analog signals are appended to the end.
- Only when they are sampled at 20 times the rate of images
RSD (read only)
Coming soon.