venerdì 1 novembre 2024

Misuratore di torbidita' TS-300B

Gia' siamo partiti male....ordinato su Aliexpress (costato 1/3 rispetto ad Amazon) ed il cavo di collegamento ha 3 pin....

 


 mentre il connettore sulla scheda ha 4 pin (ed ovviamente il cavo non entra)

 


Il problema e' dal lato scheda ... sulla scheda i pin sono nominati ADVG (dall'alto verso il basso) per l'ingresso del TS-300B e GTV per il lato di connessione verso Arduino

 


incrociando le informazioni con altre schede simili il pinout e'

A = analog input

D = soglia digitale level output

V = Power Positive

G = GND

mentre per il lato arduino

G = GND

T = segnale

V = Vcc  (e' un sensore che deve essere alimentato a 5 V)

Il sensore ha due led L2 che mostra la presenza di alimentazione ed il led L1 che si illumina quando si raggiunge la soglia di tordibita'

Il funzionamento e' semplice...da un lato c'e' un led IR e dall'altro un ricevitore...a seconda di quanta luce arriva al ricevitore viene stimata la torbidita'...visto cio' il sensore e' sensibile alla luce ambientale (deve quindi lavorare al buio ancora meglio dentro ad un tubo)


Leggendo ho trovato che questo tipo di sensori vengono usati in lavastoviglie


 

 

 

 

 

mercoledì 30 ottobre 2024

Polarita' Lipo e JST

Ho imparato a mie spese che non tutte le batterie LiPo hanno la polarita' connessa nello stesso modo al connettore JST

Come si vede nella foto sottostante una LiPo e' connessa in modo corretto ad una Arduino MKR (positivo a sinistra) Nella stessa foto si vede il connettore di un'altra batteria con positivo a destra ...e meno male che non si' bruciata la scheda


In ogni caso i connettori JST con un po' di pazienza di possono smontare ed invertire i cavi

lunedì 21 ottobre 2024

Change detection monocular metric

Ho provato ad usare la rete di neurale a questo indirizzo https://github.com/apple/ml-depth-pro per ottenere una mappa di profondita' da un unico jpg

 Questa l'immagine di partenza


con una NVidia 4070 l'elaborazione e' inferiore al secondo e questo il risultato
 

La rete viene definita metrica ma i risultati sono lontanissimi dalle misure reali degli oggetti fotografati

Se si prendono due immagini distanti nel tempo



 si puo' calcolare la differenza delle distanze ed eventuali cambiamenti

 Una volta ottenuta la mappa di profondita' e' possibile avere anche la nuvola dei punti utilizzando il seguente programmino in Python

import open3d as o3d
import sys

a23 = np.load("agosto23.npz")
a24 = np.load("agosto24.npz")
dd = a24['depth']-a23['depth']

plt.imshow(dd, interpolation='nearest',cmap='plasma')
plt.colorbar()
#plt.show()
plt.savefig('grafico.png',dpi=600)


#versione O3D
depth = o3d.geometry.Image(a23['depth'])
print("Prof"+str(np.shape(depth)))
color = o3d.io.read_image("rgb.jpg")
print(np.shape(color))

rgbd = o3d.geometry.RGBDImage.create_from_color_and_depth(color, depth,convert_rgb_to_intensity = False)
intrinsic = o3d.camera.PinholeCameraIntrinsic(width=3840, height=2160, fx=2520.7, fy=2518.2, cx=1918, cy=1022)

pcd = o3d.geometry.PointCloud.create_from_rgbd_image(rgbd, intrinsic)
pcd.transform([[1,0,0,0],[0,-1,0,0],[0,0,-1,0],[0,0,0,1]])
o3d.visualization.draw_geometries([pcd])
o3d.io.write_point_cloud("nuvola2.ply", pcd)


questo il risultato






 

 

 

 

 


lunedì 14 ottobre 2024

Arduino 2009 dal passato

 Aprendo un cassetto e' saltato fuori questo progetto del 2010


Non si vede benissimo ma e' una Arduino 2009 (probabilmente un clone)

Inner Join con Pandas

 Avevo la necessita' di unire due file csv (misura di tempo; misura del sensore) ma i due sensori hanno avuto dei fermi per cui non era sufficiente mettere le colonne affiancate ed era necessaria una inner join (ma sulla macchine di lavoro non ho accesso un sql server) ..sono oltre 85000 dati quindi e' escluso fare a mano

La libreria Pandas e' venuta in aiuto




CSV Portata

tempo;valore
38923.54;37
38923.58;36
38923.63;36
38923.67;36

CSV Tordibita

tempo;valore
38923.54;0
38923.58;0


import pandas as pd
from matplotlib import pyplot as plt

por = pd.read_csv('portata.csv',sep=';')
tor = pd.read_csv('torbidita.csv',sep=';')
por['tempo'] = por['tempo'].astype(str)
tor['tempo'] = tor['tempo'].astype(str)

unione = por.merge(tor, on="tempo", how='inner')
unione.plot(
x='valore_x',
xlabel='Portata',
y='valore_y',
ylabel='Torbidita',
title= '25/07/06 - 27/02/2017',
kind='scatter'
)
plt.show()
#unione.to_csv("unione.csv", sep=';')


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ì 9 ottobre 2024

Cron in Docker

E' possibile attivare un crontab all'interno di un docker aggiungendo al Dockerfile i seguenti comandi


RUN apt-get -y install cron 

RUN crontab -l | { cat; echo "0 3 * * * bash /root/mioscript.sh"; } | crontab - 

CMD cron

Aggiornamento algoritmi di spectral unmxing

Durante il dottorato avevo provato a fare unmixing di suoli naturali Una discreta serie di campioni di suolo naturale era stato raccolto in ...