image-patches-differential-rotation-scale.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
#
# Flusso ottico differenziale a patch di immagine - Rotazione/Scala
#
# Questo esempio mostra come usare la tua OpenMV Cam per misurare
# la rotazione/scala confrontando l'immagine corrente e quella
# precedente tra loro. Nota che in questa modalità viene gestita solo
# la rotazione/scala, non la traslazione X e Y.
#
# Tuttavia questo esempio va oltre il semplice calcolo del flusso ottico sull'intera
# immagine in una volta sola. Invece suddivide il processo lavorando su gruppi
# di pixel dell'immagine. Questo fornisce una "nuova" immagine di risultati.
#
# NOTA che le superfici devono avere un qualche tipo di "bordo" affinché
# l'algoritmo funzioni. Una superficie priva di dettagli produce risultati assurdi.
#
# Per eseguire efficacemente questa demo, monta la tua OpenMV Cam su una base
# stabile e ruota LENTAMENTE la fotocamera attorno all'obiettivo, spostando la fotocamera
# avanti/indietro per vedere i numeri cambiare.
# Ovvero solo cambiamenti nella direzione Z.
#
# NOTA È necessario usare una piccola risoluzione potenza di 2 quando si usa
# find_displacement(). Questo perché l'algoritmo è basato su
# qualcosa chiamato correlazione di fase, che esegue il confronto tra immagini
# usando le FFT. Una risoluzione che non è una potenza di 2 richiede un padding fino a una potenza
# di 2, il che riduce l'utilità dei risultati dell'algoritmo. Si prega di
# usare una risoluzione come B128X128 o B128X64 (2x più veloce).
#
# La tua OpenMV Cam supporta risoluzioni potenza di 2 di 64x32, 64x64,
# 128x64 e 128x128. Se desideri una risoluzione di 32x32 puoi crearla
# eseguendo "img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)" su un'immagine 64x64.
import csi
import image
import time
import math
BLOCK_W = 16 # pow2
BLOCK_H = 16 # pow2
csi0 = csi.CSI()
csi0.reset() # Resetta e inizializza il sensore.
csi0.pixformat(csi.GRAYSCALE) # Imposta il formato pixel su GRAYSCALE
csi0.framesize((128, 128)) # Imposta la dimensione del fotogramma a 128x128... (o 64x64)...
csi0.snapshot(time=2000) # Attendi che le impostazioni abbiano effetto.
clock = time.clock() # Crea un oggetto clock per tracciare gli FPS.
# Crea un secondo frame buffer nell'heap.
extra_fb = image.Image(csi0.width(), csi0.height(), csi0.pixformat())
extra_fb.draw_image(csi0.snapshot())
while True:
clock.tick() # Traccia i millisecondi trascorsi tra le chiamate a snapshot().
img = csi0.snapshot() # Scatta una foto e restituisce l'immagine.
for y in range(0, csi0.height(), BLOCK_H):
for x in range(0, csi0.width(), BLOCK_W):
displacement = extra_fb.find_displacement(
img,
logpolar=True,
roi=(x, y, BLOCK_W, BLOCK_H),
template_roi=(x, y, BLOCK_W, BLOCK_H),
)
# Al di sotto di circa 0.1 (i risultati possono variare) i risultati sono solo rumore.
if displacement.response > 0.1:
rotation_change = displacement.rotation
zoom_amount = 1.0 + displacement.scale
pixel_x = (
x
+ (BLOCK_W // 2)
+ int(math.sin(rotation_change) * zoom_amount * (BLOCK_W // 4))
)
pixel_y = (
y
+ (BLOCK_H // 2)
+ int(math.cos(rotation_change) * zoom_amount * (BLOCK_H // 4))
)
img.draw_line(
(x + BLOCK_W // 2, y + BLOCK_H // 2, pixel_x, pixel_y), color=255
)
else:
img.draw_line(
(
x + BLOCK_W // 2,
y + BLOCK_H // 2,
x + BLOCK_W // 2,
y + BLOCK_H // 2,
),
color=0,
)
extra_fb.draw_image(img)
print(clock.fps())