def test_swtriggermultipleclients(): cam = ifm3dpy.Camera() # O3X cannot handle multiple client connections to PCIC # so this test does not apply if cam.is_O3X(): return # mark the current active application as sw triggered idx = cam.active_application() config = cam.to_json() config['ifm3d']['Apps'][idx-1]['TriggerMode'] = \ str(int(ifm3dpy.Camera.trigger_mode.SW)) cam.from_json(config) # create two framegrabbers with same camera fg1 = ifm3dpy.FrameGrabber(cam) fg2 = ifm3dpy.FrameGrabber(cam) # launch two threads where each of the framegrabbers will # wait for a new frame def get_frame(fg): buff = ifm3dpy.ImageBuffer() if not fg.wait_for_frame(buff, 5000): buff = None return buff pool = ThreadPool(2) res = pool.map_async(get_frame, [fg1, fg2]) # Let's S/W trigger from the first -- this could have been a third # framegrabber fg1.sw_trigger() pool.close() pool.join() # Did they both get a frame? frames = res.get() assert all(frames) # Check that the data are the same if all(frames): assert (frames[0].distance_image() == frames[1].distance_image()).all() assert (frames[0].unit_vectors() == frames[1].unit_vectors()).all() assert (frames[0].gray_image() == frames[1].gray_image()).all() assert ( frames[0].amplitude_image() == frames[1].amplitude_image()).all() assert (frames[0].raw_amplitude_image() == frames[1].raw_amplitude_image()).all() assert (frames[0].confidence_image() == frames[1].confidence_image() ).all() assert (frames[0].xyz_image() == frames[1].xyz_image()).all() # set the camera back into free-run mode config['ifm3d']['Apps'][idx-1]['TriggerMode'] = \ str(int(ifm3dpy.Camera.trigger_mode.FREE_RUN)) cam.from_json(config)
def test_json_model(): cam = ifm3dpy.Camera() mask = ifm3dpy.IMG_AMP | ifm3dpy.JSON_MODEL if cam.is_O3X(): with pytest.raises(RuntimeError): fg = ifm3dpy.FrameGrabber(cam, mask) else: fg = ifm3dpy.FrameGrabber(cam, mask) buff = ifm3dpy.ImageBuffer() assert fg.wait_for_frame(buff, 1000) model = buff.json_model() assert model
def test_customschema(): mask = ifm3dpy.IMG_AMP | ifm3dpy.IMG_RDIS | ifm3dpy.IMG_UVEC cam = ifm3dpy.Camera() fg = ifm3dpy.FrameGrabber(cam, mask) buff = ifm3dpy.ImageBuffer() assert fg.wait_for_frame(buff, 1000)
def test_memorymodel_ownership(): cam = ifm3dpy.Camera() im = ifm3dpy.ImageBuffer() fg = ifm3dpy.FrameGrabber(cam) assert fg.wait_for_frame(im, 1000) # Memory is owned and managed in the C++ layer. When projected, numpy # should report that it does not 'own' the underlying buffer assert not im.xyz_image().flags.owndata assert not im.amplitude_image().flags.owndata # Pointer to underlying buffers should remain constant on consecutive # captures with the same ImageBuffer object addr_xyz1 = im.xyz_image().__array_interface__['data'][0] addr_amp1 = im.amplitude_image().__array_interface__['data'][0] assert fg.wait_for_frame(im, 1000) addr_xyz2 = im.xyz_image().__array_interface__['data'][0] addr_amp2 = im.amplitude_image().__array_interface__['data'][0] assert addr_xyz1 == addr_xyz2 assert addr_amp1 == addr_amp2 # Copies of numpy arrays should copy into the python memory space (aka # numpy should report that it DOES own memory of copies, and the addrs # should be different xyz = im.xyz_image() xyz_copy = xyz.copy() assert not xyz.flags.owndata assert xyz_copy.flags.owndata assert (xyz.__array_interface__['data'][0] != xyz_copy.__array_interface__['data'][0])
def test_intrinsicparamschema(): mask = ifm3dpy.IMG_AMP | ifm3dpy.IMG_RDIS | ifm3dpy.INTR_CAL cam = ifm3dpy.Camera() if cam.is_O3X(): with pytest.raises(RuntimeError): fg = ifm3dpy.FrameGrabber(cam, mask) elif (cam.is_O3D() and cam.check_minimum_firmware_version( ifm3dpy.O3D_INTRINSIC_PARAM_SUPPORT_MAJOR, ifm3dpy.O3D_INTRINSIC_PARAM_SUPPORT_MINOR, ifm3dpy.O3D_INTRINSIC_PARAM_SUPPORT_PATCH)): fg = ifm3dpy.FrameGrabber(cam, mask) buff = ifm3dpy.ImageBuffer() assert fg.wait_for_frame(buff, 1000) elif (cam.is_O3D()): with pytest.raises(RuntimeError): fg = ifm3dpy.FrameGrabber(cam, mask)
def test_xyzimage(): cam = ifm3dpy.Camera() fg = ifm3dpy.FrameGrabber(cam) im = ifm3dpy.ImageBuffer() assert fg.wait_for_frame(im, 1000) xyz = im.xyz_image() assert (xyz.dtype == np.int16) or (xyz.dtype == np.float32) assert (xyz.shape[2] == 3)
def test_waitforframe(): cam = ifm3dpy.Camera() fg = ifm3dpy.FrameGrabber(cam) buff = ifm3dpy.ImageBuffer() count = 0 for i in range(10): assert fg.wait_for_frame(buff, 1000) count = count + 1 assert count == 10
def test_framegrabberrecycling(): cam = ifm3dpy.Camera() fg = ifm3dpy.FrameGrabber(cam) buff = ifm3dpy.ImageBuffer() for i in range(5): assert fg.wait_for_frame(buff, 1000) fg.reset(cam) for i in range(5): assert fg.wait_for_frame(buff, 1000)
def test_references(): cam = ifm3dpy.Camera() fg = ifm3dpy.FrameGrabber(cam) im = ifm3dpy.ImageBuffer() assert fg.wait_for_frame(im, 1000) amp1 = im.amplitude_image() amp2 = im.amplitude_image() if cam.is_O3X(): assert amp1.dtype == np.float32 assert amp2.dtype == np.float32 else: assert amp1.dtype == np.uint16 assert amp2.dtype == np.uint16 assert (amp1 == amp2).all() amp2 += 1 assert (amp1 == amp2).all()
def __init__(self, ip=ifm3dpy.DEFAULT_IP): """ Create the camera object. With RDIS and AMP to get Distance or Amplitude image. Parameters ---------- ip : str Camera's IP. """ self.cam = ifm3dpy.Camera(ip) try: self.fg = ifm3dpy.FrameGrabber(self.cam, ifm3dpy.IMG_RDIS | ifm3dpy.IMG_AMP) except RuntimeError as e: print(e) sys.exit() self.im = ifm3dpy.ImageBuffer()
def test_timestamp(): json_str = ('{' '"o3d3xx":' '{' '"Device":' '{' '"ActiveApplication": "1"' '},' '"Apps":' '[' '{' '"TriggerMode": "1",' '"Index": "1",' '"Imager":' '{' '"ExposureTime": "5000",' '"ExposureTimeList": "125;5000",' '"ExposureTimeRatio": "40",' '"Type":"under5m_moderate"' '}' '}' ']' '}' '}') j = json.loads(json_str) cam = ifm3dpy.Camera() cam.from_json(j) im = ifm3dpy.ImageBuffer() fg = ifm3dpy.FrameGrabber(cam, ifm3dpy.IMG_AMP | ifm3dpy.IMG_CART) # get two consecutive timestamps assert fg.wait_for_frame(im, 1000) tp1 = im.timestamp() assert fg.wait_for_frame(im, 1000) tp2 = im.timestamp() # the first time point needs to be smaller than the second one assert tp1 < tp2 assert (tp2 - tp1) > datetime.timedelta(milliseconds=20)
def test_softwaretrigger(): cam = ifm3dpy.Camera() idx = cam.active_application() config = cam.to_json() config['ifm3d']['Apps'][idx-1]['TriggerMode'] = \ str(int(ifm3dpy.Camera.trigger_mode.SW)) cam.from_json(config) fg = ifm3dpy.FrameGrabber(cam) buff = ifm3dpy.ImageBuffer() # waiting for an image should now timeout assert not fg.wait_for_frame(buff, 1000) # now, get image data by explicitly s/w triggering the device for i in range(10): fg.sw_trigger() assert fg.wait_for_frame(buff, 1000) # set the camera back into free-run mode config['ifm3d']['Apps'][idx-1]['TriggerMode'] = \ str(int(ifm3dpy.Camera.trigger_mode.FREE_RUN)) cam.from_json(config)
def test_memorymodel_changing_flags(): cam = ifm3dpy.Camera() im = ifm3dpy.ImageBuffer() # First grab a frame with only amplitude data fg = ifm3dpy.FrameGrabber(cam, ifm3dpy.IMG_AMP) assert fg.wait_for_frame(im, 1000) # XYZ should be empty, but have a valid address xyz = im.xyz_image() xyz_addr = xyz.__array_interface__['data'][0] assert all(i == 0 for i in xyz.shape) assert xyz_addr != 0 amp = im.amplitude_image() amp_addr = amp.__array_interface__['data'][0] assert all(i != 0 for i in amp.shape) assert amp_addr != 0 # Cache a copy of the data in amp amp_copy = amp.copy() # Now enable cartesian/xyz data and get another frame using the same # ImageBuffer object fg.reset(cam, ifm3dpy.IMG_AMP | ifm3dpy.IMG_CART) assert fg.wait_for_frame(im, 1000) # We expect XYZ to now be valid, (with a different pointer) xyz = im.xyz_image() assert all(i != 0 for i in xyz.shape) assert xyz_addr != xyz.__array_interface__['data'][0] xyz_addr = xyz.__array_interface__['data'][0] # Amplitude *data* will have changed, but not the underlying pointer! amp = im.amplitude_image() assert all(i != 0 for i in amp.shape) assert amp_addr == amp.__array_interface__['data'][0] assert (amp_copy != amp).any() amp_addr = amp.__array_interface__['data'][0]
def test_computecartesian(): cam = ifm3dpy.Camera() im = ifm3dpy.ImageBuffer() # 1. Stream in the unit vectors fg = ifm3dpy.FrameGrabber(cam, ifm3dpy.IMG_UVEC) assert fg.wait_for_frame(im, 1000) uvec = im.unit_vectors() # 2. Now we stream in both the radial distance image and the cartesian # data. The latter we simply use as ground truth fg.reset(cam, ifm3dpy.IMG_RDIS | ifm3dpy.IMG_CART) assert fg.wait_for_frame(im, 1000) rdis = im.distance_image() conf = im.confidence_image() xyz = im.xyz_image() if xyz.dtype == np.float32: # Convert to mm xyz *= 1000 xyz = xyz.astype(np.int16) # We also need the translation vector from the extrinsics extrinsics = im.extrinsics() tx = extrinsics[0] ty = extrinsics[1] tz = extrinsics[2] # 3. Compute the cartesian data # unit vectors ex = uvec[:, :, 0] ey = uvec[:, :, 1] ez = uvec[:, :, 2] rdis_f = rdis.copy().astype(np.float32) if rdis.dtype == np.float32: # Assume rdis was in meters, convert to mm rdis_f *= 1000 # Compute x_ = ex * rdis_f + tx y_ = ey * rdis_f + ty z_ = ez * rdis_f + tz # Blank out bad pixels .. our zero pixels will # be exactly equal to tx, ty, tz and if any of those # exceed 1cm (our test tolerance) like on an O3D301, # we will get errors in the unit test. bad_mask = (np.bitwise_and(conf, 0x1) == 0x1) x_[bad_mask] = 0 y_[bad_mask] = 0 z_[bad_mask] = 0 # 4. Cast (back) to int16 and transform to ifm3d coord frame x_i = x_.astype(np.int16) y_i = y_.astype(np.int16) z_i = z_.astype(np.int16) x_computed = z_i y_computed = -x_i z_computed = -y_i # 5. Compare for correctness assert (np.abs(x_computed - xyz[:, :, 0]) <= 10).all() assert (np.abs(y_computed - xyz[:, :, 1]) <= 10).all() assert (np.abs(z_computed - xyz[:, :, 2]) <= 10).all()