2016-02-17 7 views
12

Sto provando a contare automaticamente il numero di auto nell'immagine usando OpenCV e Python.Come conti le auto in OpenCV con Python?

enter image description here

Inizialmente ho pensato che avrei potuto fare questo con un po 'di segmentazione, ma non ho avuto molto successo. Poi ho pensato che una trasformazione di Hough potesse aiutare a calcolare il confine attorno alle auto, ma ha solo individuato le linee di parcheggio. L'unica cosa che posso pensare sarebbe iniziare ad allenare alcune partite su modelli di auto e non, ma spero che ci sia qualcosa di più semplice che farà bene qui. Ho provato anche il rilevamento dei bordi che sembra positivo, ma non sono davvero sicuro come continuare:

enter image description here

+0

hm, se raccogliendo le linee parcheggio, si potrebbe fare un po 'di segmentazione fino a quando il le dimensioni del parcheggio possono essere "date". Vale a dire, estrai le linee di parcheggio, verifica che si tratti di un punto con rapporto/dimensioni prestabilito, quindi controlla all'interno del punto se c'è un'auto esaminando l'area all'interno del punto, probabilmente usando un'analisi di uniformità o qualcosa del genere. – ABC

+0

Non posso presumere che ci saranno sempre linee di parcheggio. – nickponline

+0

in questo caso, la V dallo spazio colore HSV e fare un po 'di morfologico giocando intorno. Pubblicherò un codice rapido e rudimentale per iniziare. – ABC

risposta

1

codice MATLAB rapida che può essere facilmente convertito in python per ottenere iniziare ...

b = rgb2hsv(I); 
se = strel('rectangle', [2,4]); %# structuring element 
BW = b(:,:,3)>0.5; 
BW2 = bwareaopen(BW,30); 
BW3 = imerode(BW2, se); 
BW4 = imdilate(BW3, se); 
CC = bwconncomp(BW4); 

Da qui saprai di dover dare un'occhiata ai risultati put di CC e del rapporto larghezza/altezza del calcolo, dal momento che sai approssimativamente quanto sono grandi le automobili. Ecco il mio risultato in uscita da BW4.

enter image description here

2

Questo appare come una situazione in cui si consiglia di sfruttare le componenti di colore dell'immagine. Ovviamente, una soglia dritta sul valore medio di luminanza eliminerà le auto con vernice scura. Una possibilità sarebbe quella di esplorare le relazioni cromatiche (da rosso a verde, da blu a verde, da rosso a blu) e anche la saturazione. La tonalità probabilmente non ti darà molto in quanto la maggior parte delle auto è fortemente grigia.

Penso che il metodo di rilevamento dei bordi potrebbe funzionare se è possibile limitare la regione di interesse. Per ottenere un vantaggio migliore ed eliminare le linee di parcheggio utilizzare un filtro di erosione 2x2 sull'immagine a colori prima di eseguire il rilevamento dei bordi. Quindi mi consiglia di utilizzare un metodo di rilevamento dei bordi più forte (come sobel o prewitt). Si dovrebbe ottenere qualcosa di simile (miniera è eseguito su tutti i 3 canali dei colori):

3 channel sobel edge detect after erosion

Quindi è possibile convertire in binario se si vuole (non dovrebbe essere necessario) o semplicemente contare i pixel nelle pertinenti ROI.

ROIs

Se si sta tentando di creare qualcosa per le macchine fotografiche, più lotti, angolazioni multiple in movimento, allora si avrà bisogno di un sistema molto più complicato. Ma per una singola telecamera fissa, qualcosa del genere dovrebbe funzionare.

+0

La grande domanda, a proposito, si è divertita a giocarci. – BHawk

0

Le auto sono oggetti con un'alta densità di angoli, pertanto forniscono alcune informazioni aggiuntive per determinare se un'area dell'immagine può essere un'auto. Ho semplicemente usato

goodFeaturesToTrack 

con maxCorners = 10000, qualityLevel = 0,01 e minDistance = 1 e ottenuto questo risultato

detected corners on image

rispettivamente

detected corners

Questo solo è molto rumoroso ma forse puoi combinarlo con altri approcci di segmentazione.Ad esempio, è possibile calcolare un "rettangolo di dimensioni auto previsto" basato sulla segmentazione del colore e cercare tali rettangoli con un'alta densità di angoli. Quando hai una situazione molto strutturata come nell'immagine campione, "sai" dove dovrebbe essere una macchina, quindi puoi controllare solo queste aree.

5

Ok, quindi ... Probabilmente ho lavorato troppo su questo, ma mi è sembrato abbastanza semplice.

Per la mia implementazione ho deciso che sarebbe stato meglio trovare spazi di parcheggio vuoti e assumere che tutti gli altri spazi siano occupati. Per determinare se uno spot è vuoto, l'ho semplicemente paragonato a una porzione di spazio di parcheggio della strada. Ciò significa che questo stesso algoritmo dovrebbe funzionare sia chiaro che scuro, ecc. Perché il modello viene estratto direttamente dall'immagine.

A questo punto, eseguo solo la corrispondenza dei modelli (ho provato vari metodi, ma l'cv2.TM_CCORR_NORMED ha funzionato meglio). Questo dà un risultato decente, e ora dobbiamo elaborarlo.

enter image description here

ho creare il ROI (regioni di interesse) intorno le righe parcheggio. Poi li collasso su un singolo vettore prendendo le statistiche per colonna. Guardo il mezzo. enter image description here

È un indicatore abbastanza buono, è già possibile vedere chiaramente dove sono gli spazi vuoti. Ma le auto di colore scuro presentano ancora alcuni problemi, quindi ora decidiamo di guardare un'altra statistica, che dire della varianza? Il parcheggio è abbastanza costante in tutta la regione. Una macchina d'altra parte ha alcuni cambiamenti, le finestre, gli specchietti per il tetto creano qualche variazione. Quindi grafico la varianza "invertita". Quindi, piuttosto che nessun cambiamento con una varianza di 0, ha una varianza di 1. Assomiglia a questo enter image description here

Questo sembra piuttosto promettente! Ma sai cosa è ancora meglio? Combinare i due! quindi basta moltiplicarli insieme, ho chiamato questo risultato la "probabilità" poiché dovrebbe variare tra 0 e 1 enter image description here

Ora puoi davvero vedere la differenza tra uno spazio vuoto e un'auto scura. Quindi facciamo qualche semplice soglia. Questo è fantastico, ma non ti dà il NUMERO di veicoli/spazi vuoti. A questo punto passiamo attraverso la colonna "probabilità" per colonna, e cerchiamo un certo numero di pixel consecutivi oltre la soglia. Quanti pixel? circa tanti pixel di una macchina è ampia. Questo modello di tipo "isteresi" dovrebbe sopprimere eventuali picchi o punti di dati spuri.

E ora si parla tutti insieme, si assume il numero di spazi è costante (ipotesi ragionevole credo) e ci limitiamo a dire il number of cars = number of spaces - number of empty spaces e segnare l'immagine

enter image description here

e stampare alcuni risultati

found 24 cars and 1 empty space(s) in row 1 
found 23 cars and 0 empty space(s) in row 2 
found 20 cars and 3 empty space(s) in row 3 
found 22 cars and 0 empty space(s) in row 4 
found 13 cars and 9 empty space(s) in row 5 

e, naturalmente, il codice. Potrebbe non essere il più efficiente, ma sono in genere una persona MATLAB, la sua la mia prima OpenCV/progetto Python

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

# this just keeps things neat 
class ParkingLotRow(object): 
    top_left=None 
    bot_right=None 
    roi=None 
    col_mean=None 
    inverted_variance=None 
    empty_col_probability=None 
    empty_spaces=0 
    total_spaces=None 

    def __init__(self,top_left,bot_right,num_spaces): 
     self.top_left = top_left 
     self.bot_right = bot_right 
     self.total_spaces = num_spaces 

############################ BEGIN: TWEAKING PARAMETERS ########################################### 
car_width = 8  #in pixels 
thresh = 0.975  #used to determine if a spot is empty 
############################### END: TWEAKING PARAMETERS ########################################### 
parking_rows = [] 

# defines regions of interest, row 1 is on top, row 5 is on bottom, values determined empirically 
parking_rows.append(ParkingLotRow(( 1, 20),(496, 41),25))  #row 1 
parking_rows.append(ParkingLotRow(( 1, 87),(462,105),23))  #row 2 
parking_rows.append(ParkingLotRow(( 1,140),(462,158),23))  #row 3 
parking_rows.append(ParkingLotRow(( 1,222),(462,240),22))  #row 4 
parking_rows.append(ParkingLotRow(( 1,286),(462,304),22))  #row 5 

#read image 
img = cv2.imread('parking_lot.jpg') 
img2 = img.copy() 

#creates a template, its jsut a car sized patch of pavement 
template = img[138:165,484:495] 
m, n, chan = img.shape 

#blurs the template a bit 
template = cv2.GaussianBlur(template,(3,3),2) 
h, w, chan = template.shape 

# Apply template Matching 
res = cv2.matchTemplate(img,template,cv2.TM_CCORR_NORMED) 
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) 

top_left = max_loc 
bottom_right = (top_left[0] + w, top_left[1] + h) 
#adds bounding box around template 
cv2.rectangle(img,top_left, bottom_right, 255, 5) 

#adds bounding box on ROIs 
for curr_parking_lot_row in parking_rows: 
    tl = curr_parking_lot_row.top_left 
    br = curr_parking_lot_row.bot_right 

    cv2.rectangle(res,tl, br, 1, 5) 

#displays some intermediate results 
plt.subplot(121),plt.imshow(res,cmap = 'gray') 
plt.title('Matching Result'), plt.xticks([]), plt.yticks([]) 
plt.subplot(122),plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)) 
plt.title('Original, template in blue'), plt.xticks([]), plt.yticks([]) 

plt.show() 

curr_idx = int(0) 

#overlay on original picture 
f0 = plt.figure(4) 
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB)),plt.title('Original') 


for curr_parking_lot_row in parking_rows: 
    #creates the region of interest 
    tl = curr_parking_lot_row.top_left 
    br = curr_parking_lot_row.bot_right 

    my_roi = res[tl[1]:br[1],tl[0]:br[0]] 

    #extracts statistics by column 
    curr_parking_lot_row.col_mean = np.mean(my_roi, 0) 
    curr_parking_lot_row.inverted_variance = 1 - np.var(my_roi,0) 
    curr_parking_lot_row.empty_col_probability = curr_parking_lot_row.col_mean * curr_parking_lot_row.inverted_variance 

    #creates some plots 
    f1 = plt.figure(1) 
    plt.subplot('51%d' % (curr_idx + 1)),plt.plot(curr_parking_lot_row.col_mean),plt.title('Row %d correlation' %(curr_idx + 1)) 

    f2 = plt.figure(2) 
    plt.subplot('51%d' % (curr_idx + 1)),plt.plot(curr_parking_lot_row.inverted_variance),plt.title('Row %d variance' %(curr_idx + 1)) 

    f3 = plt.figure(3) 
    plt.subplot('51%d' % (curr_idx + 1)) 
    plt.plot(curr_parking_lot_row.empty_col_probability),plt.title('Row %d empty probability ' %(curr_idx + 1)) 
    plt.plot((1,n),(thresh,thresh),c='r') 

    #counts empty spaces 
    num_consec_pixels_over_thresh = 0 
    curr_col = 0 

    for prob_val in curr_parking_lot_row.empty_col_probability: 
     curr_col += 1 

     if(prob_val > thresh): 
      num_consec_pixels_over_thresh += 1 
     else: 
      num_consec_pixels_over_thresh = 0 

     if (num_consec_pixels_over_thresh >= car_width): 
      curr_parking_lot_row.empty_spaces += 1 

      #adds mark to plt 
      plt.figure(3) # the probability graph 
      plt.scatter(curr_col,1,c='g') 

      plt.figure(4) #parking lot image 
      plt.scatter(curr_col,curr_parking_lot_row.top_left[1] + 7, c='g') 

      #to prevent doubel counting cars, just reset the counter 
      num_consec_pixels_over_thresh = 0 

    #sets axis range, apparantlly they mess up when adding the scatters 
    plt.figure(3) 
    plt.xlim([0,n]) 

    #print out some stats 
    print('found {0} cars and {1} empty space(s) in row {2}'.format(
     curr_parking_lot_row.total_spaces - curr_parking_lot_row.empty_spaces, 
     curr_parking_lot_row.empty_spaces, 
     curr_idx +1)) 

    curr_idx += 1 

#plot some figures 
plt.show()