112 lines
3.9 KiB
Python
Executable File
112 lines
3.9 KiB
Python
Executable File
import numpy
|
|
import time
|
|
|
|
|
|
|
|
class SimulatedCamera():
|
|
"""
|
|
Camera simulation for debugging purposes.
|
|
"""
|
|
|
|
def __init__(self, camera_config = None, size_x=1280, size_y=960, number_of_dead_pixels=100, noise=0.1,
|
|
beam_size_x=100, beam_size_y=20):
|
|
"""
|
|
Initialize the camera simulation.
|
|
:param size_x: Image width.
|
|
:param size_y: Image height.
|
|
:param number_of_dead_pixels: Number of simulated dead pixels.
|
|
:param noise: How much noise to introduce.
|
|
:param beam_size_x: Beam width.
|
|
:param beam_size_y: Beam height.
|
|
"""
|
|
self.camera_config = camera_config
|
|
self.channel_image = None
|
|
self.width_raw = size_x
|
|
self.height_raw = size_y
|
|
self.noise = noise # double {0,1} noise amplification factor
|
|
self.dead_pixels = self._generate_dead_pixels(number_of_dead_pixels)
|
|
self.beam_size_x = beam_size_x
|
|
self.beam_size_y = beam_size_y
|
|
|
|
def _generate_dead_pixels(self, number_of_dead_pixel):
|
|
dead_pixels = numpy.zeros((self.height_raw, self.width_raw))
|
|
|
|
for _ in range(number_of_dead_pixel):
|
|
x = numpy.random.randint(0, self.height_raw)
|
|
y = numpy.random.randint(0, self.width_raw)
|
|
dead_pixels[x, y] = 1
|
|
|
|
return dead_pixels
|
|
|
|
def get_image(self, raw=False):
|
|
"""
|
|
Get the simulated image.
|
|
:param raw: If true, return a simulated camera wihtout the beam (just noise).
|
|
:return: Camera image.
|
|
"""
|
|
|
|
if raw:
|
|
image = numpy.zeros((self.size_y, self.size_x))
|
|
else:
|
|
beam_x = numpy.linspace(-self.beam_size_x + numpy.random.rand(),
|
|
self.beam_size_x + numpy.random.rand(),
|
|
self.height_raw)
|
|
beam_y = numpy.linspace(-self.beam_size_y + numpy.random.rand(),
|
|
self.beam_size_y + numpy.random.rand(),
|
|
self.width_raw)
|
|
x, y = numpy.meshgrid(beam_y, beam_x)
|
|
image = numpy.exp(-(x ** 2 + y ** 2))
|
|
|
|
# Add some noise
|
|
if self.noise:
|
|
image += numpy.random.random((self.height_raw, self.width_raw)) * self.noise
|
|
|
|
# Add dead pixels
|
|
image += self.dead_pixels
|
|
|
|
image.clip(0, 0.9, out=image)
|
|
image *= (numpy.power(2, 16) - 1)
|
|
|
|
return self._get_image(image, raw=raw)
|
|
|
|
def _get_image(self, value, raw=False):
|
|
|
|
if value is None:
|
|
return None
|
|
|
|
# Convert type - we are using f because of better performance
|
|
# floats (32bit-ones) are way faster to calculate than 16 bit ints, actually even faster than native
|
|
# int type (32/64uint) since we can leverage SIMD instructions (SSE/SSE2 on Intels).
|
|
value = value.astype('u2').astype(numpy.float32)
|
|
|
|
# Shape image
|
|
value = value[:(self.width_raw * self.height_raw)].reshape((self.height_raw, self.width_raw))
|
|
|
|
# Return raw image without any corrections
|
|
if raw:
|
|
return value
|
|
|
|
if self.camera_config is not None:
|
|
# Correct image
|
|
if self.camera_config.parameters["mirror_x"]:
|
|
value = numpy.fliplr(value)
|
|
|
|
if self.camera_config.parameters["mirror_y"]:
|
|
value = numpy.flipud(value)
|
|
value = numpy.rot90(value, self.camera_config.parameters["rotate"])
|
|
|
|
return numpy.ascontiguousarray(value)
|
|
|
|
|
|
|
|
simulated_camera = None
|
|
def new_simulated_camera( camera_config = None, size_x=1280, size_y=960, number_of_dead_pixels=100, noise=0.1, beam_size_x=100, beam_size_y=20):
|
|
global simulated_camera
|
|
simulated_camera = SimulatedCamera(camera_config, size_x, size_y, number_of_dead_pixels, noise,beam_size_x, beam_size_y)
|
|
return simulated_camera
|
|
|
|
|
|
def get_image(raw=False):
|
|
return simulated_camera.get_image(raw)
|
|
|