Skip to content

Commit

Permalink
Merge pull request #41 from ifm/imagesuncompressed
Browse files Browse the repository at this point in the history
Imagesuncompressed
  • Loading branch information
Galoshi authored May 3, 2024
2 parents 7ca5f7e + f224783 commit 97236c5
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 23 deletions.
40 changes: 35 additions & 5 deletions examples/create_rawimage_application.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
try:
from o2x5xx import O2x5xxRPCDevice
from o2x5xx import O2x5xxRPCDevice, O2x5xxDeviceV2
except ModuleNotFoundError:
from source.rpc.client import O2x5xxRPCDevice
from source.device.client import O2x5xxDeviceV2
import sys
import matplotlib.pyplot as plt
import matplotlib.image

if __name__ == '__main__':
if len(sys.argv) > 1:
Expand All @@ -22,11 +25,11 @@

with device.editProxy.editApplication(app_index=newApplicationIndex):
print("Starting editing application with index: " + str(newApplicationIndex))
device.application.Name = "My new application"
device.application.Name = "Application Uncompressed Image"
print("Changed name of application: " + device.application.Name)
device.application.Description = "My new description"
device.application.Description = "Application for retrieving an uncompressed image"
print("Changed description of application: " + device.application.Description)
device.application.TriggerMode = 2 # continuous trigger mode
device.application.TriggerMode = 2 # process interface trigger mode
print("Trigger Mode {} set".format(device.application.TriggerMode))

# Setup of image001
Expand All @@ -39,7 +42,7 @@
device.imager.startCalculateAutofocus()
print("End of calculating autofocus with recommended value(s): " + str(
device.imager.getAutofocusDistances()))
device.imager.Name = "My new image001"
device.imager.Name = "Uncompressed Image"
print("Changed name of image001: " + device.imager.Name)

# Switch to uncompressed images
Expand All @@ -50,3 +53,30 @@
print("Saving parameter consistent to memory for application: " + device.application.Name)
device.switchApplication(applicationIndex=newApplicationIndex)
print("Application with new index {} now active".format(newApplicationIndex))

# create device
print("Create O2x5xx V2 device.")
with O2x5xxDeviceV2(address) as device:
# Save 10 uncompressed images
for i in range(10):
print("Executing trigger.")
# device.pcic.execute_asynchronous_trigger()
trigger_result = device.pcic.execute_asynchronous_trigger()
if trigger_result != '*':
print(trigger_result)
sys.exit("Trigger failed!")
else:
_ = device.pcic.read_next_answer()

print("Requesting last image...")
result = device.pcic.request_last_image_taken_deserialized(image_id=2, datatype="ndarray")
if result == "!":
print(result)
sys.exit("Request for last image failed!")
image_uncompressed = result[0][1]

# Uncomment if you want to see the image
# plt.imshow(image_uncompressed, cmap='gray')
# plt.show()
# matplotlib.image.imsave(fname='image_uncompressed_{}.png'.format(str(i)),
# arr=image_uncompressed, cmap='gray')
2 changes: 1 addition & 1 deletion examples/image_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
address = '192.168.0.69'

# create grabber
image_client = ImageClient(address, 50010)
image_client = ImageClient(address=address, port=50010, timeout=None)

# create figures
figs = [image_client.make_figure(i) for i in range(image_client.number_images)]
Expand Down
29 changes: 17 additions & 12 deletions source/device/image_client.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
from __future__ import (absolute_import, division, print_function)
from builtins import *
from ..pcic.client import O2x5xxPCICDevice
from ..static.formats import serialization_format
from ..static.configs import images_config
import binascii
from source.pcic import O2x5xxPCICDevice
from source.static.formats import serialization_format, ChunkType
from source.static.configs import images_config
import struct
import io
import enum
import array
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np

class ChunkType(enum.IntEnum):
MONOCHROME_2D_8BIT = 251
JPEG_IMAGE = 260

SOCKET_TIMEOUT = 10


class ImageClient(O2x5xxPCICDevice):
def __init__(self, address, port):
super(ImageClient, self).__init__(address, port)
def __init__(self, address, port, timeout=SOCKET_TIMEOUT):
super(ImageClient, self).__init__(address=address, port=port, timeout=timeout)

# disable all result output
self.turn_process_interface_output_on_or_off(0)
Expand Down Expand Up @@ -89,10 +86,18 @@ def _deserialize_image_chunk(data):
# append image
image_hex = data[header['HEADER_SIZE']:header['CHUNK_SIZE']]
chunk_type = int(header['CHUNK_TYPE'])
# check end decode image depending on chunk type
if chunk_type == ChunkType.JPEG_IMAGE:
# Check that we have received chunk type JPEG_IMAGE
# Convert jpeg data to image data
image = mpimg.imread(io.BytesIO(image_hex), format='jpg')
results[counter].append(image)
elif chunk_type == ChunkType.MONOCHROME_2D_8BIT:
image = np.reshape(array.array('B', image_hex), (header['IMAGE_HEIGHT'], header['IMAGE_WIDTH']))
# Check that we have received chunk type MONOCHROME_2D_8BIT
# Read pixel data and reshape to width/height
image = np.frombuffer(image_hex, dtype=np.uint8) \
.reshape((header["IMAGE_HEIGHT"], header["IMAGE_WIDTH"]))
results[counter].append(image)
else:
image = None
print("Unknown image chunk type", header['CHUNK_TYPE'])
Expand Down
26 changes: 21 additions & 5 deletions source/pcic/client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from ..static.formats import error_codes, serialization_format
from ..static.formats import error_codes, serialization_format, ChunkType
import matplotlib.image as mpimg
import numpy as np
import binascii
import socket
import struct
Expand Down Expand Up @@ -361,7 +362,8 @@ def request_last_image_taken(self, image_id=1):
- <length> (int) char string with exactly 9 digits as decimal number for the image data size in bytes.
- <image data> (bytearray) image data / result data. The data is encapsulated in an image chunk.
- ! No image available
| Wrong ID
| Wrong ID (Applications which transfer uncompressed images are
not able to transfer images as JPG and vise versa)
- ? Invalid command length
"""
if str(image_id).isnumeric():
Expand All @@ -385,11 +387,14 @@ def request_last_image_taken_deserialized(self, image_id=1, datatype='ndarray'):
- <image data> image data / result data. The data is encapsulated
in an image chunk if bytes as datatype is selected.
- ! No image available
| Wrong ID
| Wrong ID (Applications which transfer uncompressed images are
not able to transfer images as JPG and vise versa)
- ? Invalid command length
"""
results = {}
result = self.request_last_image_taken(image_id)
if str(result)[2:3] == "!":
return "!"
length = int(result[:9].decode())
data = binascii.unhexlify(result[9:].hex())
counter = 0
Expand All @@ -406,9 +411,20 @@ def request_last_image_taken_deserialized(self, image_id=1, datatype='ndarray'):
results.setdefault(counter, []).append(header)
# append image
image_hex = data[header['HEADER_SIZE']:header['CHUNK_SIZE']]
chunk_type = int(header['CHUNK_TYPE'])
# check end decode image depending on chunk type
if datatype == 'ndarray':
image = mpimg.imread(io.BytesIO(image_hex), format='jpg')
results[counter].append(image)
if chunk_type == ChunkType.JPEG_IMAGE:
# Check that we have received chunk type JPEG_IMAGE
# Convert jpeg data to image data
image = mpimg.imread(io.BytesIO(image_hex), format='jpg')
results[counter].append(image)
elif chunk_type == ChunkType.MONOCHROME_2D_8BIT:
# Check that we have received chunk type MONOCHROME_2D_8BIT
# Read pixel data and reshape to width/height
image = np.frombuffer(image_hex, dtype=np.uint8)\
.reshape((header["IMAGE_HEIGHT"], header["IMAGE_WIDTH"]))
results[counter].append(image)
elif datatype == 'bytes':
results[counter].append(image_hex)
else:
Expand Down
7 changes: 7 additions & 0 deletions source/static/formats.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import enum

# These are the error codes with the corresponding error message
error_codes = {
000000000: "No error detected",
Expand Down Expand Up @@ -78,3 +80,8 @@
2: "external illumination shall be used",
3: "internal and external illumination shall be used together"
}


class ChunkType(enum.IntEnum):
MONOCHROME_2D_8BIT = 251
JPEG_IMAGE = 260

0 comments on commit 97236c5

Please sign in to comment.