image-patches-differential-rotation-scale.py
# Ce travail est publié sous licence MIT.
# Copyright (c) 2013-2023 OpenMV LLC. Tous droits réservés.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# Flux optique différentiel par blocs d'image - Rotation/Échelle
#
# Cet exemple montre comment utiliser votre OpenMV Cam pour mesurer
# la rotation/l'échelle en comparant l'image actuelle et la
# précédente. Notez que seules la rotation et l'échelle sont
# gérées, et non la translation X et Y dans ce mode.
#
# Cependant, cet exemple va plus loin que le simple flux optique sur l'ensemble
# de l'image à la fois. Il décompose plutôt le traitement en travaillant sur des groupes
# de pixels de l'image. Cela vous donne une « nouvelle » image de résultats.
#
# REMARQUE : les surfaces doivent présenter un type de « contour » pour que
# l'algorithme fonctionne. Une surface sans motif produit des résultats aberrants.
#
# Pour exécuter cette démonstration efficacement, veuillez monter votre OpenMV Cam sur une
# base stable et faire tourner LENTEMENT la caméra autour de l'objectif, puis la déplacer
# vers l'avant/l'arrière pour voir les chiffres changer.
# C'est-à-dire uniquement des changements dans la direction Z.
#
# REMARQUE : vous devez utiliser une petite résolution puissance de 2 lorsque vous utilisez
# find_displacement(). En effet, l'algorithme repose sur
# un mécanisme appelé corrélation de phase, qui effectue la comparaison d'images
# à l'aide de FFT. Une résolution qui n'est pas une puissance de 2 nécessite un remplissage jusqu'à une puissance
# de 2, ce qui réduit l'utilité des résultats de l'algorithme. Veuillez
# utiliser une résolution telle que B128X128 ou B128X64 (2x plus rapide).
#
# Votre OpenMV Cam prend en charge les résolutions puissance de 2 de 64x32, 64x64,
# 128x64 et 128x128. Si vous souhaitez une résolution de 32x32, vous pouvez la créer
# en effectuant « img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA) » sur une image 64x64.
import csi
import image
import time
import math
BLOCK_W = 16 # pow2
BLOCK_H = 16 # pow2
csi0 = csi.CSI()
csi0.reset() # Réinitialiser et initialiser le capteur.
csi0.pixformat(csi.GRAYSCALE) # Définir le format de pixel sur GRAYSCALE
csi0.framesize((128, 128)) # Définir la taille d'image sur 128x128... (ou 64x64)...
csi0.snapshot(time=2000) # Attendre que les réglages prennent effet.
clock = time.clock() # Créer un objet horloge pour suivre le FPS.
# Créer un second tampon d'image sur le tas.
extra_fb = image.Image(csi0.width(), csi0.height(), csi0.pixformat())
extra_fb.draw_image(csi0.snapshot())
while True:
clock.tick() # Suivre les millisecondes écoulées entre les snapshots().
img = csi0.snapshot() # Prendre une photo et renvoyer l'image.
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),
)
# En dessous d'environ 0,1 (les résultats peuvent varier), les résultats ne sont que du bruit.
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())