92 lines
2.4 KiB
Python
92 lines
2.4 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
# SPDX-FileCopyrightText: 2023 Wojtek Porczyk <woju@hackerspace.pl>
|
|
|
|
import numpy as np
|
|
import picamera2 # pylint: disable=import-error
|
|
|
|
from loguru import logger
|
|
|
|
|
|
def get_char_for_pixel(pixel):
|
|
s = sum(pixel)
|
|
if s > 614:
|
|
return '\u2588'
|
|
if s > 460:
|
|
return '\u2593'
|
|
if s > 307:
|
|
return '\u2592'
|
|
if s > 153:
|
|
return '\u2591'
|
|
return ' '
|
|
|
|
|
|
def print_frame_to_console(frame):
|
|
for row in frame:
|
|
print(''.join(get_char_for_pixel(cell) for cell in row))
|
|
print()
|
|
|
|
|
|
class Camera:
|
|
def __init__(self, size):
|
|
self._exposure = 1.0
|
|
|
|
size = tuple(map(int, size))
|
|
self.camera = picamera2.Picamera2()
|
|
self.camera.preview_configuration.update(
|
|
{
|
|
'main': {
|
|
'format': 'BGR888',
|
|
'size': size,
|
|
},
|
|
'lores': None,
|
|
'raw': None,
|
|
'display': None,
|
|
'encode': None,
|
|
'controls': {
|
|
'ExposureValue': self._exposure,
|
|
},
|
|
}
|
|
)
|
|
self.camera.configure('preview')
|
|
|
|
# ExposureValue vanishes from controls for some reason
|
|
@property
|
|
def exposure(self):
|
|
return self._exposure
|
|
|
|
@exposure.setter
|
|
def exposure(self, value):
|
|
self._exposure = max(-8, min(8, value))
|
|
self.camera.controls.ExposureValue = self._exposure
|
|
|
|
def __enter__(self):
|
|
self.camera.start()
|
|
|
|
def __exit__(self, exc_type, exc_value, exc_tb):
|
|
try:
|
|
self.camera.stop()
|
|
except SystemError: # raised on double stop
|
|
pass
|
|
|
|
def resize(self, size):
|
|
logger.debug(f'resize({size=})')
|
|
|
|
# this is in picamera2.py:
|
|
# if size[0] % 2 or size[1] % 2:
|
|
# raise RuntimeError("width and height should be even")
|
|
x, y = map(int, size)
|
|
x -= x & 1
|
|
y -= y & 1
|
|
self.camera.preview_configuration.update({'size': (x, y)})
|
|
self.camera.switch_mode('preview')
|
|
|
|
def capture_frame(self, rotate=0):
|
|
'''returns (array, metadata)
|
|
|
|
array has shape (height, width, 3)
|
|
'''
|
|
request = self.camera.capture_request()
|
|
frame = request.make_array('main')
|
|
metadata = picamera2.Metadata(request.get_metadata())
|
|
request.release()
|
|
return np.rot90(frame, rotate), metadata
|