J'essaie de détecter le nombre de tuyaux dans cette image. Pour cela, j'utilise OpenCV et la détection basée sur Python. Sur la base des réponses existantes à des questions similaires, j'ai pu trouver les étapes suivantes
- Ouvrez l'image
- Filtrer
- Appliquer la détection des contours
- Utiliser les contours
- Vérifiez le nombre
Le nombre total de tuyaux est ~ 909 lorsque nous le comptons donner ou prendre manuellement 4.
Après avoir appliqué le filtre
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('images/input-rectpipe-1.jpg')
blur_hor = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((11,1,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
blur_vert = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((1,11,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
mask = ((img[:,:,0]>blur_hor*1.2) | (img[:,:,0]>blur_vert*1.2)).astype(np.uint8)*255
Je reçois cette image masquée
Cela semble assez précis en termes de nombre de rectangles visibles qu'il montre. Cependant, lorsque j'essaie de prendre le compte et de tracer le cadre de sélection au-dessus de l'image, il sélectionne également de nombreuses régions indésirables. Pour les cercles, HoughCircles a un moyen de définir le rayon max et min. Existe-t-il quelque chose de similaire pour les rectangles qui peut améliorer la précision. En outre, je suis ouvert aux suggestions d'approches alternatives à ce problème.
ret,thresh = cv2.threshold(mask,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)
count = 0
for i in range(len(contours)):
count = count+1
x,y,w,h = cv2.boundingRect(contours[i])
rect = cv2.minAreaRect(contours[i])
area = cv2.contourArea(contours[i])
box = cv2.boxPoints(rect)
ratio = w/h
M = cv2.moments(contours[i])
if M["m00"] == 0.0:
cX = int(M["m10"] / 1 )
cY = int(M["m01"] / 1 )
if M["m00"] != 0.0:
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
if (area > 50 and area < 220 and hierarchy[0][i][2] < 0 and (ratio > .5 and ratio < 2)):
#cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
cv2.circle(img, (cX, cY), 1, (255, 255, 255), -1)
count = count + 1
print(count)
cv2.imshow("m",mask)
cv2.imshow("f",img)
cv2.waitKey(0)
MISE À JOUR Sur la base de la deuxième réponse, j'ai converti le code c ++ en code python et obtenu des résultats plus proches, mais il manque toujours quelques rectangles évidents.
Réponses:
Bien sûr, vous pouvez les filtrer par zone. J'ai pris votre image binaire et j'ai continué le travail comme ci-dessous:
1- Faites une boucle sur tous les contours que vous avez trouvés dans findContours
2- Dans la boucle, vérifiez si chaque contour est un contour interne ou non
3- A partir de ceux qui sont des contours internes, vérifiez leur surface et si la zone est dans la plage acceptable, vérifiez le rapport largeur / hauteur de chaque contour et enfin si c'est bon aussi, comptez ce contour comme un tuyau.
J'ai fait la méthode ci-dessus sur votre image binaire et trouvé 794 tuyaux :
(Cependant, certaines boîtes sont perdues, vous devez modifier les paramètres du détecteur de bord pour obtenir plus de boîtes séparables dans l'image.)
et voici le code (c'est c ++ mais facilement convertible en python):
la source
Il existe de nombreuses méthodes pour résoudre ce problème, mais je doute qu'il y aura une seule méthode sans une sorte de mesures ad-hod. Voici une autre tentative pour résoudre ce problème.
Au lieu d'utiliser les informations de bord, je suggère un filtre de type LBP (modèle binaire local) qui compare le pixel environnant avec la valeur centrale. Si un certain pourcentage du pixel environnant est plus grand que le pixel central, le pixel central sera étiqueté 255. si la condition n'est pas remplie, alors le pixel central sera étiqueté 0.
Cette méthode basée sur l'intensité est exécutée en supposant que le centre du tuyau est toujours plus sombre que les bords du tuyau. Puisqu'il compare l'intensité, il devrait bien fonctionner tant qu'il reste du contraste.
Grâce à ce processus, vous obtiendrez une image avec des taches binaires pour chaque tuyau et certains bruits. Vous devrez les supprimer avec certaines conditions pré-connues telles que, taille, forme, fill_ratio, couleur et etc. La condition peut être trouvée dans le code donné.
Résultat du traitement de type LBP
Après nettoyage avec processus morphologique
Résultat final avec les cases rouges montrant tous les candidats blob et les segments jaunes montrant les blobs qui remplissent toutes les conditions que nous avons définies. Il y a quelques fausses alarmes en dessous et au-dessus du faisceau de tuyaux, mais elles peuvent être omises avec certaines conditions aux limites.
Tuyau total trouvé: 943
la source