Impact Acquire SDK Python
Getting A Single Image

At least four steps are necessary to capture a single image from a Balluff device. These steps are explained with the help of source examples from ImpactControlCenter.

Step 1: The Device Needs To Be Initialized

# Get a pointer to the first device found
devMgr = acquire.DeviceManager()
pDev = devMgr.getDevice(0)
# initialise it(this step is optional as this will be done automatically from
# all other wrapper classes that accept a device pointer):
pDev.open()
Note
You HAVE to keep a reference to at least one instance of mvIMPACT.acquire.DeviceManager as long as you want to work with devices! When the last reference gets destroyed by the garbage collector all devices will be closed automatically!

Step 2: Request The Acquisition Of An Image

# create an instance of the function interface for this device
# (this would also initialise a device if necessary)
fi = acquire.FunctionInterface(pDev)
# send the request for one image down to the driver
fi.imageRequestSingle()

A live acquisition (running inside a thread function) could be implemented as follows:

ContinuousCapture.py:

import os, platform, sys
# import all the stuff from our SDK into the current scope
from mvIMPACT import acquire
# import all the helper functions for the examples using our SDK such as 'conditionalSetProperty' into the current scope
# If you want to use this module in your code feel free to do so but make sure the 'Common' folder resides in a sub-folder of your project then
from mvIMPACT.Common import exampleHelper
# For systems with NO mvDisplay library support
#import ctypes
#import Image
#import numpy
devMgr = acquire.DeviceManager()
pDev = exampleHelper.getDeviceFromUserInput(devMgr)
if pDev == None:
exampleHelper.requestENTERFromUser()
sys.exit(-1)
pDev.open()
print("Please enter the number of buffers to capture followed by [ENTER]: ", end='')
framesToCapture = exampleHelper.getNumberFromUser()
if framesToCapture < 1:
print("Invalid input! Please capture at least one image")
sys.exit(-1)
# The mvDisplay library is only available on Windows systems for now
isDisplayModuleAvailable = platform.system() == "Windows"
if isDisplayModuleAvailable:
display = acquire.ImageDisplayWindow("A window created from Python")
else:
print("The display library of this SDK is not available on this('" + platform.system() + "') system. Consider using the PIL(Python Image Library) and numpy(Numerical Python) packages instead. Have a look at the source code of this application to get an idea how.")
fi = acquire.FunctionInterface(pDev)
statistics = acquire.Statistics(pDev)
while fi.imageRequestSingle() == acquire.DMR_NO_ERROR:
print("Buffer queued")
pPreviousRequest = None
exampleHelper.manuallyStartAcquisitionIfNeeded(pDev, fi)
for i in range(framesToCapture):
requestNr = fi.imageRequestWaitFor(10000)
if fi.isRequestNrValid(requestNr):
pRequest = fi.getRequest(requestNr)
if pRequest.isOK:
if i%100 == 0:
print("Info from " + pDev.serial.read() +
": " + statistics.framesPerSecond.name() + ": " + statistics.framesPerSecond.readS() +
", " + statistics.errorCount.name() + ": " + statistics.errorCount.readS() +
", " + statistics.captureTime_s.name() + ": " + statistics.captureTime_s.readS())
if isDisplayModuleAvailable:
display.GetImageDisplay().SetImage(pRequest)
display.GetImageDisplay().Update()
# For systems with NO mvDisplay library support
#cbuf = (ctypes.c_char * pRequest.imageSize.read()).from_address(int(pRequest.imageData.read()))
#channelType = numpy.uint16 if pRequest.imageChannelBitDepth.read() > 8 else numpy.uint8
#arr = numpy.fromstring(cbuf, dtype = channelType)
#arr.shape = (pRequest.imageHeight.read(), pRequest.imageWidth.read(), pRequest.imageChannelCount.read())
#if channelCount == 1:
# img = Image.fromarray(arr)
#else:
# img = Image.fromarray(arr, 'RGBA' if alpha else 'RGB')
if pPreviousRequest != None:
pPreviousRequest.unlock()
pPreviousRequest = pRequest
fi.imageRequestSingle()
else:
# Please note that slow systems or interface technologies in combination with high resolution sensors
# might need more time to transmit an image than the timeout value which has been passed to imageRequestWaitFor().
# If this is the case simply wait multiple times OR increase the timeout(not recommended as usually not necessary
# and potentially makes the capture thread less responsive) and rebuild this application.
# Once the device is configured for triggered image acquisition and the timeout elapsed before
# the device has been triggered this might happen as well.
# The return code would be -2119(DEV_WAIT_FOR_REQUEST_FAILED) in that case, the documentation will provide
# additional information under TDMR_ERROR in the interface reference.
# If waiting with an infinite timeout(-1) it will be necessary to call 'imageRequestReset' from another thread
# to force 'imageRequestWaitFor' to return when no data is coming from the device/can be captured.
print("imageRequestWaitFor failed (" + str(requestNr) + ", " + acquire.ImpactAcquireException.getErrorCodeAsString(requestNr) + ")")
exampleHelper.manuallyStopAcquisitionIfNeeded(pDev, fi)
exampleHelper.requestENTERFromUser()
Definition Common/__init__.py:1
Note
Images supplied to the user are locked for the driver. So if the user does not unlock the images, a permanent acquisition won't be possible as sooner or later all available requests will have been processed by the driver and have been returned to the user.
See also
Step 4.

Step 3: Wait Until The Image Has Been Captured

requestNr = fi.imageRequestWaitFor(timeout_ms)

Step 4: Unlock The Image Buffer Once The Image Has Been Processed:

if fi.isRequestNrValid(requestNr):
# processing, displaying whatever
fi.imageRequestUnlock(requestNr)
Note
ImpactControlCenter acquires images with the help of a capture thread. In order to avoid performance losses, the image buffer is locked during either the live or single image acquisition.

So after displaying the image the unlock is necessary!