Processus d’image pratique avec OpenCV
Le traitement d’image est essentiellement le processus qui nous permet d’obtenir les fonctionnalités des images. Le traitement d’image est appliqué pour les images et les vidéos. Ce sont les procédures fréquemment utilisées pour améliorer la réussite de la formation dans les structures d’apprentissage en profondeur.
Le traitement d’image commence par la reconnaissance des données par les ordinateurs. Tout d’abord, une matrice est créée pour les données au format image. Chaque valeur de pixel de l’image est traitée dans cette matrice. Par exemple, une matrice de taille 200×200 est créée pour une image de taille 200×200. Si cette image est colorée, cette dimension devient 200x200x3 (RVB). En fait, chaque manipulation dans le traitement d’image est une opération matricielle. Supposons qu’une opération de flou soit souhaitée sur l’image. Un filtre particulier se déplace sur toute la matrice qu’il apporte des modifications sur tous les éléments de la matrice ou une partie des éléments de la matrice. À la suite de ce processus, la partie requise ou l’ensemble de l’image devient floue.
Le traitement des images est nécessaire dans de nombreux cas [1]. Généralement, ces opérations sont appliquées aux données de format d’image qui seront utilisées dans les modèles d’apprentissage en profondeur. Par exemple, peu importe que les données soient colorées dans certains projets. Dans ce cas, l’utilisation d’images couleur pour la formation entraînera des pertes de performances. L’une des structures d’apprentissage en profondeur les plus utilisées du traitement d’image est les réseaux de neurones convolutifs. Ce réseau détermine les attributs requis pour la formation avec une couche convolutionnelle sur l’image. À ce stade, seules certaines parties des images qui seront utilisées pour la formation peuvent devoir être traitées. L’importance de lignes plus arrondies plutôt que les lignes nettes dans les images peut parfois améliorer le succès de la formation.
Dans de tels cas, des techniques de traitement d’image sont utilisées.
La même logique est basée sur les opérations des programmes d’optimisation d’image utilisés dans la vie quotidienne en plus des situations décrites ci-dessus. Il existe de nombreux processus dans le traitement d’image tels que l’amélioration de la qualité des images, la réalisation de restaurations sur les images, la suppression du bruit, l’égalisation de l’histogramme.
OpenCV est l’une des bibliothèques les plus populaires utilisées pour le traitement d’image [2]. Il existe de nombreuses entreprises qui utilisent OpenCV, telles que Microsoft, Intel, Google, Yahoo. OpenCV prend en charge une grande variété de langages de programmation tels que Java, C ++, Python et Matlab. Tous les exemples de ce travail qu’ils sont codés en Python.
import cv2
from matplotlib import pyplot as plt
import numpy as np
Premièrement, les bibliothèques sont importées. Certaines fonctions d’OpenCV ne fonctionnent pas de manière stable dans toutes les versions. L’une de ces fonctions est «imshow». Cette fonction nous permet de voir les changements dans l’image à la suite de nos opérations. La bibliothèque matplotlib sera utilisée comme solution alternative dans ce travail pour ceux qui ont de tels problèmes.
Les processus à effectuer seront appliqués sur l’image ci-dessus (figure 1). L’image est lue initialement pour pouvoir être traitée.
img_path = "/Users/..../opencv/road.jpeg"
img = cv2.imread(img_path)
print(img.shape)>>>(960, 1280, 3)
Les dimensions de l’image sont de 960 x 1280 pixels sur la figure 2. Nous voyons le résultat de 960x1280x3 lorsque nous voulons imprimer les dimensions après le processus de lecture. Une matrice a donc été créée aux dimensions de l’image et cette matrice se voit attribuer les valeurs de chaque pixel de l’image. Il y a 3 dimensions de RVB car l’image est colorée.
Si nous voulons convertir l’image en noir et blanc, la fonction cvtColor est utilisée.
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Si nous voulons voir le changement qui se produit à la suite de cette fonction, nous utilisons la fonction imshow de matplotlib.
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(gray_image)
plt.show()
print(gray_image.shape)>>>(960, 1280)
Comme le montre la figure 2, nous avons converti notre image en noir et blanc. Lorsque nous vérifions leurs dimensions, il n’y a plus 3 dimensions en raison du RVB.
Lorsque vous regardez les valeurs matricielles de l’image, nous voyons qu’elle se compose de valeurs comprises entre 0 et 255. Dans certains cas, nous pouvons souhaiter que cette matrice ne soit constituée que de valeurs 0 et 255 [3]. La fonction de seuil est utilisée dans de tels cas.
(thresh, blackAndWhiteImage) = cv2.threshold(gray_image, 20, 255, cv2.THRESH_BINARY)
(thresh, blackAndWhiteImage) = cv2.threshold(gray_image, 80, 255, cv2.THRESH_BINARY)
(thresh, blackAndWhiteImage) = cv2.threshold(gray_image, 160, 255, cv2.THRESH_BINARY)
(thresh, blackAndWhiteImage) = cv2.threshold(gray_image, 200, 255, cv2.THRESH_BINARY)
plt.imshow(blackAndWhiteImage)
plt.show()
Le premier paramètre requis par la fonction de seuil dans OpenCV est l’image à traiter. Le paramètre suivant est la valeur seuil. Le troisième paramètre est la valeur à laquelle nous voulons affecter les éléments de matrice qui dépassent la valeur seuil. Les effets de quatre valeurs de seuil différentes sont visibles sur la figure 3. Dans la première image (image 1), la valeur de seuil a été déterminée comme étant 20. Toutes les valeurs supérieures à 20 sont attribuées à 255. Les valeurs restantes sont mis à 0. Cela a permis que seules les couleurs noires ou très sombres soient noires et que toutes les autres teintes soient directement blanches. Les valeurs de seuil de l’image 2 et de l’image 3 ont été données à 80 et 160. Enfin, la valeur de seuil a été déterminée à 200 dans l’image 4. Contrairement à l’image 1, les couleurs blanches et très claires ont été assignées à 255, tandis que toutes les les valeurs restantes ont été définies sur 0 dans l’image 4. Les valeurs de seuil doivent être définies spécifiquement pour chaque image et pour chaque cas.
Une autre méthode utilisée dans le traitement d’image est le flou. Cela peut être accompli avec plus d’une fonction.
output2 = cv2.blur(gray_image, (10, 10))
plt.imshow(output2)
plt.show()
output2 = cv2.GaussianBlur(gray_image, (9, 9), 5)
plt.imshow(output2)
plt.show()
Comme le montrent les figures 4 et 5, l’image en noir et blanc est floue avec les filtres de flou et les degrés de flou spécifiés. Ce processus est généralement utilisé pour supprimer le bruit dans les images. De plus, dans certains cas, l’entraînement est gravement affecté en raison des lignes nettes des images. Il est disponible dans les cas où il est utilisé pour cette raison.
Dans certains cas, les données peuvent nécessiter une rotation pour une augmentation, ou des images à utiliser car les données peuvent être biaisées. Les fonctions suivantes peuvent être utilisées dans ce cas.
(h, w) = img.shape[:2]
center = (w / 2, h / 2)
M = cv2.getRotationMatrix2D(center, 13, scale =1.1)
rotated = cv2.warpAffine(gray_image, M, (w, h))
plt.imshow(rotated)
plt.show()
Tout d’abord, le centre de l’image est déterminé et la rotation est effectuée par ce centre. Le premier paramètre de la fonction getRotationMatrix2D est les valeurs centrales calculées. Le deuxième paramètre est la valeur d’angle. Enfin, le troisième paramètre est la valeur d’échelle à appliquer après la rotation. Si cette valeur est définie sur 1, elle fera pivoter la même image uniquement selon l’angle donné sans aucune mise à l’échelle.
Les méthodes mentionnées ci-dessus sont souvent utilisées ensemble dans les projets. Faisons un exemple de projet pour une meilleure compréhension de ces structures et processus.
Disons que nous voulons former un pilote de conduite autonome pour les véhicules [4]. Lorsque l’image de la figure 1 est examinée pour ce problème, notre pilote autonome devrait être capable de comprendre le chemin et les voies. Nous pouvons utiliser l’OpenCV pour ce problème. Étant donné que la couleur n’a pas d’importance dans ce problème, l’image est convertie en noir et blanc. Les éléments de matrice définissent les valeurs 0 et 255 par la valeur seuil déterminée. Comme mentionné ci-dessus dans l’explication de la fonction de seuil, la sélection de la valeur de seuil est critique pour cette fonction. La valeur de seuil est fixée à 200 pour ce problème. Nous pouvons éclaircir d’autres détails car il suffira de se concentrer sur les bords de route et les voies. Afin de se débarrasser du bruit, le flou est effectué avec la fonction GaussianBlur. Les parties jusqu’ici peuvent être examinées en détail à partir des figures 1 à 5.
Après ces processus, la détection des bords Canny est appliquée.
img = cv2.imread(img_path)
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(thresh, output2) = cv2.threshold(gray_image, 200, 255, cv2.THRESH_BINARY)
output2 = cv2.GaussianBlur(output2, (5, 5), 3)
output2 = cv2.Canny(output2, 180, 255)
plt.imshow(output2)
plt.show()
Le premier paramètre pris par la fonction Canny est l’image à laquelle l’opération sera appliquée. Le deuxième paramètre est la valeur de seuil bas et le troisième paramètre est la valeur de seuil haut. L’image est numérisée pixel par pixel pour la détection des contours. Dès qu’il existe une valeur inférieure à la valeur seuil basse, le premier côté du bord est détecté. Lorsqu’une valeur plus élevée est trouvée que la valeur de seuil plus élevée, l’autre côté est déterminé et le bord est créé. Pour cette raison, les valeurs des paramètres de seuil sont déterminées pour chaque image et pour chaque problème. Afin de mieux observer l’effet GaussianBlur, faisons les mêmes actions sans brouiller cette fois.
img = cv2.imread(img_path)
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(thresh, output2) = cv2.threshold(gray_image, 200, 255, cv2.THRESH_BINARY)
output2 = cv2.Canny(output2, 180, 255)
plt.imshow(output2)
plt.show()
Lorsque la fonction GaussianBlur n’est pas implémentée, le bruit est clairement visible sur la figure 8. Ces bruits peuvent ne pas être un problème pour notre projet, mais ils auront un grand impact sur la réussite de la formation dans différents projets et situations. Après cette étape, les processus sont effectués sur l’image réelle (standard) en fonction des bords déterminés. Les fonctions HoughLinesP et line sont utilisées pour cela.
lines = cv2.HoughLinesP(output2, 1, np.pi/180,30)
for line in lines:
x1,y1,x2,y2 = line[0]
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),4)
plt.imshow(img)
Comme le montre l’image de la figure 9, les limites des routes et les voies ont été bien réalisées. Cependant, lorsque la figure 9 est soigneusement examinée, certains problèmes seront constatés. Bien qu’il n’y ait eu aucun problème pour déterminer les limites des voies et des routes, les nuages étaient également perçus comme des limites des routes. La méthode de masquage doit être utilisée pour éviter ces problèmes [5].
def mask_of_image(image):
height = image.shape[0]
polygons = np.array([[(0,height),(2200,height),(250,100)]])
mask = np.zeros_like(image)
cv2.fillPoly(mask,polygons,255)
masked_image = cv2.bitwise_and(image,mask)
return masked_image
Nous pouvons faire le processus de masquage avec la fonction mask_of_image. Tout d’abord, la zone à masquer est déterminée comme un polygone. Les valeurs des paramètres sont des valeurs entièrement spécifiques aux données.
Le masque (figure 10) sera appliqué sur l’image réelle. Il n’y a aucun processus dans les régions correspondant à la zone noire de l’image réelle. Cependant, tous les processus ci-dessus sont appliqués aux zones correspondant à la zone blanche.
Comme le montre la figure 11, à la suite du processus de masquage, nous avons résolu le problème que nous avons vu dans les nuages.
Nous avons résolu le problème de reconnaissance de voie avec HougLinesP. Supposons que ce problème s’applique aux formes circulaires [6].
Créons un traitement d’image qui reconnaît les pièces de la figure 12. Dans ce cas, les méthodes utilisées dans le projet de reconnaissance des voies seront également utilisées ici.
img = cv2.imread("/Users/.../coin.png")
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(thresh, output2) = cv2.threshold(gray_image, 120, 255, cv2.THRESH_BINARY)
output2 = cv2.GaussianBlur(output2, (5, 5), 1)
output2 = cv2.Canny(output2, 180, 255)
plt.imshow(output2, cmap = plt.get_cmap("gray"))circles = cv2.HoughCircles(output2,cv2.HOUGH_GRADIENT,1,10, param1=180,param2=27,minRadius=20,maxRadius=60)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)plt.imshow(img)
À la suite du traitement d’image, il i peut être atteint dans la figure 13.
L’image est convertie en noir et blanc. Ensuite, la fonction de seuil est appliquée. Les fonctions de détection des bords GaussianBlur et Canny sont utilisées.
Enfin, les cercles sont dessinés avec la fonction HoughCircles.
Le traitement d’image est également appliqué au texte au format d’image.
Disons que nous voulons former notre système avec le texte de la figure 14. Nous voulons que tous les mots ou certains mots spécifiques soient identifiés par notre modèle à la suite de la formation. Nous devrons peut-être enseigner les informations de position des mots au système. OpenCV est également utilisé dans de tels problèmes. Tout d’abord, l’image (sur la figure 14) est convertie en texte. Un moteur de reconnaissance optique de caractères appelé Tesseract est utilisé pour cela[7].
data = pytesseract.image_to_data(img, output_type=Output.DICT, config = "--psm 6")
n_boxes = len(data['text'])
for i in range(n_boxes):
(x, y, w, h) = (data['left'][i], data['top'][i], data['width'][i], data['height'][i])
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)plt.imshow(img)
plt.show()
L’image est obtenue représentée sur la figure 15 en combinant les informations obtenues à l’aide de Tesseract avec OpenCV. Chaque mot et chaque bloc de mots sont entourés d’un cercle. Il est également possible de manipuler uniquement certains mots dans le cadre en manipulant les informations de Tesseract. De plus, un traitement d’image peut être appliqué pour effacer le texte des bruits. Cependant, lorsque la fonction GaussianBlur utilisée dans d’autres exemples est appliquée au texte, cela affectera négativement la qualité et la lisibilité du texte. Par conséquent, la fonction medianBlur sera utilisée à la place de la fonction GaussianBlur.
img = cv2.imread(img_path)
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
output2 = cv2.medianBlur(gray_image, ksize=5)
plt.imshow(output2)
plt.show()
Lorsque l’image est examinée sur la figure 14, les lignes en pointillés sont clairement visibles sous certains mots. Dans ce cas, les moteurs de reconnaissance optique de caractères peuvent mal lire certains mots. À la suite du processus medianBlur de la figure 16, on peut voir que ces lignes en pointillés ont disparu.
Remarque: Les dimensions des matrices d’images en noir et blanc doivent être vérifiées. La plupart du temps, il existe des dimensions RVB, même si elles sont en noir et blanc. Cela peut entraîner des erreurs de dimension dans certaines fonctions d’OpenCV.
Les fonctions Erode et Dilate peuvent également être utilisées pour éliminer le bruit du texte au format d’image.
kernel = np.ones((3,3),np.uint8)
output2 = cv2.dilate(gray_image,kernel,iterations = 3)
plt.imshow(output2)
plt.show()
En regardant le texte de la figure 14, on verra qu’il y a des bruits en forme de point. On peut voir que ces bruits sont considérablement éliminés avec l’utilisation de la fonction dilatée de la figure 17. Le taux d’amincissement sur l’article peut être modifié en changeant les valeurs de paramètre de filtre et d’itérations créées. Ces valeurs doivent être déterminées correctement afin de préserver la lisibilité du texte. La fonction d’érosion, contrairement à la fonction dilatée, permet un épaississement du texte.
kernel = np.ones((3,3),np.uint8)
output2 = cv2.erode(gray_image,kernel,iterations = 3)
plt.imshow(output2)
plt.show()
Les épaisseurs de police ont été augmentées avec la fonction Erode, comme le montre la figure 18. C’est une méthode utilisée pour augmenter la qualité des articles écrits en polices fines en général. Un autre point à noter ici est que nos articles sont noirs et que notre fond est blanc. Si l’arrière-plan était noir et le texte était blanc, les processus de ces fonctions seraient déplacés.
OpenCV est utilisé pour augmenter la qualité de certaines images. Par exemple, les valeurs d’histogramme d’images avec un faible contraste sont réparties sur une zone étroite.
Afin d’améliorer le contraste de cette image, il est nécessaire d’étaler les valeurs de l’histogramme sur une large zone. La fonction equalizeHist est utilisée pour ces opérations. Faisons une égalisation d’histogramme pour l’image de la figure 19.
L’histogramme de l’image originale (figure 19) peut être vu sur la figure 20.
La visibilité des objets dans l’image est faible.
equ = cv2.equalizeHist(gray_image)
plt.imshow(equ)
L’image dont l’histogramme est égalisé avec la fonction equalizeHist peut être vue sur la figure 21. La qualité et la clarté de l’image ont augmenté. De plus, un graphique d’histogramme de l’image dont l’égalisation d’histogramme a été effectuée sur la figure 22. On peut voir que les valeurs collectées dans une zone de la figure 20 s’étalent sur une zone plus grande après égalisation d’histogramme. Ces valeurs d’histogramme peuvent être vérifiées pour chaque image. La qualité de l’image peut être augmentée en effectuant une égalisation d’histogramme lorsqu’elle est nécessaire.
[1]P.Erbao, Z.Guotong, «Image Processing Technology Research of On-Line Thread Processing», 2012 Conférence internationale sur le futur système électrique et énergétique, avril 2012.
[2]H.Singh, Apprentissage automatique et traitement d’images, pp.63–88, janvier 2019.
[3]R.H.Moss, S.E.Watkins, T.Jones, D.Apel, «Image seuillage in the high resolution target motion monitor», Actes de SPIE – The International Society for Optical Engineering, mars 2009.
[4]Y.Xu, L.Zhang, «Research on Lane Detection Technology Based on OPENCV», Conférence: 2015 3rd International Conference on Mechanical Engineering and Intelligent Systems, janvier 2015.
[5]F.J.M.Lizan, F.Llorens, M.Pujol, R.R.Aldeguer, C.Villagrá, «Travailler avec OpenCV et Intel Image Proccessing Libraries. Processing image data tools », Informática Industrial e Inteligencia Artificial, juillet 2002.
[6]Q.R.Zhang, P.Peng, Y.M.Jin, «Cherry Picking Robot Vision Recognition System Based on OpenCV», MATEC Web of Conferences, janvier 2016.
[7]R.Smith, «An Overview of the Tesseract OCR Engine», Conference: Document Analysis and Recognition, 2007. ICDAR 2007. Ninth International Conference on, Volume: 2, octobre 2007.
[8]https://www.mathworks.com/help/examples/images/win64/GetAxesContainingImageExample_01.png