6

Sto cercando di realizzare un programma di visione artificiale in cui rilevare rifiuti e rifiuti casuali in uno sfondo rumoroso come la spiaggia (rumoroso a causa della sabbia).In caso di difficoltà nel rilevamento di piccoli oggetti su uno sfondo rumoroso. Qualche modo per risolvere questo problema?

Immagine originale:

enter image description here

Algoritmo di Canny senza alcuna elaborazione delle immagini:

enter image description here

mi rendo conto che una certa combinazione di tecniche di elaborazione delle immagini mi aiuterà a raggiungere il mio obiettivo di ignorando lo sfondo sabbioso rumoroso e rilevare tutti i rifiuti e gli oggetti sul terreno.

ho cercato di preforme mediana sfocatura, giocare e regolare i parametri, e mi ha dato questo:

enter image description here

E preforme bene in termini di ignorare il fondo di sabbia, ma non riesce a rilevare una certa degli altri molti oggetti sul terreno, probabilmente perché è sfocato (non troppo sicuro).

Esiste un modo per migliorare il mio algoritmo o le tecniche di elaborazione delle immagini che ignorano il rumore di fondo sabbioso mentre consentono il rilevamento dei bordi per trovare tutti gli oggetti e fanno in modo che il programma rilevi e disegni i contorni su tutti gli oggetti.

Codice:

from pyimagesearch.transform import four_point_transform 
from matplotlib import pyplot as plt 
import numpy as np 
import cv2 
import imutils 

im = cv2.imread('images/beach_trash_3.jpg') 


#cv2.imshow('Original', im) 

# Histogram equalization to improve contrast 




### 
#im = np.fliplr(im) 

im = imutils.resize(im, height = 500) 

imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 

# Contour detection 
#ret,thresh = cv2.threshold(imgray,127,255,0) 

#imgray = cv2.GaussianBlur(imgray, (5, 5), 200) 
imgray = cv2.medianBlur(imgray, 11) 

cv2.imshow('Blurred', imgray) 

''' 
hist,bins = np.histogram(imgray.flatten(),256,[0,256]) 
plt_one = plt.figure(1) 
cdf = hist.cumsum() 
cdf_normalized = cdf * hist.max()/ cdf.max() 

cdf_m = np.ma.masked_equal(cdf,0) 
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min()) 
cdf = np.ma.filled(cdf_m,0).astype('uint8') 
imgray = cdf[imgray] 

cv2.imshow('Histogram Normalization', imgray) 
''' 
''' 
imgray = cv2.adaptiveThreshold(imgray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\ 
      cv2.THRESH_BINARY,11,2) 
''' 

thresh = imgray 

#imgray = cv2.medianBlur(imgray,5) 
#imgray = cv2.Canny(imgray,10,500) 
thresh = cv2.Canny(imgray,75,200) 
#thresh = imgray 
cv2.imshow('Canny', thresh) 


contours, hierarchy = cv2.findContours(thresh.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 

cnts = sorted(contours, key = cv2.contourArea, reverse = True)[:5] 

test = im.copy() 
cv2.drawContours(test, cnts, -1,(0,255,0),2) 
cv2.imshow('All contours', test) 

print '---------------------------------------------' 
##### Code to show each contour ##### 
main = np.array([[]]) 
for c in cnts: 
    epsilon = 0.02*cv2.arcLength(c,True) 
    approx = cv2.approxPolyDP(c,epsilon,True) 

    test = im.copy() 
    cv2.drawContours(test, [approx], -1,(0,255,0),2) 
    #print 'Contours: ', contours 
    if len(approx) == 4: 
     print 'Found rectangle' 
     print 'Approx.shape: ', approx.shape 
     print 'Test.shape: ', test.shape 

     # frame_f = frame_f[y: y+h, x: x+w] 
     frame_f = test[approx[0,0,1]:approx[2,0,1], approx[0,0,0]:approx[2,0,0]] 

     print 'frame_f.shape: ', frame_f.shape 
     main = np.append(main, approx[None,:][None,:]) 
     print 'main: ', main 


    # Uncomment in order to show all rectangles in image 
    #cv2.imshow('Show Ya', test) 


    #print 'Approx: ', approx.shape 
    #cv2.imshow('Show Ya', frame_f) 
    cv2.waitKey() 
print '---------------------------------------------' 
cv2.drawContours(im, cnts, -1,(0,255,0),2) 
print main.shape 
print main 
cv2.imshow('contour-test', im) 
cv2.waitKey() 
+0

Non sono sicuro che la domanda sia off-topic in quanto sembra chiedere consigli su quale algoritmo utilizzare. –

+0

Ok, l'ho svalutato. –

+1

prova a sfocare e canny sull'immagine HSV (canale H) anziché sull'immagine in scala di grigi. E/o usare un filtro bilaterale invece della mediana. – Micka

risposta

3

quello che sto capendo dal tuo problema è: vuoi segmentare gli oggetti in primo piano da uno sfondo che è di natura variabile (il livello di grigio sabbia dipende da molte altre condizioni).

ci sono vari modi per affrontare questo tipo di problema:

Approccio 1:

Dalla vostra immagine una cosa è chiaro che, pixel colore di sfondo sarà sempre molto di più in numero di primo piano, più semplice metodo per iniziare la segmentazione iniziale è:

  1. Convertire l'immagine in grigio.
  2. Crea il suo istogramma.
  3. Trova l'indice di picco dell'istogramma, cioè l'indice con i pixel massimi.

sopra tre punti che danno un'idea di fondo MA il gioco non è finisce qui, ora si può mettere questo valore di indice al centro e prendere un intervallo di valori attorno ad esso come 25 sopra e sotto, per esempio: se il tuo indice di picco è 207 (come nel tuo caso) scegli un intervallo di livelli di grigio da 75 a 225 e immagine di soglia, Come per la natura dello sfondo sopra il metodo può essere usato per il rilevamento di oggetti in primo piano, dopo la segmentazione devi eseguire alcune fasi di post-elaborazione come l'analisi morfologica per segmentare diversi oggetti dopo l'estrazione di oggetti, è possibile applicare alcune classificazioni per un livello di segmentazione più fine per rimuovere i falsi positivi.

Approccio 2:

Gioca con alcune statistiche dei pixel dell'immagine, come fare un piccolo insieme di dati di valori di grigio e

  1. etichettarli classe 1 e 2, ad esempio, 1 per la sabbia e 2 per primo piano,
  2. Trova media e varianza (deviazione standard) di pixel da entrambe le classi e calcola anche la probabilità per entrambe le classi (num_pix_per_class/total_num_pix), ora memorizza queste statistiche per un utilizzo futuro,
  3. Ora torna all'immagine e prendi ogni pixel uno per uno e applica un pdf gaussiano: 1/2 * pi sigma (exp (- (pix - media)/2 * sigma)); al posto della media metti la media calcolata prima e al sigma metti la deviazione std calcolata in precedenza.
  4. Dopo aver applicato la fase 3, si otterrà un valore di due probabilità per ciascun pixel per due classi, basta scegliere la classe che ha una probabilità maggiore.

Approccio 3:

Approach 3 è più complessa di quanto sopra due: è possibile utilizzare alcune texture funzionamento base di segmentare la sabbia tipo di texture, ma per l'applicazione di metodo basato trama mi consiglia classificazione supervisionata di senza supervisione (come k-significa). caratteristica consistenza diversa che è possibile utilizzare sono:

base:

  1. gamma di livelli di grigio in un quartiere definito.
  2. media locale e varianza o entropia.
  3. Matrici co-occorrenza livello grigio (GLCM).

avanzata:

  1. locali Patterns binari.
  2. Trasformata Wavelet.
  3. Gabor Transform. ecc

PS: A mio parere si dovrebbe dare una prova di avvicinarsi 1 e 2. si può risolvere molto lavoro. :)

2

Per ottenere risultati migliori si dovrebbe applicare molti algoritmi. Le esercitazioni di OpenCV si concentrano sempre su una funzionalità di OpenCV. Le vere applicazioni CV dovrebbero usare il maggior numero possibile di tecniche e algoritmi.

ho usato per rilevare le cellule biologiche in immagini rumorosi e ho guadagnato ottimi risultati applicando alcune informazioni contestuali:

  • dimensioni previsto di cellule
  • Il fatto che tutte le cellule hanno dimensioni simili
  • Numero previsto di celle Così ho cambiato molti parametri e ho cercato di rilevare quello che stavo cercando.

Se si utilizza il rilevamento dei bordi, la sabbia fornirebbe forme piuttosto casuali. Prova a cambiare i parametri canny e rilevare linee, rects, cerchi, ets. - qualsiasi forma più probabile per i rifiuti. Ricordare le posizioni degli oggetti rilevati per ciascun set di parametri e al e dare la priorità a quelle posizioni (aree) in cui le forme sono state rilevate la maggior parte delle volte.

Utilizzare la separazione dei colori. I picchi nell'istogramma del colore potrebbero essere i suggerimenti per la lettiera, poiché la distribuzione dei colori della sabbia dovrebbe essere più uniforme.

Per alcuni oggetti di piccole dimensioni, come mozziconi di sigarette, è possibile applicare object matching.

P.S: Cool application! Per curiosità, stai andando a scansionare la spiaggia con un quadricottero?

+0

avete altri riferimenti su come combinare sistematicamente più rivelatori? – Micka

+1

No. Alcune parti che ho hardcoded, per alcune parti ho usato SVM. All'inizio ho passato molto tempo a cercare "la soluzione pronta all'uso" in OpenCV per "non reinventare la ruota". Finalmente ho usato una combinazione del mio codice con OpenCV. Più tardi un esperto di OpenCV mi ha confermato, per non prendere letteralmente OpenCV. Non possono aver pensato a tutti i casi d'uso. Ho persino implementato la selezione automatica delle funzionalità per poter considerare le informazioni contestuali o di dominio. –

0

Se si desidera rilevare oggetti su uno sfondo uniforme, è necessario iniziare rilevando il colore principale nell'immagine. In questo modo scoprirai tutta la sabbia e gli oggetti saranno nelle parti rimanenti. Puoi dare un'occhiata agli articoli pubblicati da Arnaud LeTrotter e Ludovic Llucia che hanno entrambi usato questo tipo di "rilevamento del colore principale".

+1

Lo sfondo non è affatto uniforme! La sabbia può essere asciutta o bagnata, il colore della sabbia può essere diverso. Gli shaddows, l'ora del giorno cambieranno considerevolmente il colore, ecc. –

+0

Dovrebbe essere uniforme per una determinata immagine! L'algoritmo che usano è calcolato su ogni immagine, non una volta per tutte. – FiReTiTi

Problemi correlati