Visualizzazione post con etichetta Aruco. Mostra tutti i post
Visualizzazione post con etichetta Aruco. Mostra tutti i post

venerdì 11 ottobre 2024

Aruco e Image Stacking

Uno dei problemi maggiori dell'uso dei tag aruco in esterno per misurare distanze e' che le condizioni di illuminazione solare sono molto variabili e la compressione jpg completa l'opera aggiungendo rumore su rumore

Per cercare di limitare il problema ho provato a fare image stacking sovrapponendo 8 foto (una ogni ora dalle 09 alle 16) con lo script al link https://github.com/maitek/image_stacking ed applicando il programma visto qui


Il miglioramento non e' trascurabile perche' la standard deviation e' passata

3.1 m => da 0.19% a 0.16% (0.5 cm)

5.4 m => da 0.35% a 0.28% (1.5 cm)

7.6 m => da 0.71% a 0.38% (2.8 cm)

9.6 m => da 0.5% a 0.41% (4.8 cm)

 

import os
import cv2
import numpy as np
from time import time



# Align and stack images with ECC method
# Slower but more accurate
def stackImagesECC(file_list):
M = np.eye(3, 3, dtype=np.float32)

first_image = None
stacked_image = None

for file in file_list:
image = cv2.imread(file,1).astype(np.float32) / 255
print(file)
if first_image is None:
# convert to gray scale floating point image
first_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
stacked_image = image
else:
# Estimate perspective transform
s, M = cv2.findTransformECC(cv2.cvtColor(image,cv2.COLOR_BGR2GRAY), first_image, M, cv2.MOTION_HOMOGRAPHY)
w, h, _ = image.shape
# Align image to first image
image = cv2.warpPerspective(image, M, (h, w))
stacked_image += image

stacked_image /= len(file_list)
stacked_image = (stacked_image*255).astype(np.uint8)
return stacked_image


# Align and stack images by matching ORB keypoints
# Faster but less accurate
def stackImagesKeypointMatching(file_list):

orb = cv2.ORB_create()

# disable OpenCL to because of bug in ORB in OpenCV 3.1
cv2.ocl.setUseOpenCL(False)

stacked_image = None
first_image = None
first_kp = None
first_des = None
for file in file_list:
print(file)
image = cv2.imread(file,1)
imageF = image.astype(np.float32) / 255

# compute the descriptors with ORB
kp = orb.detect(image, None)
kp, des = orb.compute(image, kp)

# create BFMatcher object
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

if first_image is None:
# Save keypoints for first image
stacked_image = imageF
first_image = image
first_kp = kp
first_des = des
else:
# Find matches and sort them in the order of their distance
matches = matcher.match(first_des, des)
matches = sorted(matches, key=lambda x: x.distance)

src_pts = np.float32(
[first_kp[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)
dst_pts = np.float32(
[kp[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)

# Estimate perspective transformation
M, mask = cv2.findHomography(dst_pts, src_pts, cv2.RANSAC, 5.0)
w, h, _ = imageF.shape
imageF = cv2.warpPerspective(imageF, M, (h, w))
stacked_image += imageF

stacked_image /= len(file_list)
stacked_image = (stacked_image*255).astype(np.uint8)
return stacked_image

# ===== MAIN =====
# Read all files in directory
import argparse


if __name__ == '__main__':

parser = argparse.ArgumentParser(description='')
parser.add_argument('input_dir', help='Input directory of images ()')
parser.add_argument('output_image', help='Output image name')
parser.add_argument('--method', help='Stacking method ORB (faster) or ECC (more precise)')
parser.add_argument('--show', help='Show result image',action='store_true')
args = parser.parse_args()

image_folder = args.input_dir
if not os.path.exists(image_folder):
print("ERROR {} not found!".format(image_folder))
exit()

file_list = os.listdir(image_folder)
file_list = [os.path.join(image_folder, x)
for x in file_list if x.endswith(('.jpg', '.png','.bmp'))]

if args.method is not None:
method = str(args.method)
else:
method = 'KP'

tic = time()

if method == 'ECC':
# Stack images using ECC method
description = "Stacking images using ECC method"
print(description)
stacked_image = stackImagesECC(file_list)

elif method == 'ORB':
#Stack images using ORB keypoint method
description = "Stacking images using ORB method"
print(description)
stacked_image = stackImagesKeypointMatching(file_list)

else:
print("ERROR: method {} not found!".format(method))
exit()

print("Stacked {0} in {1} seconds".format(len(file_list), (time()-tic) ))

print("Saved {}".format(args.output_image))
cv2.imwrite(str(args.output_image),stacked_image)

# Show image
if args.show:
cv2.imshow(description, stacked_image)
cv2.waitKey(0)

 

 

 

 

mercoledì 2 ottobre 2024

Aruco Tag e filtri Kalman

Usando gli Aruco tag in ambiente esterno con illuminazione solare a diverse ore e in diversi periodi dell'anno ho trovato un errore nella stima della distanza tra due tag compresi tra 0.7% e 1.3% della distanza misurata. La domanda e' stata: e' possibile ridurre l'errore ?

Ho provato ad applicare il filtro Kalman per condizioni statiche (le distanze tra i tag nel tempo non sono variate) usando usando il codice a questo indirizzo 


Nel  grafico sottostante i punti blu sono i dati non filtrati, in linea continua blu i dati filtrati, in linea rossa il valore reale della misura di distanza

questo il codice impiegato con modestissime modifiche rispetto a quello di esempio

 

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd



def kalman_1d(x, P, measurement, R_est, Q_est):
x_pred = x
P_pred = P + Q_est
K = P_pred / (P_pred + R_est)
x_est = x_pred + K * (measurement - x_pred)
P_est = (1 - K) * P_pred
return x_est, P_est


def plot_1d_comparison(measurements_made, estimate, true_value, axis):
axis.plot(measurements_made ,'k+' ,label='measurements' ,alpha=0.3)
axis.plot(estimate ,'-' ,label='KF estimate')
if not isinstance(true_value, (list, tuple, np.ndarray)):
# plot line for a constant value
axis.axhline(true_value ,color='r' ,label='true value', alpha=0.5)
else:
# for a list, tuple or array, plot the points
axis.plot(true_value ,color='r' ,label='true value', alpha=0.5)
axis.legend(loc = 'lower right')
axis.set_title('Estimated position vs. time step')
axis.set_xlabel('Time')
axis.set_ylabel('$x_t$')

def plot_1d_error(estimated_error, lower_limit, upper_limit, axis):
# lower_limit and upper_limit are the lower and upper limits of the vertical axis
axis.plot(estimated_error, label='KF estimate for $P$')
axis.legend(loc = 'upper right')
axis.set_title('Estimated error vs. time step')
axis.set_xlabel('Time')
axis.set_ylabel('$P_t$')
plt.setp(axis ,'ylim' ,[lower_limit, upper_limit])


nome_file = "20_40"
df = pd.read_csv(nome_file+'.csv',header=0,sep=";")

#11 5.38
#15 3.39
#25 7.46
#40 4.26

mu = 4.26 # Actual position
R = 0.1 # Actual standard deviation of actual measurements (R)

# Generate measurements
#n_measurements = 1000 # Change the number of points to see how the convergence changes
#Z = np.random.normal(mu, np.sqrt(R), size=n_measurements)
Z = df[df.columns[2]].to_numpy()
# Estimated covariances
Q_est = 1e-4
R_est = 2e-2

# initial guesses
x = 5.1 # Use an integer (imagine the initial guess is determined with a meter stick)
P = 0.04 # error covariance P

KF_estimate=[] # To store the position estimate at each time point
KF_error=[] # To store estimated error at each time point
for z in Z:
x, P = kalman_1d(x, P, z, R_est, Q_est)
KF_estimate.append(x)
KF_error.append(P)

fig, axes = plt.subplots(1 ,2, figsize=(12, 5))
plot_1d_comparison(Z, KF_estimate, mu, axes[0])
np.savetxt(nome_file+"_stima.csv",KF_estimate)
plot_1d_error(KF_error, 0, 0.015, axes[1])
plt.tight_layout()
plt.savefig(nome_file+'.png')

 

 

 

 

lunedì 23 settembre 2024

Spot Robot Calibration Board Boston Bynamics e OpenCV

Ho avuto la fortuna di poter usare una enorma Charuco Board legata al cane robot Spot della Boston Dynamics


Nonostante non sia esplicitamente indicato si tratta di una Charuco Board 4x4_100 di 9 colonne e 4 righe

Per usarla per calibrare una camera si puo' usare il seguente script OpenCV

Attenzione: per funzionare lo script necessita setLegacyPattern(True)

import os
import numpy as np
import cv2

# ------------------------------
# ENTER YOUR REQUIREMENTS HERE:
ARUCO_DICT = cv2.aruco.DICT_4X4_250
SQUARES_VERTICALLY = 9
SQUARES_HORIZONTALLY = 4
SQUARE_LENGTH = 0.115
MARKER_LENGTH = 0.09
# ...
PATH_TO_YOUR_IMAGES = './hikvision'
# ------------------------------

def calibrate_and_save_parameters():
# Define the aruco dictionary and charuco board
dictionary = cv2.aruco.getPredefinedDictionary(ARUCO_DICT)
board = cv2.aruco.CharucoBoard((SQUARES_VERTICALLY, SQUARES_HORIZONTALLY), SQUARE_LENGTH, MARKER_LENGTH, dictionary)
board.setLegacyPattern(True)
params = cv2.aruco.DetectorParameters()
params.cornerRefinementMethod = 0


image_files = [os.path.join(PATH_TO_YOUR_IMAGES, f) for f in os.listdir(PATH_TO_YOUR_IMAGES) if f.endswith(".jpg")]
image_files.sort()

all_charuco_corners = []
all_charuco_ids = []

for image_file in image_files:
print(image_file)
image = cv2.imread(image_file)
marker_corners, marker_ids, _ = cv2.aruco.detectMarkers(image, dictionary, parameters=params)

# If at least one marker is detected
if len(marker_ids) > 0:
charuco_retval, charuco_corners, charuco_ids = cv2.aruco.interpolateCornersCharuco(marker_corners, marker_ids, image, board)

if charuco_retval:
all_charuco_corners.append(charuco_corners)
all_charuco_ids.append(charuco_ids)

# Calibrate camera
retval, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.aruco.calibrateCameraCharuco(all_charuco_corners, all_charuco_ids, board, image.shape[:2], None, None)

# Save calibration data
np.save('hik_camera_matrix.npy', camera_matrix)
np.save('hik_dist_coeffs.npy', dist_coeffs)


cv2.destroyAllWindows()

calibrate_and_save_parameters()







venerdì 22 marzo 2024

Aruco tag e image stacking

Per cercare di migliorare il riconoscimento dei tag (Aruco, April) ho provato a fare image stacking per ridurre il rumore

Ho trovato una soluzione gia' pronta in questo repository

https://github.com/maitek/image_stacking

La definizione dei bordi e' nettamente migliorata

Image stacking

 
Immagine singola

domenica 10 marzo 2024

Rete neurale ed Aruco

Per alcune prove con gli Aruco tags sto usando una camera che ha come formato di output JPG ma sarebbe piu' idoneo il formato PNG 

Ho provato la rete neurale a questo link che permette di ricostruire dettagli che si sono persi al momento della compressione JPG.

Ho usato un set di immagini processandole come segue

alias enhance='function ne() { docker run --rm -v "$(pwd)/`dirname ${@:$#}`":/ne/input -it alexjc/neural-enhance ${@:1:$#-1} "input/`basename ${@:$#}`"; }; ne'
for x in ./originali/*.jpg; do
    #echo $x
    enhance --zoom=1 --model=repair $x
done

e mettendo a confronto le coordinate degli stessi aruco tags nel set jpg ed in quello elaborato dalla rete neurale e salvato in png

Per dare un'idea la prima immagine e' un originale in JPG

 


la seconda e' la stessa immagine processata dalla rete neurale e salvata in PNG


 

Nei grafici sottostanti i risultati (nei grafici rosso=set PNG, blu=set JPG)

In sintesi le coordinate dei tag sono molto simili ma

1) il dato PNG non ha mostrato outliers ed errori come invece quello JPG

2) nel set PNG il riconoscimento di tag lontani era circa il doppio rispetto al set JPG

3) a parte i punti 1 e 2 il processing tramite rete neurale ma non ha migliorato in modo sensibile la qualita' dell'algoritmo di posizionamento dei tags


 






 

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




martedì 27 giugno 2023

Confronto ArucoTags ed AprilTags

 Ho provato una comparazione sulla stabilita' della misura di distanza usando Aruco Tags (con Opencv) e AprilTags (con AprilTag v2 e v3 modificata per avere la pose estimation)

Sono state acquisite 576 immagini con una camera Reolink E1 Pro (con immagini sia notturne che diurne) di due tag delle medesime dimensioni (4x4_100 per Aruco e 36h11 per Apriltag 10 cm)

Le nuove versioni di OpenCV hanno modificate le API per cui gli script che ho usato l'anno scorso non funzionano piu'. Per fare prima ho usato il docker sottostante che monta OpenCV 4.5.5

docker run -it -v /home/luca/ottico/:/home/ottichdgigante/python-opencv:4.5.5-debian  sh




OpenCV ed Aruco mostrano outliers, Apriltag3 ne mostra solo uno mentre Apriltag 2 ha mostrato dati molto piu' stabili)




Rimossi gli outlier si evidenzia che l'errore quadratico medio di Arpriltag e' circa la meta' di quella di Aruco (l'errore quadratico  migliore e' circa lo 0,3 % della distanza)






mercoledì 14 giugno 2023

Aruco calibration file format

 Ho provato a vedere se effettuare la calibrazione di tag Aruco con immagini in formato raw lossless od in formato jpg (lossy) poteva influenzare l'errore finale




Per fare cio' ho preso un telefono Android che permette di salvare la stessa immagine in formato DNG ed in formato JPG 

Lo script di calcolo e' il seguente

import numpy as np
import cv2
import cv2.aruco as aruco

# Aruco parameters
aruco_dict = aruco.Dictionary_get(aruco.DICT_4X4_50)
aruco_params = aruco.DetectorParameters_create()

# Chessboard parameters
num_chessboard_corners_horizontal = 9
num_chessboard_corners_vertical = 6
chessboard_square_size = 0.025  # in meters

# Image directory and file extension
image_directory = 'path_to_images_directory/'
image_extension = '.jpg'

# Arrays to store object points and image points
obj_points = []  # 3D points in real-world coordinates
img_points = []  # 2D points in image plane

# Generate chessboard object points
chessboard_size = (num_chessboard_corners_horizontal,
num_chessboard_corners_vertical)
objp = np.zeros((num_chessboard_corners_horizontal *
num_chessboard_corners_vertical, 3), np.float32)
objp[:, :2] = np.mgrid[0:num_chessboard_corners_horizontal,
0:num_chessboard_corners_vertical].T.reshape(-1, 2)
objp = objp * chessboard_square_size

# Iterate through images and find chessboard corners
image_count = 0
while True:
    # Load image
    image_path = image_directory + str(image_count) + image_extension
    image = cv2.imread(image_path)
    if image is None:
        break

    # Convert to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Find chessboard corners
    ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)

    # If corners found, add object points and image points
    if ret == True:
        obj_points.append(objp)
        img_points.append(corners)

        # Draw and display corners
        cv2.drawChessboardCorners(image, chessboard_size, corners, ret)
        cv2.imshow('Chessboard Corners', image)
        cv2.waitKey(500)

    image_count += 1

cv2.destroyAllWindows()

# Perform Aruco calibration
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points,
img_points, gray.shape[::-1], None, None)

# Calculate reprojection error
mean_error = 0
for i in range(len(obj_points)):
    img_points_proj, _ = cv2.projectPoints(obj_points[i], rvecs[i],
tvecs[i], mtx, dist)
    error = cv2.norm(img_points[i], img_points_proj, cv2.NORM_L2) /
len(img_points_proj)
    mean_error += error

calibration_error = mean_error / len(obj_points)
print("Calibration error: {}".format(calibration_error))

# Estimate additional error
reproj_error = 0
total_points = 0
for i in range(len(obj_points)):
    img_points_proj, _ = cv2.projectPoints(obj_points[i], rvecs[i],
tvecs[i], mtx, dist)
    error = cv2.norm(img_points[i], img_points_proj, cv2.NORM_L2)
    reproj_error += error
    total_points += len(obj_points[i])

additional_error = reproj_error / total_points
print("Additional error: {}".format(additional_error))

I risultati sono i seguenti (per i file DNG ho usato la libreria rawpy)

JPG

python calibration.py --dir ./jpg/ --square_size 0.015  -w 9 -t 6
Calibration error: 0.13602731796497697
Additional error: 0.13602731796497697

DNG

Calibration error: 0.13606447706803765

Additional error: 0.13606447706803765

In conclusione non si ha una significativa differenza di errore nell'usare JPG o DNG

venerdì 18 novembre 2022

Compressione immagine per Aruco Tags

Per il progetto Aruco ho provato ad acquisire un fotogramma da una webcam  e salvarlo in diversi formati con diverso grado di compressione. Di sotto si riportano i risultati (ingrandire le immagini per vedere gli artefatti di compressione)


import cv2
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH,1280)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,720)
compression_params = [cv2.IMWRITE_PNG_COMPRESSION, 0] 
while True:
    return_value,image = camera.read()
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    cv2.imshow('image',gray)
    if cv2.waitKey(1)& 0xFF == ord('s'):
        cv2.imwrite('test_0.png',image,[cv2.IMWRITE_PNG_COMPRESSION,0])
        cv2.imwrite('test_3.png',image,[cv2.IMWRITE_PNG_COMPRESSION,3])
        cv2.imwrite('test_9.png',image,[cv2.IMWRITE_PNG_COMPRESSION,9])
        cv2.imwrite('test_100.jpg',image,[cv2.IMWRITE_JPEG_QUALITY,100])
        cv2.imwrite('test_060.jpg',image,[cv2.IMWRITE_JPEG_QUALITY,60])
        cv2.imwrite('test_060.ppm',image,[cv2.IMWRITE_PXM_BINARY,1])
        break
camera.release()
cv2.destroyAllWindows()



PNG compressione 0


PNG compressione 3


PNG compressione 9


JPG quality 60



JPG quality 100



Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...