Tengo un gran conjunto de puntos (orden de 10k puntos) formados por pistas de partículas (movimiento en el plano xy en el tiempo filmado por una cámara, por lo que 3D - 256x256px y ca 3k fotogramas en mi conjunto de ejemplo) y ruido. Estas partículas viajan aproximadamente en líneas rectas aproximadamente (pero solo aproximadamente) en la misma dirección, por lo que para el análisis de sus trayectorias estoy tratando de ajustar las líneas a través de los puntos. Traté de usar RANSAC secuencial, pero no puedo encontrar un criterio para identificar con seguridad los falsos positivos, así como el enlace T y J, que eran demasiado lentos y tampoco lo suficientemente confiables.
Aquí hay una imagen de una parte del conjunto de datos con ajustes buenos y malos que obtuve con Ransac secuencial: estoy usando los centroides de los blobs de partículas aquí, los tamaños de blob varían entre 1 y aproximadamente 20 píxeles.
Descubrí que las submuestras que utilizan, por ejemplo, solo cada décimo fotograma también funcionaban bastante bien, por lo que el tamaño de los datos a procesar se puede reducir de esta manera.
Leí una publicación de blog sobre todas las cosas que las redes neuronales pueden lograr, y me gustaría preguntarle si esta sería una aplicación viable para uno antes de comenzar a leer (vengo de un entorno no matemático, por lo que tendría que hacer bastante un poco de lectura)
¿O podrías sugerir un método diferente?
¡Gracias!
Anexo: Aquí hay un código para una función de Matlab para generar una nube de puntos de muestra que contiene 30 líneas ruidosas paralelas, que aún no puedo distinguir:
function coords = generateSampleData()
coords = [];
for i = 1:30
randOffset = i*2;
coords = vertcat(coords, makeLine([100+randOffset 100 100], [200+randOffset 200 200], 150, 0.2));
end
figure
scatter3(coords(:,1),coords(:,2),coords(:,3),'.')
function linepts = makeLine(startpt, endpt, numpts, noiseOffset)
dirvec = endpt - startpt;
linepts = bsxfun( @plus, startpt, rand(numpts,1)*dirvec); % random points on line
linepts = linepts + noiseOffset*randn(numpts,3); % add random offsets to points
end
end
fuente
Respuestas:
Basado en la retroalimentación y tratando de encontrar un enfoque más efectivo, desarrollé el siguiente algoritmo usando una medida de distancia dedicada.
Se realizan los siguientes pasos:
1) Definir una distancia métrica de retorno:
cero : si los puntos no pertenecen a una línea
Distancia euclidiana de los puntos : si los puntos constituyen una línea de acuerdo con los parámetros definidos, es decir
su distancia es mayor o igual que min_line_length y
su distancia es menor o igual que max_line_length y
la línea consta de al menos min_line_points puntos con una distancia menor que line_width / 2 desde la línea
2) Calcule la matriz de distancia usando esta medida de distancia (use una muestra de los datos para grandes conjuntos de datos; ajuste los parámetros de línea en consecuencia)
3) Encuentre los puntos A y B con la distancia máxima - vaya al paso 5) si la distancia es cero
Tenga en cuenta que si la distancia es mayor que cero, los puntos A y B están construyendo una línea basada en nuestra definición
4) Obtenga todos los puntos que pertenecen a la línea AB y elimínelos de la matriz de distancia. Repita el paso 3) para encontrar otra línea.
5) Verifique la cobertura del punto con las líneas seleccionadas, si un número sustancial de puntos permanece sin cubrir, repita todo el algoritmo con los parámetros de línea ajustados.
6) En caso de que se usó una muestra de datos, reasigne todos los puntos a las líneas y recalcule los puntos límite.
Se utilizan los siguientes parámetros:
ancho de línea - ancho_línea / 2 es la distancia permitida del punto desde la línea ideal =
r line_width
longitud mínima de línea : los puntos con una distancia más corta no se consideran pertenecientes a la misma línea =
r min_line_length
longitud máxima de la línea : los puntos con una distancia más larga no se consideran pertenecientes a la misma línea =
r max_line_length
puntos mínimos en una línea : se ignoran las líneas con menos puntos =
r min_line_points
Con sus datos (después de jugar con los parámetros) obtuve un buen resultado cubriendo las 30 líneas.
Se pueden encontrar más detalles en el script de knitr
fuente
Resolví una tarea similar, aunque más simple, con un enfoque de fuerza bruta. La simplificación estaba en el supuesto de que la línea es una función lineal (en mi caso, incluso los coeficientes y la intersección estaban en algún rango conocido).
Por lo tanto, esto no resolverá su problema en general, donde una partícula puede moverse ortogonal con el eje x (es decir, no traza ninguna función), pero publico la solución como una posible inspiración.
1) Tome todas las combinaciones de dos puntos A y B con A (x)> B (x) + constante (para evitar la simetría y un alto error al calcular el coeficiente)
2) Calcule el coeficiente c e intercepte i de la línea AB
3) Redondear el coeficiente e interceptar (esto debería eliminar / disminuir los problemas con errores causados por los puntos en una cuadrícula)
4) Para cada intersección y coeficiente, calcule el número de puntos en esta línea
5) Considere solo líneas con puntos por encima de algún umbral.
Ejemplo simple ver aquí
fuente