Estoy tratando de detectar el recuento de tuberías en esta imagen. Para esto, estoy usando OpenCV y detección basada en Python. Basado en las respuestas existentes a preguntas similares, pude llegar a los siguientes pasos
- Abre la imagen
- Filtrarlo
- Aplicar detección de bordes
- Usar contornos
- Verificar el recuento
El recuento total de tuberías es ~ 909 cuando lo contamos manualmente, da o toma 4.
Después de aplicar el filtro
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
Me sale esta imagen enmascarada
Esto parece bastante preciso en términos de la cantidad de rectángulos visibles que muestra. Sin embargo, cuando trato de contar y trazar el cuadro delimitador en la parte superior de la imagen, también selecciona muchas regiones no deseadas. Para los círculos, HoughCircles tiene una forma de definir el radio máximo y mínimo. ¿Hay algo similar para los rectángulos que pueda mejorar la precisión? Además, estoy abierto a sugerencias para enfoques alternativos a este problema.
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)
ACTUALIZACIÓN Basado en la segunda respuesta, he convertido el código c ++ a código python y obtuve resultados más cercanos, pero aún me faltan algunos rectángulos obvios.
Respuestas:
Por supuesto, puedes filtrarlos por su área. Tomé su imagen binaria y continué el trabajo de la siguiente manera:
1- Haz un bucle en todos los contornos que encontraste en findContours
2- En el bucle verifique si cada contorno, es un contorno interno o no
3- De aquellos que son contornos internos, verifique su área y si el área está en el rango aceptable, verifique la relación ancho / alto de cada contorno y, por último, si también es bueno, cuente ese contorno como una tubería.
Hice el método anterior en su imagen binaria y encontré 794 tuberías :
(Sin embargo, algunos cuadros se pierden. Debe cambiar los parámetros del detector de bordes para obtener más cuadros separables en la imagen).
y aquí está el código (es c ++ pero fácilmente convertible a python):
fuente
Hay muchos métodos para resolver este problema, pero dudo que haya un solo método sin algún tipo de medidas ad-hod. Aquí hay otro intento de este problema.
En lugar de utilizar la información de borde, sugiero un filtro tipo LBP (patrón binario local) que compara el píxel circundante con el valor central. Si un cierto porcentaje del píxel circundante es mayor que el píxel central, el píxel central se etiquetará con 255. si no se cumple la condición, el píxel central se etiquetará con 0.
Este método basado en la intensidad se ejecuta asumiendo que el centro de la tubería siempre es más oscuro que los bordes de la tubería. Como está comparando la intensidad, debería funcionar bien siempre que quede algo de contraste.
A través de este proceso, obtendrá una imagen con manchas binarias para cada tubería y algunos ruidos. Tendrá que eliminarlos con alguna condición conocida, como, tamaño, forma, índice de relleno, color, etc. La condición se puede encontrar en el código dado.
Resultado del procesamiento similar a LBP
Después de la limpieza con proceso morfológico.
Resultado final con los cuadros rojos que muestran todos los candidatos de blob y los segmentos amarillos que muestran blobs que pasan todas las condiciones que establecimos. Hay algunas falsas alarmas debajo y en la parte superior del haz de tuberías, pero se pueden omitir con algunas condiciones de contorno.
Total de tuberías encontradas: 943
fuente