image_transfer_raw_as_the_controller_device.py
# Este trabalho está licenciado sob a licença MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Todos os direitos reservados.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Transferência de imagem - Como o dispositivo controlador
#
# Este script foi feito para ser combinado com outra OpenMV Cam rodando "image_transfer_raw_as_the_remote_device.py"
#
# Este script mostra como transferir o frame buffer de uma OpenMV Cam para outra.
import image
import omv
import rpc
import csi
import struct
import time
# A biblioteca RPC acima está instalada na sua OpenMV Cam e fornece diversas classes para
# permitindo que sua OpenMV Cam controle via CAN, I2C, SPI, UART ou LAN/WLAN.
##############################################################
# Escolha a interface pela qual deseja controlar uma OpenMV Cam.
##############################################################
# Descomente a linha abaixo para configurar sua OpenMV Cam para controlar via CAN.
#
# * message_id - Mensagem CAN usada para transporte de dados no barramento CAN (11 bits).
# * bit_rate - Taxa de bits do CAN.
# * sample_point - Proporção Tseg1/Tseg2. Tipicamente 75%. (50.0, 62.5, 75.0, 87.5, etc.)
#
# NOTA: Os message ids e as taxas de bits do CAN do mestre e do escravo devem coincidir. Conecte o can high do mestre ao
# can high do escravo e o can low do mestre ao can low do escravo. O barramento CAN deve ser terminado com 120 ohms.
#
# interface = rpc.rpc_can_master(message_id=0x7FF, bit_rate=1000000, sample_point=75.0)
# Descomente a linha abaixo para configurar sua OpenMV Cam para controlar via I2C.
#
# * slave_addr - Endereço I2C.
# * rate - Frequência do clock do barramento I2C.
#
# NOTA: Os endereços do mestre e do escravo devem coincidir. Conecte o scl do mestre ao scl do escravo e o sda do mestre
# ao sda do escravo. É necessário usar pull-ups externos. Por fim, ambos os dispositivos devem compartilhar um ground.
#
# interface = rpc.rpc_i2c_master(slave_addr=0x12, rate=1000000)
# Descomente a linha abaixo para configurar sua OpenMV Cam para controlar via SPI.
#
# * cs_pin - Pino de seleção do escravo (Slave Select).
# * freq - Frequência do clock do barramento SPI
# * clk_polarity - Nível do clock em repouso (0 ou 1).
# * clk_phase - Amostra dados na primeira (0) ou segunda borda (1) do clock.
#
# NOTA: As configurações do mestre e do escravo devem coincidir. Conecte CS, SCLK, MOSI, MISO a CS, SCLK, MOSI, MISO.
# Por fim, ambos os dispositivos devem compartilhar um ground comum.
#
interface = rpc.rpc_spi_master(cs_pin="P3", freq=20000000, clk_polarity=1, clk_phase=0)
# Descomente a linha abaixo para configurar sua OpenMV Cam para controlar via UART.
#
# * baudrate - Taxa de transmissão serial.
#
# NOTA: As taxas de baud do mestre e do escravo devem coincidir. Conecte o tx do mestre ao rx do escravo e o rx do mestre ao
# tx do escravo. Por fim, ambos os dispositivos devem compartilhar um ground comum.
#
# interface = rpc.rpc_uart_master(baudrate=7500000)
##############################################################
# Manipuladores de Call Back
##############################################################
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) # Alocar frame buffer zerado.
img_ba = img.bytearray()
if cutthrough:
# Transferência de dados rápida (cutthrough) sem verificação de erros.
# Antes de iniciar a transferência de dados cutthrough, precisamos sincronizar tanto o mestre quanto o
# dispositivo escravo. No retorno, ambos os dispositivos estão sincronizados.
result = interface.call("raw_image_read")
if result is not None:
# GET BYTES PRECISA SER EXECUTADO IMEDIATAMENTE A SEGUIR, COM POUCO ATRASO.
# Ler todos os dados da imagem em uma única transferência bem grande.
interface.get_bytes(img_ba, 5000) # timeout
else:
# Transferência de dados mais lenta com verificação de erros.
# Transferir blocos de 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): # Tentar até 3 vezes.
result = interface.call(
"raw_image_read", struct.pack("<II", i, chunk_size)
)
if result is not None:
img_ba[i:i + chunk_size] = result # Escrever os dados da imagem.
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()
# Você pode alterar o pixformat e o framesize da imagem transferida do dispositivo remoto
# modificando os argumentos abaixo.
#
# Quando cutthrough é False, a imagem será transferida pela biblioteca RPC com proteção de CRC e
# retransmissão em todos os dados movidos. Para uma transferência de dados mais rápida, defina cutthrough como True para que
# get_bytes() e put_bytes() sejam chamados após a conclusão de uma chamada RPC para transferir dados
# mais rapidamente de um buffer de imagem para outro. Nota: Isso funciona porque, assim que uma chamada RPC
# é concluída com sucesso, tanto o dispositivo mestre quanto o escravo ficam completamente sincronizados.
#
img = get_frame_buffer_call_back(
csi.RGB565, csi.QQVGA, cutthrough=True, silent=True
)
if img is not None:
pass # Você pode processar a imagem aqui.
print(clock.fps())