Skip to main content

ids_peak_afl - A library for auto features

Project description

ids_peak_afl provides python bindings for the IDS peak AFL. It exposes all the functionality of the peak AFL and requires at least the drivers and GenICam transport layers to be installed, which are included in the IDS peak SDK.

Benefit from many Python advantages, for example the interactive programming of your IDS camera. Write and test small code snippets without the complex setup of a programming IDE including a toolchain. This package is ideal for prototyping IDS camera applications for all supported peak AFL platforms (Windows, Linux, Linux Embedded).

Installation

$ pip install ids_peak_afl

Quickstart

This example shows how to open a device, start image acquisition and use the ids_peak_afl package for triggering a host-sided automatic adjustment of image brightness (requires version >=1.2).

NOTE: For the sake of simplicity, most of the error checking has been omitted in this example.

from ids_peak import ids_peak, ids_peak_ipl_extension
from ids_peak_ipl import ids_peak_ipl
from ids_peak_afl import ids_peak_afl

import time


class ProcessingCallback(
        ids_peak_afl.ProcessingCallback):
    def callback(self, process_data) -> None:
        print("ProcessingCallback: "
              f"Controller Status {process_data.controller_status} "
              f"Controller Type {process_data.controller_type}")
        if isinstance(process_data,
                      ids_peak_afl.peak_afl_process_data_brightness):
            print("Brightness")
            print(f"\tMean: {process_data.mean}")
            print(f"\tController Component: {process_data.controller_component}")
        elif isinstance(process_data,
                        ids_peak_afl.peak_afl_process_data_whitebalance):
            print("Whitebalance")
            print("\tMean (R/G/B): "
                  f"{process_data.mean_r}/{process_data.mean_g}/"
                  f"{process_data.mean_b}")
            print("\tController Component: "
                  f"{process_data.controller_component}")
        elif isinstance(process_data,
                        ids_peak_afl.peak_afl_process_data_focus):
            print("Focus")
            print(f"\tFocus {process_data.focus_value} "
                  f"Sharpness {process_data.sharpness_value}")
        else:
            raise RuntimeError("Unknown process_data type!")


class FinishedCallback(
        ids_peak_afl.FinishedCallback):
    def callback(self) -> None:
        print("ControllerFinishedCallback!")


class ComponentExposureFinishedCallback(
        ids_peak_afl.ComponentExposureFinishedCallback):
    def callback(self) -> None:
        print("ExposureFinishedCallback!")


class ComponentHostGainFinishedCallback(
        ids_peak_afl.ComponentHostGainFinishedCallback):
    def callback(self) -> None:
        print("HostGainFinishedCallback!")


def main():
    # Initialize library calls should be matched by a corresponding
    # Exit or close call
    ids_peak.Library.Initialize()
    ids_peak_afl.Library.Init()

    # Create a DeviceManager object
    device_manager = ids_peak.DeviceManager.Instance()

    try:
        # Update the DeviceManager
        device_manager.Update()

        # Exit program if no device was found
        if device_manager.Devices().empty():
            print("No device found. Exiting Program.")
            return -1

        # Open the first device
        device = device_manager.Devices()[0].OpenDevice(
            ids_peak.DeviceAccessType_Control)

        print(f"Device: {device.SerialNumber()} -> {device.DisplayName()}")

        # Nodemap for accessing GenICam nodes
        remote_nodemap = device.RemoteDevice().NodeMaps()[0]

        # Autofeature manager, which can have multiple controllers
        manager = ids_peak_afl.Manager(remote_nodemap)
        # Create controller types
        controller_brightness = manager.CreateController(
            ids_peak_afl.PEAK_AFL_CONTROLLER_TYPE_BRIGHTNESS)
        controller_focus = manager.CreateController(
            ids_peak_afl.PEAK_AFL_CONTROLLER_TYPE_AUTOFOCUS)
        controller_whitebalance = manager.CreateController(
            ids_peak_afl.PEAK_AFL_CONTROLLER_TYPE_WHITE_BALANCE)

        print(f"Controller Status: {controller_brightness.Status()}")
        print(f"Controller Type: {controller_brightness.Type()}")

        # Load default camera settings
        remote_nodemap.FindNode("UserSetSelector").SetCurrentEntry("Default")
        remote_nodemap.FindNode("UserSetLoad").Execute()
        remote_nodemap.FindNode("UserSetLoad").WaitUntilDone()

        # Activate the controllers
        # NOTE: mode is reset to off automatically after the operation finishes
        # when using PEAK_AFL_CONTROLLER_AUTOMODE_ONCE
        controller_focus.SetMode(
                ids_peak_afl.PEAK_AFL_CONTROLLER_AUTOMODE_ONCE)
        controller_whitebalance.SetMode(
                ids_peak_afl.PEAK_AFL_CONTROLLER_AUTOMODE_ONCE)

        # Auto brightness mode is split up in multiple components
        # so you can't use the regular controller.SetMode etc.
        controller_brightness.BrightnessComponentSetMode(
            ids_peak_afl.PEAK_AFL_CONTROLLER_BRIGHTNESS_COMPONENT_EXPOSURE,
            ids_peak_afl.PEAK_AFL_CONTROLLER_AUTOMODE_ONCE,
        )
        controller_brightness.BrightnessComponentSetMode(
            ids_peak_afl.PEAK_AFL_CONTROLLER_BRIGHTNESS_COMPONENT_HOST_GAIN,
            ids_peak_afl.PEAK_AFL_CONTROLLER_AUTOMODE_ONCE,
        )

        # Register callbacks
        # NOTE: these have to be assigned, otherwise they get destructed
        # and the callback gets removed
        finished_brightness = FinishedCallback(controller_brightness)
        exposure_finished = ComponentExposureFinishedCallback(controller_brightness)
        gain_finished = ComponentHostGainFinishedCallback(controller_brightness)
        processing_brightness = ProcessingCallback(controller_brightness)

        finished_focus = FinishedCallback(controller_focus)
        processing_focus = ProcessingCallback(controller_focus)

        finished_whitebalance = FinishedCallback(controller_whitebalance)
        processing_whitebalance = ProcessingCallback(controller_whitebalance)

        # Open first data stream
        data_stream = device.DataStreams()[0].OpenDataStream()
        # Buffer size
        payload_size = remote_nodemap.FindNode("PayloadSize").Value()

        # Minimum number of required buffers
        buffer_count_max = data_stream.NumBuffersAnnouncedMinRequired()

        # Allocate buffers and add them to the pool
        for buffer_count in range(buffer_count_max):
            # Let the TL allocate the buffers
            buffer = data_stream.AllocAndAnnounceBuffer(payload_size)
            # Put the buffer in the pool
            data_stream.QueueBuffer(buffer)

        # Lock writeable nodes during acquisition
        remote_nodemap.FindNode("TLParamsLocked").SetValue(1)

        print("Starting acquisition...")
        data_stream.StartAcquisition()
        remote_nodemap.FindNode("AcquisitionStart").Execute()
        remote_nodemap.FindNode("AcquisitionStart").WaitUntilDone()

        print("Getting 100 images...")
        # Process 100 images
        for _ in range(100):
            try:
                # Wait for finished/filled buffer event
                buffer = data_stream.WaitForFinishedBuffer(1000)
                img = ids_peak_ipl_extension.BufferToImage(buffer)

                # NOTE: If performance is a concern, then `ids_peak_ipl.ImageConverter`
                #       should be preferred.
                img = img.ConvertTo(ids_peak_ipl.PixelFormatName_RGB8)
                # Put the buffer back in the pool, so it can be filled again
                # NOTE: `ConvertTo` will make a copy, so it is fine to queue
                #       the buffer immediately after.
                data_stream.QueueBuffer(buffer)

                # Process the image in the autofeature manager, which will
                # apply all the actions of associated controllers.
                # Skip processing if another image is still being processed.
                isProcessing = manager.Status()
                if not isProcessing:
                    manager.Process(img)
            except Exception as e:
                print(f"Exception: {e}")

        print("Stopping acquisition...")
        remote_nodemap.FindNode("AcquisitionStop").Execute()
        remote_nodemap.FindNode("AcquisitionStop").WaitUntilDone()

        data_stream.StopAcquisition(ids_peak.AcquisitionStopMode_Default)

        # In case another thread is waiting on WaitForFinishedBuffer
        # you can interrupt it using:
        # data_stream.KillWait()

        # Remove buffers from any associated queue
        data_stream.Flush(ids_peak.DataStreamFlushMode_DiscardAll)

        for buffer in data_stream.AnnouncedBuffers():
            # Remove buffer from the transport layer
            data_stream.RevokeBuffer(buffer)

        # Unlock writeable nodes again
        remote_nodemap.FindNode("TLParamsLocked").SetValue(0)

        # Last auto average for the controller working on a mono image
        print(f"LastAutoAverage: {controller_brightness.GetLastAutoAverage()}")
    except Exception as e:
        print(f"EXCEPTION: {e}")
        return -2

    finally:
        ids_peak_afl.Library.Exit()
        ids_peak.Library.Close()


if __name__ == '__main__':
    main()

Documentation

Documentation is available here

Troubleshoot

Windows Runtime DLL Conflict (PyQt / MSVCP140.dll)

Problem

On Windows, PyQt ships with its own copies of Microsoft runtime libraries, such as:

msvcp140.dll
vcruntime140.dll

These DLLs are usually older than the ones installed by the official Microsoft Visual C++ Redistributable (2015–2022).

IDS peak AFL is compiled with a newer MSVC toolset, Windows may load the outdated DLLs from the PyQt package first. This can cause runtime errors such as:

OSError: [WinError 1114] A dynamic link library (DLL) initialization routine failed

Workaround in Python

To ensure IDS peak AFL uses the newer system runtime instead of PyQt’s local DLLs, you can import IDS peak AFL before PyQt.

from ids_peak_afl import ids_peak_afl
from PyQt5 import QtCore  # or PyQt6 / etc.

## Continue with the rest of your program

This ensures that your extension module links against the newer runtime DLLs from C:\Windows\System32, before PyQt’s versions are loaded.


Workaround in PyQt Installation

If you can modify the PyQt installation, you can safely rename or remove the bundled runtime DLLs in the PyQt package:

<python>\Lib\site-packages\PyQt<version>\Qt\bin\msvcp140.dll
<python>\Lib\site-packages\PyQt<version>\Qt\bin\vcruntime140.dll

Rename them to:

msvcp140.dll.old
vcruntime140.dll.old

Windows will then automatically use the system-wide (and up-to-date) runtime libraries from the Visual C++ Redistributable.

License

LICENSE TERMS

IDS SOFTWARE SUITE AND IDS peak

Preamble

IDS Imaging Development Systems GmbH ("Licensor")
has developed an additional Software Suite ("Software")
for the purpose of operating and programming
of all purchaseable cameras of the Licensor ("IDS cameras")
and integrating it in other products which use IDS
cameras, from which the customer ("Licensee", Licensor
and Licensee hereafter also referred to as a "Party" or
the "Parties") intends to acquire certain rights of use. For
this purpose, the Parties agree on the following License
Terms.

1. Licensed Software

1.1. Licensor will license the Software as described on
the Licensor's website at www.ids.imaging.com, its
subdomains and at www.ids-imaging.us. The Software contains,
inter alia, executable programs, libraries and header file(s),
example source code for using the libraries,
and the respective documentation.

1.2. The Software contains Open Source components,
meaning components which are licensed under terms
that fulfil the criteria of the Open Source Definition of
the Open Source Initiative as of 2007 (the definition
is available at https://opensource.org/osd). A list of
such Open Source components and the respective
applicable licenses is part of the Software and can
be reviewed after the installation.

1.3. Software is not offered to consumers within the meaning
of section 13 of the German Civil Code (BGB).

2. Rights of Use

2.1. As of the Effective Date as defined in clause 5 Licensor
grants to Licensee a non-exclusive, non-transferable
worldwide right to use, distribute, duplicate or
reproduce and integrate part or all of the Software
in his own products only if they operate with IDS cameras
and to distribute the Software in connection
with such products Moreover Licensee shall have
the right to

2.1.1. Integrate or cause to be integrated the Software
into Licensee's products only if they operate with
IDS cameras and to duplicate or reproduce (or
make duplicates or reproductions) and distribute
these products to end users or third parties (in-
cluding retailers, e-tailers, wholesalers or Original
Equipment Manufacturers, etc.). For the avoidance of doubt,
Licensee shall not be entitled to sublicense the Software
unless otherwise agreed in the following clause 2.1.2.

2.1.2. Licensee shall be entitled to sublicense the rights
granted herein only to his subcontractors solely for
work directly related to Licensee's products and
updates. Other than that, Licensee shall not be
entitled to sublicense the Software.

2.2. The Parties agree that notwithstanding the above
grant of rights of use, Licensor will continue to hold
any and all intellectual property rights in the Software.

2.3. Licensee is not entitled to

2.3.1. sell, rent or lend die Software as a stand-alone to others,

2.3.2. to edit, arrange, translate or decompile the Software,

2.3.3. to use the Software with or integrate the Software
into a camera that was or is not offered by the Licensor
or that is self-produced by the Licensee,

2.3.4. to use Software or parts thereof to create an own
comparable control software or to integrate the
Software or parts thereof into own comparable
control software,

2.3.5. to assign his rights and obligations resulting from
these License terms to third parties without the
prior written consent of Licensor, unless any of the
above is explicitly allowed by statutory law.

2.4. Any software, apart from the python interface and Open Source
software, is offered in object code only. Licensee is not entitled
to access the source code.

3. Warranty

3.1. Licensor accepts warranty for the Software only as
explicitly described in this clause 3. Any further warranty is excluded.

3.2. Licensor is not aware of any patent infringements
related to the Software and undertakes to inform
Licensee without undue delay, should he be made
aware of any such patent infringement, and in such
case, to undertake reasonable measures to remedy
such infringement. Other than that, Licensor does
not assume any warranty with regard to third party
patent rights.

3.3. Licensor warrants that the Software are free from
defects which cause the Software not to operate in
accordance with the functionality as described on
the product website at the Effective Date of these
License Terms. Licensee undertakes to report any
defects discovered to Licensor without undue delay.

4. Download

4.1. The Software will be delivered by Licensor to the Licensee
via download from the Licensor's website.

4.2. Additionally the python interface can be obtained by the Licensee
from the public Python Package Index (PyPI; https://pypi.org/)

5. Effective Date, Term	and	Termination

5.1. These License Terms come into force upon successful download of
the Software not later than the commencement of use by the Licensee.

5.2. These License Terms are not limited in the term.

5.3. The Licensor may, at its choice and without prejudice to
any other legal right or remedy that it might otherwise have,
terminate these License Terms for cause with immediate effect
by written notice to the Licensee upon the happening of any one
of the following events:

5.3.1. any failure by the Licensee to perform one or more
of its obligations hereunder or any other breach
hereof which shall not have been cured within sixty (60) days
after receipt of written notice specifying the nature
of such failure or breach;

5.3.2. the Licensee makes a general assignment for the
benefit of creditors or becomes insolvent or enters
into liquidation or files bankruptcy;

5.3.3. a receiver, trustee in bankruptcy or similar officer
of all or substantially all of the property of the Licensee
is appointed and not removed within ninety (90) days.

5.4. Termination shall not excuse the parties from any
obligations incurred hereunder prior to the date of termination.

5.5. Termination of the License Terms for any reason will
not affect the rights of any end user to use the Software
under any license granted in accordance with this License Terms.

5.6. Furthermore, in the event of termination, products
already manufactured or in the distribution chan-
nels may still be distributed and sold. This is not applicable
for Licensee's products offered to its customers via download
or any other non-physical form. Such products must not be distributed
and sold after the termination of these License Terms. For the
avoidance of doubt: Apart from the regulations in
this clause 5.5, no new products containing the Software may be produced
and the Software may not be used anymore by the Licensee.

5.7. Within ten (10) business days from the termination
of these License Terms, Licensee will delete or destroy
all versions of the Software. Upon Licensor's request,
Licensee must attest in writing that Software
has been deleted or destroyed.

6. Liability

6.1. Licensor's liability for intent, gross negligence and in
the event of personal injury, bodily harm or damage
to death, and if a claim according to the law on
product liability ("Produkthaftungsgesetz") is affected
is subject to the respective applicable legal regulations.

6.2. Other than that, Licensor's liability and that of his
agents, employees and bodies shall be excluded.

6.3. The Licensor is not liable for the loss of data and software.

6.4. The restrictions of liability in this clause 6 shall apply
to Licensor himself and his agents, employees and bodies.

7. Miscellaneous

7.1. These License Terms constitute the complete understanding
between the parties regarding the subject matter.
No oral or subsidiary agreements have been concluded
or entered into. All previous agreements between the Parties
with regard to the subject matter are replaced by these License Terms.
Amendments, supplements and notices of termination of these
License Terms must be made in writing.
The rescission of these License Terms or an alteration of
the requirement of the written form must also
be made in writing. This requirement also applies to
any changes of this provision.

7.2. If individual provisions of these License Terms are
ineffective, then this shall not affect the effectiveness
of the remaining terms. However, the ineffective provision
shall be deemed to be replaced by an effective provision,
which is as close as possible to the commercially desired purpose
of the ineffective provision; the same shall apply in the case of a gap.

7.3. These License Terms are presented in two languages
(German and English). In case of discrepancies
or doubt with regard to their interpretation, the German version
shall prevail.

7.4. The legal relations between the parties regarding
the subject matter shall be governed and construed
by the laws of the Federal Republic of Germany excluding
the UN law on the sale of goods (CISG) and
German Private International Law.

7.5. In the event of any dispute or controversy arising
out of these License Terms or any breach thereof, Licensor and Licensee
shall make a good faith effort to settle the dispute through negotiation.
If the dispute or controversy cannot be solved amicably,
place of jurisdiction for all disputes arising from or in connection
with the subject matter is Berlin. In addition,
Licensor can bring an action against Licensee at the
general place of jurisdiction of Licensee.

Last revised: June 21, 2023

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ids_peak_afl-2.0.1.0.4-cp310-abi3-win_amd64.whl (906.2 kB view details)

Uploaded CPython 3.10+Windows x86-64

ids_peak_afl-2.0.1.0.4-cp310-abi3-manylinux_2_24_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.24+ x86-64

ids_peak_afl-2.0.1.0.4-cp310-abi3-manylinux_2_24_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.24+ ARM64

File details

Details for the file ids_peak_afl-2.0.1.0.4-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for ids_peak_afl-2.0.1.0.4-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 146b8c5d1ad3eefc1e137dce9aeade1563f7192e3a8ac3046e7f06ef40d2b83f
MD5 af3743ce238b1e10dc90ca05efa46d12
BLAKE2b-256 cfd68be49fc16eed682ef7d2c4427c69f00b735231603f656b43723d53685027

See more details on using hashes here.

File details

Details for the file ids_peak_afl-2.0.1.0.4-cp310-abi3-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for ids_peak_afl-2.0.1.0.4-cp310-abi3-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 33fafcbd6d0f45498bcf16a8d491129815bacb51aaf2fd59b37606d84c3199aa
MD5 de92cf7455da70ecd70d463765283f39
BLAKE2b-256 4fd85fe109e22e2f266e8bd54305882f5ab65f6756101db396a45a4214c31285

See more details on using hashes here.

File details

Details for the file ids_peak_afl-2.0.1.0.4-cp310-abi3-manylinux_2_24_aarch64.whl.

File metadata

File hashes

Hashes for ids_peak_afl-2.0.1.0.4-cp310-abi3-manylinux_2_24_aarch64.whl
Algorithm Hash digest
SHA256 92d42839c6b832311adfe19fa7e2d49e4b8dff60dcb5889775dcda52d387fa9f
MD5 4ab59f46751c985909dd3b2c0dba3c6c
BLAKE2b-256 67b952c62cf0013e0a56d40238f34a796b3663e44b9dbe6cf40526bef03254ec

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page