2012-10-30 13 views
5

Ho la seguente immagine rectangle pattern boardrilevare rettangoli sfocate su grayscaleimage multimodale

Sto cercando di trovare le coordinate dei pixel di rettangoli principali (quelle tra le linee bianche). Ho provato poche cose ma non riesco a ottenere una soluzione sufficientemente buona. La soluzione non deve essere perfetta ed è ok se non vengono rilevati tutti i rettangoli (specialmente quelli veramente piccoli). Anche se la posizione degli angoli dovrà essere il più precisa possibile, specialmente con quelle più grandi sfocate (sto provando a scrivere un semplice motore AR).

posso chiarire ci sono solo 4 livelli di scala di grigi: 0, 110, 180 e 255 (in caso di stampa, nessuno schermo varierà a causa di un fulmine e ombre)

Finora ho provato alcune cose:

  1. manuale sogliatura multilivello (a causa delle ombre e diversi fulmini non funzionava)
  2. adaptive thresholding: 2 problemi:
    • unisce 180 e 255 colori al bianco, e 0, 110 in nero
    • bordo/posizione d'angolo del sfocate rettangoli (più grandi) non è esatto (si aggiunge sfocatura al rettangolo dell'area)
  3. rilevamento dei bordi Sobel (angoli di rettangoli sfocate sono più taglienti , ma rileva anche bordi interni in rettangoli, anche tali contorni di bordo non sono sempre chiusi

Sembra combinando quei due pensa qualche modo produrrebbe risultati migliori. O forse qualcuno ha un'idea diversa?

Stavo pensando anche a fare inondazioni, ma era difficile trovare automaticamente un buon punto di semina e una soglia (potrebbero esserci altri oggetti bianchi in background). Inoltre, voglio ottimizzare in seguito questo per l'algoritmo GPU e la piena non è una buona idea per questo.

Di seguito è riportato un codice di esempio ho provato finora:

image = cv2.imread('data/image.jpg'); 
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) 
cv2.imshow('image', gray) 


adaptive = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 601, 0) 
cv2.imshow('adaptive', adaptive) 


gradx = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=3) 
grady = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=3) 
abs_gradx = cv2.convertScaleAbs(grady) 
abs_grady = cv2.convertScaleAbs(grady) 
grad = cv2.addWeighted(abs_gradx, 0.5, abs_grady, 0.5, 0) 

kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5)) 
grad = cv2.morphologyEx(grad, cv2.MORPH_OPEN, kernel) 
grad = cv2.morphologyEx(grad, cv2.MORPH_CLOSE, kernel) 
cv2.imshow('sobel',grad) 


#kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(7,7)) 
#grad = cv2.morphologyEx(grad, cv2.MORPH_OPEN, kernel) 
retval, grad = cv2.threshold(grad, 10, 255, cv2.THRESH_BINARY) 
cv2.imshow('sobel+morph+thrs',grad) 

cv2.waitKey() 
+1

Hai considerato il rilevamento degli angoli? – Junuxx

+0

sì, ho provato beneFeaturesToTrack e lì dove molti falsi-possessi – pzo

+1

Giusto per chiarire l'obiettivo. Hai grandi strisce bianche che delineano quadrati, che sono pieni di rettangoli (alcuni dei quali sono anche quadrati). Vuoi gli angoli dei grandi quadrati, gli angoli dei piccoli rettangoli che riempiono i quadrati o entrambi? – Hammer

risposta

3

Credo che la vostra risposta sta nell'uso della trasformata di Hough per rilevare le linee, che si estende queste righe per attraversare le pause tra le piazze più scuri, e quindi alla ricerca di interseca marcatura fuori angoli. Ho avuto un gioco veloce in Matlab e sono venuto su con le seguenti, non è perfetto, ma dovrebbe mostrare il potenziale:

% Open image 
i = imread('http://i.stack.imgur.com/kwcXm.jpg'); 

% Use a sharpening filter to enhance some of the edges 
H = fspecial('unsharp'); 
i = imfilter(i, H, 'replicate'); 
% Detect edge segments using canny 
BW = edge(i, 'canny'); 

% Apply hough transform to edges 
[H, T, R] = hough(BW, 'RhoResolution', 0.5, 'Theta', -90:0.5:89.5); 
% Find peaks in hough transform 
P = houghpeaks(H, 5, 'threshold', ceil(0.1*max(H(:)))); 
% Extract lines from peaks, extending partial lines 
lines = houghlines(BW, T, R, P, 'FillGap', 100, 'MinLength', 5); 

% Plot detected lines on image 
imshow(i); hold on; 
for k = 1:length(lines) 
    xy = [lines(k).point1; lines(k).point2]; 
    plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green'); 
end 

Con il risultato finale:

Final Result

Ovviamente c'è spazio per il miglioramento, con un numero di linee ancora da rilevare, ma se modificando i vari parametri non funziona si potrebbe prendere il risultato iniziale e la ricerca di più linee con angoli simili per ottenere un set più completo. Gli angoli possono quindi essere trovati dagli intersecati che dovrebbero essere abbastanza semplici da estrarre.

0

vorrei provare il seguente:

  • Hough transform per rilevare tutte le linee rette
  • Cercare serie di linee parallele che sono :
    • Una distanza sufficiente tra
    • S eparated dal colore più chiaro

Ci sono un paio di cose che rendono il vostro problema più complicato di quello che deve essere:

  • distorsione prospettica
  • cambiamenti di illuminazione, ombre minori

Se si riesce a ridurre al minimo quanto sopra, può aiutare a risolvere il problema.

Problemi correlati