reconocimiento reconocer procesamiento para objetos librerias imagenes filtros ejemplos detección deteccion con colores python opencv image-processing

procesamiento - reconocer colores opencv python



¿Cómo detectar líneas en opencv? (4)

Estoy tratando de detectar líneas en el estacionamiento como se muestra a continuación

Lo que espero obtener son las líneas claras y la posición (x, y) en la línea cruzada, sin embargo el resultado no es muy prometedor

Supongo que se debe a dos razones principales.

  1. Algunas líneas están muy rotas o faltan incluso los ojos humanos pueden identificarlas claramente. (Incluso HoughLine puede ayudar a conectar algunas líneas faltantes ya que HoughLine a veces conectaba líneas innecesarias, así que preferiría hacerlo manualmente)

  2. hay algunas lineas repetidas

La tubería general para el trabajo se muestra a continuación.

1. Seleccione algunos colores específicos (blanco o amarillo)

import cv2 import numpy as np import matplotlib from matplotlib.pyplot import imshow from matplotlib import pyplot as plt # white color mask img = cv2.imread(filein) #converted = convert_hls(img) image = cv2.cvtColor(img,cv2.COLOR_BGR2HLS) lower = np.uint8([0, 200, 0]) upper = np.uint8([255, 255, 255]) white_mask = cv2.inRange(image, lower, upper) # yellow color mask lower = np.uint8([10, 0, 100]) upper = np.uint8([40, 255, 255]) yellow_mask = cv2.inRange(image, lower, upper) # combine the mask mask = cv2.bitwise_or(white_mask, yellow_mask) result = img.copy() cv2.imshow("mask",mask)

2. Repita la dilatación y la erosión hasta que la imagen no pueda ser cambiada ( reference )

height,width = mask.shape skel = np.zeros([height,width],dtype=np.uint8) #[height,width,3] kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3)) temp_nonzero = np.count_nonzero(mask) while(np.count_nonzero(mask) != 0 ): eroded = cv2.erode(mask,kernel) cv2.imshow("eroded",eroded) temp = cv2.dilate(eroded,kernel) cv2.imshow("dilate",temp) temp = cv2.subtract(mask,temp) skel = cv2.bitwise_or(skel,temp) mask = eroded.copy() cv2.imshow("skel",skel) #cv2.waitKey(0)

3. Aplique el canal para filtrar las líneas y use HoughLinesP para obtener las líneas.

edges = cv2.Canny(skel, 50, 150) cv2.imshow("edges",edges) lines = cv2.HoughLinesP(edges,1,np.pi/180,40,minLineLength=30,maxLineGap=30) i = 0 for x1,y1,x2,y2 in lines[0]: i+=1 cv2.line(result,(x1,y1),(x2,y2),(255,0,0),1) print i cv2.imshow("res",result) cv2.waitKey(0)

Me pregunto después del primer paso de seleccionar cierto color, las líneas están con quebrados y ruidos. Pensaría que en este paso deberíamos hacer algo para hacer que la línea discontinua sea una línea completa, menos ruidosa, y luego tratar de aplicar algo para hacer el Canny y Hough lineas, alguna idea?


¿Qué sucede si ajusta maxLineGap o el tamaño de su núcleo de erosión? Alternativamente, puedes encontrar la distancia entre líneas. Tendría que ir a través de pares de líneas como ax1, ay1 a ax2, ay2 cf bx1, by1 a bx2, by2 puede encontrar el punto donde se encuentra el gradiente en ángulos rectos (-1 sobre gradiente de línea) a una línea de cruces b. Geometría escolar básica y ecuaciones simultáneas, algo así como:

x = (ay1 - by1) / ((by2 - by1) / (bx2 - bx1) + (ax2 - ax1) / (ay2 - ay1)) # then y = by1 + x * (by2 - by1) / (bx2 - bx1)

y compara x, y con ax1, ay1

Es posible que tenga que agregar una verificación de la distancia entre ax1, ay1 y bx1, by1 ya que algunas de sus líneas parecen ser continuaciones de otras líneas y estas podrían eliminarse mediante la técnica del punto más cercano.


Aquí está mi canalización, tal vez pueda brindarte ayuda.

En primer lugar, obtener la imagen gris y procesar GaussianBlur.

img = cv2.imread(''src.png'') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) kernel_size = 5 blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)

En segundo lugar, el proceso de detección de bordes utiliza Canny.

low_threshold = 50 high_threshold = 150 edges = cv2.Canny(blur_gray, low_threshold, high_threshold)

Luego, usa HoughLinesP para obtener las líneas. Puede ajustar los parámetros para un mejor rendimiento.

rho = 1 # distance resolution in pixels of the Hough grid theta = np.pi / 180 # angular resolution in radians of the Hough grid threshold = 15 # minimum number of votes (intersections in Hough grid cell) min_line_length = 50 # minimum number of pixels making up a line max_line_gap = 20 # maximum gap in pixels between connectable line segments line_image = np.copy(img) * 0 # creating a blank to draw lines on # Run Hough on edge detected image # Output "lines" is an array containing endpoints of detected line segments lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap) for line in lines: for x1,y1,x2,y2 in line: cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),5)

Finalmente, dibuja las líneas en tu srcImage.

# Draw the lines on the image lines_edges = cv2.addWeighted(img, 0.8, line_image, 1, 0)

Aquí está mi actuación final.

Imagen final:


Hay algunas respuestas geniales aquí para la primera parte de su pregunta, pero en cuanto a la segunda parte (encontrar las intersecciones de líneas) no veo mucho.

Le sugiero que eche un vistazo al algoritmo de Bentley-Ottmann .

Hay algunas implementaciones de python del algoritmo here y here .

Edición: Al usar la implementación de Houghlines de VeraPoseidon y la segunda biblioteca vinculada aquí, he logrado obtener el siguiente resultado para la detección de intersecciones. Gracias a Vera y al autor de la biblioteca por su buen trabajo. Los cuadrados verdes representan una intersección detectada. Hay algunos errores, pero este me parece un buen punto de partida. Parece que la mayoría de las ubicaciones en las que realmente desea detectar una intersección tienen múltiples intersecciones detectadas, por lo que probablemente podría ejecutar una ventana del tamaño adecuado sobre la imagen que buscaba múltiples intersecciones y se considera una intersección verdadera como una donde se activó esa ventana.

Aquí está el código que utilicé para producir ese resultado:

import cv2 import numpy as np import isect_segments_bentley_ottmann.poly_point_isect as bot img = cv2.imread(''parking.png'') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) kernel_size = 5 blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0) low_threshold = 50 high_threshold = 150 edges = cv2.Canny(blur_gray, low_threshold, high_threshold) rho = 1 # distance resolution in pixels of the Hough grid theta = np.pi / 180 # angular resolution in radians of the Hough grid threshold = 15 # minimum number of votes (intersections in Hough grid cell) min_line_length = 50 # minimum number of pixels making up a line max_line_gap = 20 # maximum gap in pixels between connectable line segments line_image = np.copy(img) * 0 # creating a blank to draw lines on # Run Hough on edge detected image # Output "lines" is an array containing endpoints of detected line segments lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap) print(lines) points = [] for line in lines: for x1, y1, x2, y2 in line: points.append(((x1 + 0.0, y1 + 0.0), (x2 + 0.0, y2 + 0.0))) cv2.line(line_image, (x1, y1), (x2, y2), (255, 0, 0), 5) lines_edges = cv2.addWeighted(img, 0.8, line_image, 1, 0) print(lines_edges.shape) #cv2.imwrite(''line_parking.png'', lines_edges) print points intersections = bot.isect_segments(points) print intersections for inter in intersections: a, b = inter for i in range(3): for j in range(3): lines_edges[int(b) + i, int(a) + j] = [0, 255, 0] cv2.imwrite(''line_parking.png'', lines_edges)

Puedes usar algo como este bloque de código para una estrategia para eliminar múltiples intersecciones en un área pequeña:

for idx, inter in enumerate(intersections): a, b = inter match = 0 for other_inter in intersections[idx:]: c, d = other_inter if abs(c-a) < 15 and abs(d-b) < 15: match = 1 intersections[idx] = ((c+a)/2, (d+b)/2) intersections.remove(other_inter) if match == 0: intersections.remove(inter)

Imagen de salida:

Sin embargo, tendrás que jugar con la función de ventana.


No estoy seguro de qué es exactamente lo que está preguntando, ya que no hay preguntas en su publicación.

Una técnica agradable y robusta para detectar segmentos de línea es el LSD (detector de segmento de línea), disponible en openCV desde openCV 3.

Aquí hay algunos códigos básicos simples en C ++, que probablemente se pueden convertir a Python fácilmente:

int main(int argc, char* argv[]) { cv::Mat input = cv::imread("C://Input/parking.png"); cv::Mat gray; cv::cvtColor(input, gray, CV_BGR2GRAY); cv::Ptr<cv::LineSegmentDetector> det; det = cv::createLineSegmentDetector(); cv::Mat lines; det->detect(gray, lines); det->drawSegments(input, lines); cv::imshow("input", input); cv::waitKey(0); return 0; }

Dando este resultado:

Que se ve mejor para el procesamiento posterior que su imagen (sin duplicados de líneas, etc.)