giovedì 14 settembre 2023

PS4 Stereo Camera su Linux

Visto che oramai si trovano anche a prezzi sui 20 euro ho provato la camera stereo di PS4

PS eye versione 1 e 2

Per usarla su PC si deve avere obbligatoriamente una porta USB3 e il convertitore (che costa in proporzione piu' della camera stessa ma si puo' anche autoprodurre) 


https://github.com/sieuwe1/PS4-eye-camera-for-linux-with-python-and-OpenCV

Dopo la connessione fisica deve essere modificato il firmware per usare il dispositivo come UVC



In fase di calibrazione ho avuto un errore di 0.024 con 40 immagini ed usando i file del pacchetto

Per vedere come funziona la camera ho un po' modificato il file GetDepth.py estraendo i dati di profondita' che sono contenuti nella matrice z_values

Come si vede dall'immagine sottostante c'e' una banda a sinistra che non riporta valori. Inoltre le profondita' variano da 0.3  a 2.6 m (valore massimo di profondita' restituito dal software nonostante le dimensioni della stanza siano ben maggiori)

I dati di profondita' sono molto variabili  ma se si mediano i valori accumulando le immagini (nel mio caso ho accumulato 100 immagini) l'errore si avvicina ad 1 cm

Differenza tra due mappe di profondita' consecutive



import numpy as np
import cv2
from matplotlib import pyplot as plt
import time
from datetime import datetime

#Load camera parameters
ret = np.load('param_ret.npy')
K = np.load('param_K.npy')
dist = np.load('param_dist.npy')
h,w = (800, 1264)
new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(K,dist,(w,h),1,(w,h))

mapx, mapy = cv2.initUndistortRectifyMap(K,dist, None ,new_camera_matrix,(w, h),cv2.CV_16SC2)

#cap = cv2.VideoCapture("/home/sieuwe/Desktop/vidz/full_2.avi")
#cap = cv2.VideoCapture("/home/sieuwe/Desktop/vidz/full_3.avi")
#cap = cv2.VideoCapture("/home/sieuwe/Desktop/vidz/full_1.avi")
cap = cv2.VideoCapture(2)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 3448)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 808)

kernel= np.ones((13,13),np.uint8)

#Stereo matcher settings
win_size = 5
min_disp = 10
max_disp = 16 * 2 + 10
num_disp = max_disp - min_disp # Needs to be divisible by 16
stereo = cv2.StereoSGBM_create(minDisparity= min_disp,
numDisparities = num_disp,
blockSize = 5,
uniquenessRatio = 10,
speckleWindowSize = 1000,
speckleRange = 10,
disp12MaxDiff = 25,
P1 = 8*3*win_size**2,#8*3*win_size**2,
P2 =32*3*win_size**2) #32*3*win_size**2)

sommatore=np.zeros((400,632),np.float32)
contatore = 0
limite = 100


def decode(frame):
left = np.zeros((800,1264,3), np.uint8)
right = np.zeros((800,1264,3), np.uint8)
for i in range(800):
left[i] = frame[i, 64: 1280 + 48]
right[i] = frame[i, 1280 + 48: 1280 + 48 + 1264]
return (left, right)

def get_distance(d):
return 30 * 10/d

while(1):

ret, frame = cap.read()

start = time.time()

right, left = decode(frame)

#Undistort images
#img_1_undistorted = cv2.undistort(left, K, dist, None, new_camera_matrix)
#img_2_undistorted = cv2.undistort(right, K, dist, None, new_camera_matrix)
#img_1_undistorted= cv2.remap(left,mapx,mapy, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0)
#img_2_undistorted= cv2.remap(right,mapx,mapy, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0)

#downsample image for higher speed
img_1_downsampled = cv2.pyrDown(cv2.cvtColor(left, cv2.COLOR_BGR2GRAY))
img_2_downsampled = cv2.pyrDown(cv2.cvtColor(right, cv2.COLOR_BGR2GRAY))

new_w, new_h = img_1_downsampled.shape

#compute stereo
disp = stereo.compute(img_1_downsampled,img_2_downsampled)
#denoise step 1
denoised = ((disp.astype(np.float32)/ 16)-min_disp)/num_disp
dispc= (denoised-denoised.min())*255
dispC= dispc.astype(np.uint8)
#denoise step 2
denoised= cv2.morphologyEx(dispC,cv2.MORPH_CLOSE, kernel)
#apply color map
disp_Color= cv2.applyColorMap(denoised,cv2.COLORMAP_OCEAN)
f = 0.3*w # 30cm focal length
Q = np.float32([[1, 0, 0, -0.5*new_w],
[0,-1, 0, 0.5*new_h], # turn points 180 deg around x-axis,
[0, 0, 0, f], # so that y-axis looks up
[0, 0, 1, 0]])
points = cv2.reprojectImageTo3D(disp, Q)

z_values = points[:,:,2]
print(np.size(z_values))
print(z_values.shape)
now = datetime.now()
np.save(now.strftime("%Y%m%d%H%M%S%f"),z_values)

cv2.imshow("Z",z_values)
sommatore = sommatore + z_values
contatore = contatore + 1
if (contatore == limite):
contatore = 0
sommatore = sommatore /limite
now = datetime.now()
np.save(now.strftime("%Y%m%d%H%M%S"),sommatore)
sommatore.fill(0)

z_values = z_values.flatten()
indices = z_values.argsort()

precentage = 25280
min_distance = np.mean(np.take(z_values,indices[0:precentage])) # takes the 30% lowest measuerements and gets the average distance from these.
avg_distance = np.mean(z_values) # averages all distances
max_distance = np.mean(np.take(z_values,indices[z_values.shape[0]-precentage:z_values.shape[0]])) # takes the 30% highest measuerements and gets the average distance from these.
#print(np.take(z_values,indices[z_values.shape[0]-precentage:z_values.shape[0]]))
#print(np.take(z_values,indices[:-100]))

#visualize
cv2.imshow("Depth", disp_Color)
left = cv2.resize(left,(632, 400))
color_depth = cv2.addWeighted(left,0.4,disp_Color,0.4,0)

end = time.time()
fps = 1 / (end-start)

cv2.putText(color_depth, "minimum: " + str(round(min_distance,1)),(5, 20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)
cv2.putText(color_depth, "average: " + str(round(avg_distance,1)),(5, 40),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)
cv2.putText(color_depth, "maximum: " + str(round(max_distance,1)),(5, 60),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)
cv2.putText(color_depth, "FPS: " + str(round(fps)),(5, 80),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)

cv2.imshow("color & Depth", color_depth)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

cap.release()
cv2.destroyAllWindows()







giovedì 7 settembre 2023

Esp32 idf.py

Per prima cosa un confronto tra un Espressif ESP32-S3 DevKit ed un clone cinese denominato YD-ESP32-S3..li ho comprati pensando che fossero uguali..in realta' oltre al fatto che una monta delle microUSB mentre l'altra USB-C ed il pin del led RGB e' in una GPIO38 e nell'altra in  GPIO47

Inoltre la programmazione nella Espressif e' sul connettore sinistro (UART) mentre in in YD e' sul connettore destro (UART) 




Un altro aspetto che non e' documentato (e che mi ha fatto impazzire fino a quando non ho trovato questo link) e' il led RGB non e' connesso nell YD-ESP32...si devono saldare i due pad con la scritta RGB

. ./export.sh

idf.py create-project pingo

idf.py create-project-from-example "espressif/esp-dsp:basic_math"

idf.py set-target esp32s3

idf.py build

idf.py menuconfig

idf.py -p /dev/ttyACM0 flash

per aggiungere un componente esterno ( https://components.espressif.com/components/espressif/) si puo' il comando sottostante (nello specifico la libreria iqmath)

idf.py add-dependency "espressif/iqmath^1.11.0"

il comando aggiunge solo il riferimento ma non scarica i file della libreria. Si deve lanciare

idf.py reconfigure

e si vefra' aggiungersi la directory managed_components

 
idf.py -p PORT build flash monitor
Ctrl-] per uscire dal monitor

Per effettuare il debug tramite la porta USB i cavi sono posizionati come in foto...si salta il primo pin della fila dal basso poi si inserisce GND/nero, bianco e verde e dal comando lsusb deve comparire Espressif USB JTAG/serial debug unit


Nel momento in cui si usa il cavo Jtag Usb insieme alla USB UART non si deve collegare il 5V (cavo rosso) del cavo del dubugger 

Per lo sviluppo di solo ESP32 e' conveniente usare l'estensione ESP-IDF di Visual Studio al posto di PlatformioIO

Per prima cosa si deve configurare ESP-IDF: Configure ESP-IDF extension


CTRL+E B : effettua la build del progetto

CTRL+E T : apre il terminale IDF

CTRL+E P : seleziona la porta

Per impostare la porta UART CTRL+SHIFT+P ESP-IDF:Device configuration

ESP-IDF : Select OpenOCD Board Configuration


mercoledì 23 agosto 2023

Installare R packages in docker

A causa di una applicazione legacy dovevo dovevo usare R ver 3 che non eà compatibile con R ver 4 (era esclusa la riscittura del codice) 




Dopo un po' di tentativi la strada piu' lineare e' stata quella di creare un container con il seguente Dockerfile che installa anche tutti i packages delle dipendenze

FROM rstudio/r-base:3.6-bookworm
RUN apt-get -y update
RUN apt-get -y install gdal-bin libgdal-dev libpng-dev libudunits2-dev libfontconfig1-dev libmagick++-dev
RUN curl -O "https://cran.r-project.org/src/contrib/Archive/randomForest/randomForest_4.6-10.tar.gz"

#setup R configs
RUN echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile
RUN Rscript -e "install.packages('zoo')"
RUN Rscript -e "install.packages('leaflet')"
RUN Rscript -e "install.packages('sf')"
RUN Rscript -e "install.packages('leafpop')"
RUN Rscript -e "install.packages('forecast')"
RUN Rscript -e "install.packages('stringr')"
RUN Rscript -e "install.packages('lubridate')"
RUN Rscript -e "install.packages('randomForest_4.6-10.tar.gz', repos = NULL, type='source')"
RUN Rscript -e "install.packages('rpart')"
RUN Rscript -e "install.packages('e1071')"
RUN Rscript -e "install.packages('kknn')"
RUN Rscript -e "install.packages('jpeg')"
RUN Rscript -e "install.packages('data.table')"
RUN Rscript -e "install.packages('tidyr')"
RUN Rscript -e "install.packages('magick')"
RUN Rscript -e "install.packages('leaflet.extras')"
RUN Rscript -e "install.packages('leafem')"
RUN Rscript -e "install.packages('raster')"

docker build -t nome_docker .


Per usare il container

docker run --rm -it -v /home/luca:/mnt nome_docker bash

(se si omette bash entra direttamente nel prompt di R)



sabato 19 agosto 2023

Fractional scaling su Gnome Debian

 Al momento e' possibile comprare dei portatili a basso costo che sono ancora del tutto validi per l'utilizzo se non per le dimensioni dello schermo (spesso 1366x768) 

Esiste la possibilita' di andare oltre le dimensioni fisiche dello schermo utilizzando il fractional scaling con il seguente comando (valori maggiori di 1 le dimensioni virtuali sono superiori a quellli reali)

xrandr --output eDP-1  --scale 1.7x1.7

In Gnome su Debian si possono impostare fattori di scala di ingrandimento di ingrandimento, su XFCE si puo' sia ingrandire che ridurre lo schermo

venerdì 18 agosto 2023

Saturno

Va abbastanza schifo ma non riesco a capire come si usa la SVBony 305 (oltre al fatto che ho litigato con il puntamento Goto tramite CPWI)




giovedì 17 agosto 2023

Subpixel corner detection con Opencv

Ho provato a vedere se la funzione di  corner detection poteva essere utile con gli aruco tags per vedere se vi erano spostamenti


Non sembra ma quella sopra e' una gif animata (187 frames)

Ho preso l'esempio della libreria OpenCV applicato ad una serie di immagini di un Aruco tag statico ripreso con differenti condizioni di illuminazione

from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng

source_window = 'Image'
maxTrackbar = 25
rng.seed(12345)

def goodFeaturesToTrack_Demo(val):
maxCorners = max(val, 1)
# Parameters for Shi-Tomasi algorithm
qualityLevel = 0.01
minDistance = 10
blockSize = 3
gradientSize = 3
useHarrisDetector = False
k = 0.04
# Copy the source image
copy = np.copy(src)
# Apply corner detection
corners = cv.goodFeaturesToTrack(src_gray, maxCorners, qualityLevel, minDistance, None, blockSize=blockSize, gradientSize=gradientSize, useHarrisDetector=useHarrisDetector, k=k)
# Draw corners detected
radius = 4
winSize = (5, 5)
zeroZone = (-1, -1)
criteria = (cv.TERM_CRITERIA_EPS + cv.TermCriteria_COUNT, 40, 0.001)
# Calculate the refined corner locations
corners = cv.cornerSubPix(src_gray, corners, winSize, zeroZone, criteria)
# Write them down
for i in range(corners.shape[0]):
print(corners[i,0,0],";",corners[i,0,1],";",end='')
parser = argparse.ArgumentParser(description='Code for Shi-Tomasi corner detector tutorial.')
parser.add_argument('--input', help='Path to input image.', default='pic3.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
maxCorners = 10 # initial threshold
goodFeaturesToTrack_Demo(maxCorners)
print()


il risultato dell'algotitmo e' di questo tipo




Alla fine e' emerso l'algoritmo seleziona in modo automatico gli angoli con un ordine diverso  e c'e' una forte influenza dell'illuminazione sulla definizione delle coordinate dell'angolo 

In casi ottimali (ma non e' questo il caso) ho visto che la standard deviation e' di circa 0.2 pixels

Non e' quindi un metodo affidabile per il change detection








domenica 13 agosto 2023

ESP PROG

 

========================================

[env:az-delivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
board_build.mcu: esp32
board_build.f_cpu: 240000000L
framework = arduino
monitor_speed = 115200
upload_speed = 115200
upload_port = /dev/ttyUSB2

[env:debugdelivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
board_build.mcu: esp32
board_build.f_cpu: 240000000L
framework = arduino
debug_speed = 12000
debug_port = /dev/ttyUSB0
debug_tool = esp-prog
debug_init_break = tbreak setup

========================================


CTRL+SHIFT+P

Platformio Upload and Monitor (non c'e' uno shortcut)






Attenziona che la numerazione dei pin sulla fila sinistra iniziano dal 2 pin dal basso 

TMS = grigio pin 14

TCK = nero pin 13

TD0 = giallo pin 15 

TDI = bianco pin 12

GND = pin GND

Il VDD deve essere collegato al pin 3.3 V dell'ESP32 SOLO se non viene inserita l'USB 



/home/luca/.platformio/packages/toolchain-xtensa-esp32@8.4.0+2021r2-patch5/bin/xtensa-esp32-elf-gdb: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory

apt-get install libpython2.7-dev


apt install python3-venv

add user xxxx dialout

curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules



Esperimento (fallito) ESP32 solare

Ho provato a vedere se era possibile alimentare con continuita' un Esp32 (un TTGO-Display) tramite un pannello solare ed una batteria 18650  tramite un modulo TP4055

Sull'ESP32 era montato uno sketch che mostrava un cronometro per verificare il tempo di funzionamento


Alla fine dei conti, nonostanti il periodo estivo e con la limitazione che il pannello era direttamente irraggiato solo meta' giornata, il pannello riusciva a caricare la batteria ma non abbastanza per avere un bilancio positivo a fine giornata e cosi' dopo 5 giorni (partendo da batteria completamente carica) il sistema si e' spento







lunedì 7 agosto 2023

TpLink WN722N v2v3 monitor ESP-NOW con Debian 11

 Volevo usare la scheda WN722N per monitorare il traffico Esp-Now usando WireShark...il fatto e' che la scheda e' riconosciuta da Debian 11 ma non entrava in monitor mode mentre usando ParrotOs funzionava perfettamente.




La soluzione e' ricompilare il modulo  usando questo link

git clone https://github.com/gglluukk/rtl8188eus

make &make install

e eliminando il modulo di defualt

sudo echo 'blacklist r8188eu'|sudo tee -a '/etc/modprobe.d/realtek.conf'

al riavvio si puo' monitorare il traffico mediante questi comandi


sudo ip link set wlx9c532268fdca down
sudo iw wlx9c532268fdca set monitor control
sudo ip link set wlx9c532268fdca up
sudo wireshark


per selezionare il traffico proveniente da un determinato MAC si puo'usare
wlan.sa==xx:xx:xx:xx:xx:xx



Il seguente codice invia un messaggio broadcast su ESP-NOW con abilitato il Long Range (evidenziato in giallo)
========================================================

/*
  ESP-NOW Demo - Transmit
  esp-now-demo-xmit.ino
  Sends data to Responder
  
  DroneBot Workshop 2022
  https://dronebotworkshop.com
  https://dronebotworkshop.com/esp-now/
*/

// Include Libraries
#include <esp_wifi.h>

#include <esp_now.h>
#include <WiFi.h>

// Variables for test data
int int_value;

// MAC Address of responder - edit as required
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

esp_interface_t current_esp_interface;
wifi_interface_t current_wifi_interface;



// Define a data structure
typedef struct struct_message {
  char a[32];
  int b;
} struct_message;

// Create a structured object
struct_message myData;

// Peer info
esp_now_peer_info_t peerInfo;

// Callback function called when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLast Packet Send Status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

void setup() {
  int_value = 0;
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  esp_wifi_set_protocol(current_wifi_interface, WIFI_PROTOCOL_LR);
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  esp_now_register_send_cb(OnDataSent);
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  
}

void loop() {
 strcpy(myData.a, "Luca");
  int_value++;
  myData.b = int_value;
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
  if (result == ESP_OK) {
    Serial.println("Sending confirmed");
  }
  else {
    Serial.println("Sending error");
  }
  delay(1000);
}
========================================================

Per leggere i pacchetti ESP-NOW a linea di comando si puo' usare tcpdump oppure un progetto Go che utilizza le libreria Pcap https://pkg.go.dev/github.com/google/gopacket/pcap

domenica 30 luglio 2023

Ophcrack per recuperare password Windows XP

Il problema e' seguente: recuperare la password da un vetusto PC con XP senza pero' resettarla

Soluzione : usare Ophcrack, un live CD linux con il sofo software per recuperare le password dagli has

Per prima cosa si deve indicare dove sono le tabelle. Se si effettua il download con le tabella gia' caricate esse si trovano in /media/ophcrack


Dopo di cio' si deve indicare dove si trova il file delle password che e'  in Windows/system/config

Sul mio calcolatore le passwords erano di 7 lettere ed il sistema ha impiegato pochi minuti per decrittarle 





giovedì 27 luglio 2023

Aruco terrestrial spotting scope

Aggiornamento: ho sostituio il Meade con il Celestron da viaggio da 70 mm. L'errore di standard deviation a 50 m e' stimato intorno al 0.6% della distanza (quindi 30 cm). Comincia a non valere piu' la pena di lavorarci sopra



Volevo vedere se era possibile usare Aruco Tags mediante telescopio (o meglio spotting scope terrestre) 

I modelli in vendita non hanno l'oculare rimuovibile (sono venduti per uso di tiro al bersaglio o bird watching) ed ho preso il mio Meade AC 70/350 ETX-70 GoTo, un rifrattore da viaggio che non uso quasi mai per la mancanza del puntatore,ed una SVBony 105



A 50 m un tag aruco da 10 cm occupa circa 120x120 pixels


per acquisire in automatico ho utlizzato i comandi sottostanti .Da notare che il SVBony 105 esce in YUYV e non RGB 


v4l2-ctl -c exposure_auto=0

sleep 10

fswebcam -r 1920x1080 --jpeg 95 -D 1 --no-banner --device /dev/video2 --skip 50 --loop 10 -p YUYV --save pic%Y-%m-%d_%H:%M:%S.jpg


giusto per confronto lo stesso bersaglio ripreso da una Canon 450D con tele da 300



sabato 22 luglio 2023

Aruco vs Apriltag condizioni reali

Aggiornamento:

Dopo aver provato un po' di tutto per correggere i dati ho scoperto che le immagini originali non sono state riprese in modo corretto. La camera satura in alcuni condizioni di luce come si vede dai due esempi sottostanti rendendo inutile l'elaborazione





Prova comparativa per misuare distanze tramite April ed Aruco tag in condizioni reali 

Lo scopo e' quello di verificare la ripetibilita' delle misure di distanza mediante tag a condizioni di luce variabile e per questo sono state effettuate misure con i tag in posizione stazionaria

E' stata impiegata una camera di sorveglianza a fuoco fisso con acquisizione ogni 10 minuti anche di notte grazie all'illuminazione ad infrarossi

I tag sono stati di dimensione di 25 cm in formato 4x4 per Aruco e 36h11 per gli Apriltag


Per determinare la distanza sono state impiegate le librerie OpenCV su Python per agli Aruco Tags mentre la libreria Apriltags3 in C++



in generale gli Apriltag risultano meglio individuabili rispetto agli Aruco tag. Di 430 immagini totali gli Apriltags sono stati individuati al 99% ad una distanza di 6 m mentre gli Aruco tag hanno prestazioni simili ma solo sulla breve distanza (4 m)


Aruco

l'elaborazione dei tag aruco indica che l'algoritmo genera molti outliers che possono essere facilmente separati dai dati corretti












Provando a smussare i dati con una media mobile a finetra oraria la situazione non migliora e si osserva un comportamento legato all'illuminazione che si ritrovera' anche dopo con gli April Tags 



Apriltag

Dall'analisi dei grafici si vede che le condizioni di illuminazione condizionano fortemente la misura della distanza mediante Apriltag. Le misure piu' stabili sono di notte quando e' attiva l'illuminazione dei led ad infrarossi

Rispetto ad Aruco ci sono molti meno outliers ed i dati sono meno rumorosi



In queste condizioni e' stato registrato un errore di standard devitation pari a 0.96% della distanza per il tag a 6.5m e dell'1% per il tag a 10 m

Se si plottano i dati a parita' di ora del giorno si vede ancora piu' chiaramente come la presenza di ombra influenza il dato di distanza

Se si fa la differenza tra le due curve l'errore scende al 0.18%


Un sistema per rimuovere l'effetto dell'illuminazione e' di correlare i dati dei due tag (sono vicini quindi sono illuminati in modo comparabile)


Per cercare di risolvere il problema delle differenti illuminazione ho provato ad elaborare le immagini mediante l'algoritmo presentato in questo articolo (Illumination Invariant Imaging: Applications in Robust Vision-based Localisation, Mapping and Classification for Autonomous Vehicles)

In estrema sintesi l'algoritmo appiattisce una immagine RGB e cerca di annullare gli effetti di differente illuminaizone (questo algoritmo funziona solo sulle immagini diurne perche' la camera di notte acquisisce a scala di grigi)


Per le elaborazioni ho usato questo progetto su Github.  (ho dovuto fare una leggere modifica perche' le immagini della camera avevano dei valori zero che ovviamente non potevano essere usati in un logaritmo)

import cv2
import numpy as np
import os
from argparse import ArgumentParser
from multiprocessing import Pool

ROBOTCAR_ALPHA = 0.4642


def transform(im):
# Assumes image is RGB-ordered
image = cv2.imread(read_dir + "/" + im, cv2.IMREAD_UNCHANGED)
r, g, b = image[:, :, 0], image[:, :, 1], image[:, :, 2]


// per eliminare gli eventuali zeri dalla matrice
r = np.where(r==0, 0.1, r)
g = np.where(g==0, 0.1, g)
b = np.where(b==0, 0.1, b)
ii_image = 0.5 + np.log(g) - ROBOTCAR_ALPHA*np.log(b) - (1-ROBOTCAR_ALPHA)*np.log(r)

# Lastly, convert from float to uint8 space
max_ii = np.max(ii_image)
min_ii = np.min(ii_image)
uii = np.uint8((ii_image - min_ii) * 256 / (max_ii - min_ii))
ii_name = write_dir + "/" + im
cv2.imwrite(ii_name, uii)
return ii_image


def transform_loop(directory):
image_names = os.listdir(directory)

# Spawn 4 worker processes to transform in parallel
p = Pool(4)
p.map(transform, image_names)


if __name__ == '__main__':
parser = ArgumentParser(
description=
'Transform images in a directory into lighting invariant color space')
parser.add_argument('--read-dir', action="store", type=str, required=True)
parser.add_argument('--write-dir', action="store", type=str, required=True)
args = parser.parse_args()

global read_dir, write_dir
read_dir = args.read_dir
write_dir = args.write_dir
transform_loop(read_dir)



dopo l'applicazione della elaborazione l'algoritmo di riconoscimento dei tag risulta molto piu' in difficolta' nel riconoscere i taf e sono state estratte solo 71 misure di distanza del tag1 e 16 misure del tag 2









Aggiornamento:

Frugando dentro al codice della demo di Apritag3 c'e' un porzione di codice che non puo' mai essere eseguito (c'e' un IF sempre True) e la condizione Falsa e' appunto l'algoritmo di Illumination Invariant 

Basta modificare la riga 156 per esempio aggiungendo un NOT si introduce il calcolo


questi sono i grafici risultanti dopo l'algoritmo. Si e' oersa la ritmicita' dell'illuminazione ma si e' persa anche la capacita' di riconoscere i tag nelle immagini trattate (per il tag 1 circa il 50%, tag2 decisamente peggio)



L'errore percentuale delle standard deviation e' pari a 1.79% per il tag1 e 1.08% per il tag 2
La differenza risiede nel valore del parametro utilizzato nell'elaborazione delle immagini




LLama3 Anita

A seguito di questo post ho provato a vedere ho provato a vedere cosa accadeva ad utilizzare un modello specifico per la lingua italiana in...