J'essaie de détecter les lignes dans le parking comme indiqué ci-dessous
Ce que j'espère obtenir, ce sont les lignes nettes et la position (x, y) dans la ligne croisée, mais le résultat n'est pas très prometteur
Je suppose que cela est dû à deux raisons principales
certaines lignes sont très cassées ou manquent même les yeux humains peuvent clairement les identifier. (Même HoughLine peut aider à connecter certaines lignes manquantes car HoughLine connectait parfois des lignes inutiles ensemble, je préférerais donc le faire manuellement)
il y a quelques lignes répétées
Le pipeline général des travaux est présenté ci-dessous.
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)
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)
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)
Je me demande après la première étape de sélection de certaines couleurs, les lignes sont fracturées et les bruits, je pense que dans cette étape, nous devrions faire quelque chose pour que la ligne brisée soit complète, moins bruyante, puis essayer d'appliquer quelque chose pour faire la Canny et Hough lignes, des idées?
Voici mon pipeline, il peut peut-être vous aider.
D'abord, récupérez l'image grise et traitez 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)
Deuxièmement, la détection de processus de processus utilise Canny.
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
Ensuite, utilisez HoughLinesP pour obtenir les lignes. Vous pouvez ajuster les paramètres pour obtenir de meilleures performances.
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)
Enfin, tracez les lignes sur votre srcImage.
# Draw the lines on the image
lines_edges = cv2.addWeighted(img, 0.8, line_image, 1, 0)
Voici ma dernière performance.
Image finale:
Je ne sais pas exactement ce que vous demandez, puisqu'il n'y a aucune question dans votre message.
Une technique agréable et robuste pour détecter les segments de ligne est le LSD (détecteur de segment de ligne), disponible en openCV depuis openCV 3.
Voici un code C++ de base simple, qui peut probablement être converti en python facilement:
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/StackOverflow/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;
}
Donnant ce résultat:
Ce qui est plus esthétique que votre image pour un traitement ultérieur (pas de doublons de lignes, etc.)
Il y a d'excellentes réponses ici à la première partie de votre question, mais en ce qui concerne la deuxième partie (trouver les intersections de lignes), je ne vois pas grand-chose.
Je vous suggère de jeter un coup d'œil à l'algorithme Bentley-Ottmann .
Il y a quelques implémentations de python de l'algorithme ici et ici .
Edit: En utilisant l’implémentation de VeraPoseidon Houghlines et la deuxième bibliothèque liée ici, j’ai réussi à obtenir le résultat suivant pour la détection d’intersection. Nous remercions Vera et l'auteur de la bibliothèque pour leur bon travail. Les carrés verts représentent une intersection détectée. Il y a quelques erreurs, mais cela me semble un très bon point de départ. Il semble que plusieurs intersections soient détectées dans la plupart des emplacements où vous souhaitez réellement détecter une intersection. Vous pouvez donc probablement afficher une fenêtre de taille appropriée sur l'image qui recherche plusieurs intersections et qui est considérée comme une intersection réelle comme étant celle où cette fenêtre est activée.
Voici le code que j'ai utilisé pour produire ce résultat:
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)
Vous pouvez utiliser quelque chose comme ce bloc de code pour une stratégie visant à supprimer plusieurs intersections dans une petite zone:
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)
Vous devrez cependant jouer avec la fonction de fenêtrage.
que se passe-t-il si vous ajustez maxLineGap ou la taille de votre noyau d'érosion. Alternativement, vous pouvez trouver la distance entre les lignes. Vous devez aller si les paires de lignes disent ax1, ay1 à ax2, ay2 c.f. bx1, by1 à bx2, by2 vous pouvez trouver le point où le dégradé à angle droit (-1 sur le dégradé de ligne) à une ligne de croix b. Géométrie scolaire de base et équations simultanées, quelque chose comme:
x = (ay1 - by1) / ((by2 - by1) / (bx2 - bx1) + (ax2 - ax1) / (ay2 - ay1))
# then
y = by1 + x * (by2 - by1) / (bx2 - bx1)
et comparez x, y avec ax1, ay1
PS: vous devrez peut-être ajouter une vérification de la distance entre ax1, ay1 et bx1, by1, car certaines de vos lignes semblent être des suites d'autres lignes et peuvent être éliminées par la technique du point le plus proche.