image_transfer_raw_as_the_controller_device.py
# Questo lavoro è concesso in licenza MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Tutti i diritti riservati.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Trasferimento immagini - Come dispositivo controllore
#
# Questo script è pensato per essere abbinato a un'altra OpenMV Cam che esegue "image_transfer_raw_as_the_remote_device.py"
#
# Questo script mostra come trasferire il frame buffer da una OpenMV Cam a un'altra.
import image
import omv
import rpc
import csi
import struct
import time
# La libreria RPC sopra indicata è installata sulla tua OpenMV Cam e fornisce diverse classi per
# permettendo alla tua OpenMV Cam di controllare tramite CAN, I2C, SPI, UART o LAN/WLAN.
##############################################################
# Scegli l'interfaccia tramite cui vuoi controllare una OpenMV Cam.
##############################################################
# Rimuovi il commento dalla riga seguente per configurare la tua OpenMV Cam per il controllo via CAN.
#
# * message_id - messaggio CAN da usare per il trasporto dati sul bus can (11 bit).
# * bit_rate - velocità di trasmissione (bit rate) CAN.
# * sample_point - rapporto Tseg1/Tseg2. Tipicamente 75%. (50.0, 62.5, 75.0, 87.5, ecc.)
#
# NOTA: gli id dei messaggi e i bit rate can di master e slave devono corrispondere. Collega il can high del master allo
# can high dello slave e il can low del master al can low dello slave. Il bus can deve essere terminato con 120 ohm.
#
# interface = rpc.rpc_can_master(message_id=0x7FF, bit_rate=1000000, sample_point=75.0)
# Rimuovi il commento dalla riga seguente per configurare la tua OpenMV Cam per il controllo via I2C.
#
# * slave_addr - indirizzo I2C.
# * rate - frequenza di clock del bus I2C.
#
# NOTA: gli indirizzi di master e slave devono corrispondere. Collega lo scl del master allo scl dello slave e lo sda del master
# allo sda dello slave. Devi usare pull-up esterni. Infine, entrambi i dispositivi devono condividere una massa comune.
#
# interface = rpc.rpc_i2c_master(slave_addr=0x12, rate=1000000)
# Rimuovi il commento dalla riga seguente per configurare la tua OpenMV Cam per il controllo via SPI.
#
# * cs_pin - pin di selezione dello slave (Slave Select).
# * freq - frequenza di clock del bus SPI
# * clk_polarity - livello del clock a riposo (0 o 1).
# * clk_phase - campiona i dati sul primo (0) o secondo fronte (1) del clock.
#
# NOTA: le impostazioni di master e slave devono corrispondere. Collega CS, SCLK, MOSI, MISO a CS, SCLK, MOSI, MISO.
# Infine, entrambi i dispositivi devono condividere una massa comune.
#
interface = rpc.rpc_spi_master(cs_pin="P3", freq=20000000, clk_polarity=1, clk_phase=0)
# Rimuovi il commento dalla riga seguente per configurare la tua OpenMV Cam per il controllo via UART.
#
# * baudrate - velocità di trasmissione seriale (baudrate).
#
# NOTA: i baudrate di master e slave devono corrispondere. Collega il tx del master all'rx dello slave e l'rx del master
# al tx dello slave. Infine, entrambi i dispositivi devono condividere una massa comune.
#
# interface = rpc.rpc_uart_master(baudrate=7500000)
##############################################################
# Gestori dei callback
##############################################################
def get_frame_buffer_call_back(pixformat, framesize, cutthrough, silent):
if not silent:
print("Getting Remote Frame...")
result = interface.call(
"raw_image_snapshot", struct.pack("<II", pixformat, framesize)
)
if result is not None:
w, h, pixformat, size = struct.unpack("<IIII", result)
img = image.Image(w, h, pixformat, copy_to_fb=True) # Alloca un frame buffer azzerato.
img_ba = img.bytearray()
if cutthrough:
# Trasferimento dati rapido cutthrough senza controllo errori.
# Prima di avviare il trasferimento dati cutthrough dobbiamo sincronizzare sia il master che lo
# slave. Al termine, entrambi i dispositivi sono sincronizzati.
result = interface.call("raw_image_read")
if result is not None:
# GET BYTES DEVE ESSERE ESEGUITO SUBITO DOPO CON POCHISSIMO RITARDO.
# Legge tutti i dati dell'immagine in un unico trasferimento molto grande.
interface.get_bytes(img_ba, 5000) # timeout
else:
# Trasferimento dati più lento con controllo errori.
# Trasferisce blocchi da 32/8 KB.
chunk_size = (1 << 15) if omv.board_type() == "H7" else (1 << 13)
if not silent:
print("Reading %d bytes..." % size)
for i in range(0, size, chunk_size):
ok = False
for j in range(3): # Prova fino a 3 volte.
result = interface.call(
"raw_image_read", struct.pack("<II", i, chunk_size)
)
if result is not None:
img_ba[i:i + chunk_size] = result # Scrive i dati dell'immagine.
if not silent:
print("%.2f%%" % ((i * 100) / size))
ok = True
break
if not silent:
print("Retrying... %d/2" % (j + 1))
if not ok:
if not silent:
print("Error!")
return None
return img
else:
if not silent:
print("Failed to get Remote Frame!")
return None
clock = time.clock()
while True:
clock.tick()
# Puoi cambiare il pixformat e il framesize dell'immagine trasferita dal dispositivo remoto
# modificando gli argomenti seguenti.
#
# Quando cutthrough è False l'immagine verrà trasferita tramite la libreria RPC con protezione CRC e
# ritentativi su tutti i dati spostati. Per un trasferimento dati più rapido imposta cutthrough su True in modo che
# get_bytes() e put_bytes() vengano chiamate al termine di una chiamata RPC per trasferire i dati
# più rapidamente da un buffer immagine a un altro. Nota: questo funziona perché una volta che una chiamata RPC
# si completa con successo, sia il dispositivo master che quello slave sono completamente sincronizzati.
#
img = get_frame_buffer_call_back(
csi.RGB565, csi.QQVGA, cutthrough=True, silent=True
)
if img is not None:
pass # Puoi elaborare l'immagine qui.
print(clock.fps())