Files
dev/script/cpython/SimulatedCamera.py
2018-01-19 10:56:53 +01:00

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)