python - objetos - Coincidencia de características de OpenCV para múltiples imágenes
python cv2 install (3)
¿Cómo puedo optimizar la coincidencia de funciones SIFT para muchas imágenes usando FLANN?
Tengo un ejemplo de trabajo tomado de los documentos Python OpenCV. Sin embargo, esto es comparar una imagen con otra y es lenta. Lo necesito para buscar funciones que coincidan en una serie de imágenes (algunos miles) y necesito que sea más rápido.
Mi idea actual:
- Ejecute todas las imágenes y guarde las características. ¿Cómo?
- Compara una imagen de una cámara con esta base superior y encuentra la correcta. ¿Cómo?
- Dame el resultado, la imagen correspondiente o algo así.
import sys # For debugging only import numpy as np import cv2 from matplotlib import pyplot as plt MIN_MATCH_COUNT = 10 img1 = cv2.imread(''image.jpg'',0) # queryImage img2 = cv2.imread(''target.jpg'',0) # trainImage # Initiate SIFT detector sift = cv2.SIFT() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) kp2, des2 = sift.detectAndCompute(img2,None) FLANN_INDEX_KDTREE = 0 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) search_params = dict(checks = 50) flann = cv2.FlannBasedMatcher(index_params, search_params) matches = flann.knnMatch(des1,des2,k=2) # store all the good matches as per Lowe''s ratio test. good = [] for m,n in matches: if m.distance MIN_MATCH_COUNT: src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2) dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2) M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0) matchesMask = mask.ravel().tolist() h,w = img1.shape pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2) dst = cv2.perspectiveTransform(pts,M) img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA) else: print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT) matchesMask = None draw_params = dict(matchColor = (0,255,0), # draw matches in green color singlePointColor = None, matchesMask = matchesMask, # draw only inliers flags = 2) img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params) plt.imshow(img3, ''gray''),plt.show()
ACTUALIZAR
Después de probar muchas cosas, me podría haber acercado más a la solución ahora. Espero que sea posible construir el índice y luego buscar en él de esta manera:
flann_params = dict(algorithm=1, trees=4) flann = cv2.flann_Index(npArray, flann_params) idx, dist = flann.knnSearch(queryDes, 1, params={})
Sin embargo, todavía no he logrado construir un npArray aceptado para el parámetro flann_Index.
loop through all images as image: npArray.append(sift.detectAndCompute(image, None)) npArray = np.array(npArray)
Aquí hay varios consejos míos:
- Debe reducir la cantidad de datos de puntos mediante el uso de técnicas adecuadas.
- Calcular la imagen de referencia repetidamente es un desperdicio. Debería persistir toda referencia calculada.
- No coloque el cálculo en un dispositivo móvil. Es mejor que cargue la referencia calculada de una imagen capturada en un servidor potente y realice la búsqueda allí.
Este es un tema muy interesante. Mis oídos también se están abriendo.
Nunca resolví esto en Python, sin embargo cambié el entorno a C ++ donde obtienes más ejemplos de OpenCV y no tienes que usar un contenedor con menos documentación.
Un ejemplo del problema que tuve con la coincidencia en varios archivos se puede encontrar aquí: https://github.com/Itseez/opencv/blob/2.4/samples/cpp/matching_to_many_images.cpp
Junto con la respuesta de @ stanleyxu2005, me gustaría agregar algunos consejos sobre cómo hacer la coincidencia completa, ya que actualmente estoy trabajando en tal cosa.
- Recomiendo crear una clase personalizada que se ajuste a cv :: Mat pero también almacene varias otras piezas de datos esenciales. En mi caso, tengo un ImageContainer que almacena la imagen original (que usaré para la costura final), la procesada (grayscaled, no distorsionada, etc.), sus puntos clave y los descriptores de esos. Al hacerlo, puede acceder a toda la información relevante para la coincidencia en un pozo bastante bien organizado. Puede implementar la extracción del punto clave y la generación del descriptor en él o hacerlo fuera de la clase y simplemente almacenar los resultados en ese contenedor.
- Almacene todos los contenedores de imágenes en algún tipo de estructura (el vector es generalmente una buena opción) para facilitar el acceso.
- También creé una clase llamada ImageMultiMatchContainer, que almacena un puntero a una imagen de consulta determinada (todas las imágenes son imágenes de consulta), un vector con punteros a todas las imágenes de trenes (para una sola imagen de consulta de la imagen, todas las demás son imágenes de tren) que se combinaron con él y también un vector de los vectores de partido para cada uno de esos partidos. Aquí tropecé con un problema de almacenamiento, es decir, primero tienes que omitir la coincidencia de una imagen consigo misma porque no tiene sentido y segundo tienes el problema de comparar dos imágenes dos veces y, por lo tanto, generar una sobrecarga considerable si tienes muchas imágenes. El segundo problema se debe al hecho de que iteramos a través de todas las imágenes (imágenes de consulta) y las comparamos con el resto en el conjunto (imágenes de trenes). En algún momento tenemos la imagen X (consulta) emparejada con la imagen Y (tren), pero luego también tenemos la imagen Y (ahora consulta) emparejada con la imagen X (ahora entrenar). Como puede ver, esto tampoco tiene sentido ya que básicamente está haciendo coincidir el mismo par de imágenes dos veces. Esto se puede resolver (trabajando actualmente en esto) creando una clase (MatchContainer) que almacena un puntero a cada una de las dos imágenes en un par coincidente y también el vector de coincidencia. Usted almacena esto en una ubicación central (en mi caso, esta es mi clase de emparejador) y para cada imagen como imagen de consulta, verifica la lista de imágenes coincidentes de la imagen del tren. Si está vacío, cree un nuevo MatchContainer y agréguelo al resto de MatchContainers. Si no es así, busca en él y ve si la imagen de consulta actual no está presente allí (la comparación de los punteros es una operación rápida). Si es así, simplemente pasa el puntero al elemento vectorial de MatchContainer que almacena las coincidencias para esas dos imágenes. Si ese no es el caso, hazlo como si estuviera vacío y crea un nuevo MatchContainer, etc. Los MatchingContainers deben almacenarse en una estructura de datos con un tiempo de acceso pequeño, ya que los verás mucho y también se iterarán desde el principio hasta el final. mucho tiempo. Estoy considerando usar un mapa, pero tal vez un árbol de algún tipo también puede ofrecer algunas ventajas.
- La estimación de la homografía es una parte muy difícil. Aquí te recomiendo que veas el ajuste del bloque del paquete . Vi que la clase de grapadora en OpenCV tiene una clase BundleBase, pero aún no la he probado para ver qué hay en ella.
Una recomendación general es observar el proceso de costura en OpenCV y leer el código fuente. La línea de costura es un conjunto sencillo de procesos y solo tiene que ver cómo exactamente puede implementar los pasos individuales.