OpenCV & Python – Canny Edge Detection

Introduzione

Ecco come promesso, un altro articolo della lunga serie di articoli riguardanti il mondo di OpenCV e della programmazione con Python. In un precedente articolo abbiamo già visto il concetto di edge detection, in questo articolo analizzeremo insieme un particolare algoritmo chiamato Canny Edge Detection.

Se vuoi sapere di più, questo è l’articolo precedente:

The Canny Edge Detection

Canny Edge Detection

Nella panoramica degli algoritmi sviluppati per la edge detection, il Canny Edge Detection è abbastanza popolare e deve il suo nome proprio a chi lo ha sviluppato, John F. Canny.

Questo algoritmo ha una serie di caratteristiche interessanti, infatti è un algoritmo a più stadi

  • Noise Reduction
  • Ricerca del gradiente di intensità
  • Non-Maximum soppression
  • Hysteresis Thresholding

Il primo stadio richiede la rimozione del rumore di fondo dell’immagine (Noise Reduction), dato che la edge detection può essere molto influenzata dalla sua presenza. Quindi si utilizza un filtro Gaussiano 5×5 per la rimozione (riduzione) del rumore di fondo.

Poi il secondo stadio coinvolge la ricerca del gradiente di intensità dell’immagine (Intensity Gradient). L’immagine viene filtrata con un kernel Sobel sia in direzione verticale che orizzontale ottenendo così le derivate prime nelle due direzioni (Gx e Gy). Da queste due immagini, si trova poi l’edge gradient G.

\mathbf {G} ={\sqrt {{\mathbf {G} _{x}}^{2}+{\mathbf {G} _{y}}^{2}}}

e la direzione del gradiente per ciascun pixel

\mathbf {\Theta } =\operatorname {atan2} \left(\mathbf {G} _{y},\mathbf {G} _{x}\right)

,

La direzione del gradiente è sempre perpendicolare agli edge. Viene arrotondato ad 1 per i quattro angoli che rappresentano le due direzioni diagonali, e quella verticale ed orizzontale.

Lo stadio successivo è la Non-maximum Suppression, in cui alcuni pixel indesiderati vengono rimossi in modo che non potranno essere confusi come edge. Per fare ciò, viene analizzata l’intera immagine, controllando se ciascun pixel è un massimo locale nella direzione del gradiente relativamente alla sua area.

Se osserviamo la figura sopra, vediamo l’analisi del punto A. Questo punto si trova sull’edge considerato nella direzione verticale. Sappiamo che la direzione del gradiente è perpendicolare all’edge. Quindi analizziamo i punti B e C che si trovano sulla direzione del gradiente. A questo punto, il punto A viene analizzato insieme ai punti B e C per vedere se forma un massimo locale. Se lo forma, allora viene considerato nel prossimo stadio, altrimenti viene rimosso, ponendolo a valore zero.

Infine l’ultimo stadio è l’applicazione di una soglia di isteresi (Hysteresis Thresholding). In questo stadio finale si decide veramente quali edge sono realmente tali e quali non lo sono affatto. Per questa operazione è necessario stabilire due valori di soglia, uno minimo minVal, e uno massimo maxVal.  Qualsiasi edge con un gradiente di intensità maggiore di maxVal sarà sicuramente un edge, e quelli con un valore minore di min Val non lo saranno affatto, e verranno scartati. Per tutti gli altri edge che si trovassero nel range tra questi due valori di soglia vengono sottoposti ad una ulteriore analisi, stabilendo se siano tali attraverso la loro connettività. Se essi sono connessi ad un edge di quelli già accertati allora viene anch’esso considerato come tale, altrimenti scartato.

Canny Edge Detection - Hysteresis Thresholding

Prerequisiti prima di cominciare a programmare

Per eseguire il codice presente in questo articolo sono necessari alcuni prerequisiti. Per prima cosa è necessario far partire l’ambiente virtuale su cui avete compilato ed installato la libreria OpenCV.

source ~/.profile
workon cv
(cv) $

Se non aveste ancora installato OpenCV, seguite la procedura di installazione descritta in questo articolo.

Inoltre in questo esempio per migliorare la visualizzazione di più immagini contemporaneamente, sfrutteremo la libreria grafica matplotlib. Se ancora non l’avete installata sul vostro ambiente virtuale potete farlo scrivendo

pip --no-cache-dir install matplotlib

poi installate il pacchetto TKinter necessario per il corretto funzionamento di matplotlib.

sudo apt-get install python-tk

Faremo qualche prova anche su un’immagine a colori e ricca di bordi e di gradienti di colore. Scaricate l’immagine seguente (se non l’avete già fatto negli esempi precedenti) e salvatela come logos.jpg.

Programmiamo con Python l’algoritmo Canny Edge Detection

In OpenCV, questo tipo di edge detection è già stata implementata e si attiva richiamando la funzione cv2.Canny().

cv2.Canny(image, minVal, maxVal)

Questa funzione accetta tre argomenti. Il primo argomento è proprio l’immagine da sottoporre ad analisi, il secondo ed il terzo argomento sono i valori di minVal e maxVal rispettivamente, di cui abbiamo parlato in precedenza.

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

img = cv2.imread('logos.jpg',0)
edges = cv2.Canny(img,100,110)

plt.subplot(2,1,1),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(2,1,2),plt.imshow(edges,cmap = 'gray')
plt.title('Canny Edge Detection'), plt.xticks([]), plt.yticks([])

plt.show()

Se eseguiamo il codice otterremo i risultati seguenti.

Altre prove sulle immagini

Passiamo ora ad effettuare l’analisi su una fotografia ricca di particolari e contorni. A tale proposito ho scelto gli ingranaggi di un orologio.

Utilizzerò questa immagine per vedere i bordi selezionati a seconda dei valori di thresholding minVal e maxVal. Ecco i risultati ottenuti.

Questi sono i bordi selezionati con i valori standard minVal = 100, maxVal = 200. Come possiamo vedere i contorni del meccanismo sono stati ben individuati.

Passando ad un threshold troppo altro, parecchi particolari vengono persi, e molti contorni diventano approssimativi. minVal = 300 maxVal = 350

Vediamo nel caso opposto, un threshold troppo basso fa passare troppi falsi contorni e l’immagine si arricchisce di troppi particolari inutili. minVal = 30 maxVal = 35.

Conclusione

Come hai visto in questo articolo, l’applicazione dell’algoritmo Canny Edge Detection è davvero molto semplice grazie proprio alla libreria OpenCV. In altri articoli della stessa serie, potrai approfondire ancora di più l’argomento della edge detection.

1 commento su “OpenCV & Python – Canny Edge Detection

  1. gionterra

    ciao a tutti!
    dato la mia estrema ignoranza nel campo della programmazione, e dopo vari tentativi di ricerca su web di software che rispondono alle mie esigenze, mi trovo a dover chiedere aiuto.
    vorrei trovare il modo di scattare delle foto tramite webcam o altro dispositivo di acquisizione ritagliarle e rinominarle in automatico, mi spiego, mantenendo la webcam fissa e usando uno sfondo neutro come un cartoncino colorato, posizionando al centro un oggetto da fotografare ( nel mio caso sono libri), vorrei ottenere come risultato un immagine dell’oggetto con una cornice (cartoncino) in percentuale o di alcuni px, in modo che si adatti il tutto alle dimensioni dell’oggetto che fotografo senza dover manualmente “zummare” o spostare la webcam manualmente ogni volta che fotografo un libro diverso in dimensioni da quello precedente. a tutto questo vorrei che fosse possibile, cosa meno difficile , associare un numero tipo codice a barre in maniera tale da scattare la foto e salvandola nominandola con il codice a barre
    potreste aiutarmi a trovare una soluzione?
    Grazie!!

Lascia un commento