Encontrar regiones / patrones simétricos en la imagen

14

Tengo un conjunto de imágenes que representan la curvatura media de una superficie posterior humana.

Lo que quiero hacer es "escanear" la imagen en busca de puntos que tengan "contrapartidas" similares y reflejadas en alguna otra parte de la imagen (muy probablemente simétrica a la línea media, pero no necesariamente porque puede haber deformidades). Algunas técnicas de unión de imágenes usan esto para "autodetectar" puntos similares entre imágenes, pero quiero detectarlos para ambos lados de la misma imagen.

El objetivo final es encontrar una línea longitudinal continua, probablemente curva, que divida adaptativamente la espalda en "mitades" simétricas.

Una imagen de muestra se coloca debajo. Tenga en cuenta que no todas las regiones son simétricas (específicamente, justo encima del centro de la imagen, la "franja" vertical roja se desvía a la derecha). Esa región debería recibir una mala puntuación, o lo que sea, pero luego la simetría local se definiría a partir de puntos simétricos ubicados más lejos. En cualquier caso, tendré que adaptar cualquier algoritmo al dominio de mi aplicación, pero lo que busco es una estrategia de correlación / convolución / coincidencia de patrones, creo que ya debe haber algo.

(EDITAR: hay más imágenes a continuación, y algunas explicaciones más)

ingrese la descripción de la imagen aquí

EDITAR: según lo solicitado, incluiré imágenes más típicas, bien comportadas y problemáticas. Pero en lugar de imágenes mapeadas en color, son en escala de grises, por lo que el color se relaciona directamente con la magnitud de los datos, lo que no sucedió con la imagen en color (proporcionada solo para la comunicación). Aunque las imágenes grises parecen carecer de contraste en comparación con las de color, los gradientes de datos están ahí y pueden aparecer con un poco de contraste adaptativo si se desea.


1) Imagen de un sujeto muy simétrico:

ingrese la descripción de la imagen aquí


2) Imagen del mismo sujeto en un momento diferente. Aunque hay más "características" (más gradientes), no se "siente" tan simétrica como antes:

ingrese la descripción de la imagen aquí


3) Un sujeto joven y delgado, con convexidades (protuberancias óseas, denotadas por regiones más claras) en la línea media en lugar de la línea media cóncava más común:

ingrese la descripción de la imagen aquí


4) Una persona joven con desviación espinal confirmada por rayos X (tenga en cuenta las asimetrías):

ingrese la descripción de la imagen aquí


5) El sujeto típico "inclinado" (aunque en su mayoría simétrico alrededor de la línea media curva, y como tal no está "deformado" correctamente):

ingrese la descripción de la imagen aquí


Cualquier ayuda es muy bienvenida!

heltonbiker
fuente
¿Por qué no simplemente usar la columna vertebral como divisor?
Jim Clay
@ JimClay: sospecho que la columna vertebral es la parte que se mide, en relación con el eje de simetría real del resto de la imagen
endolito el
"Algunas técnicas de unión de imágenes usan esto para" detectar automáticamente "puntos similares entre imágenes" Haga una copia invertida de la imagen y luego use una de ellas. :)
Endolith
¿No podría simplemente reflejar la imagen a lo largo del eje Y y utilizar un algoritmo de registro? Porque ya hay mucha investigación sobre algoritmos de registro flexibles / no paramétricos sobre los que podría basarse.
Niki Estner
JimClay, la columna vertebral es lo que quiero encontrar, no sé dónde está; Endolith, mi pregunta involucra a personas que me dicen los nombres de algunos de esos algoritmos, todavía no he encontrado ninguno. Y Nikie, ese es el punto, pero no conozco ninguno de esos algoritmos, por eso estoy haciendo la pregunta en primer lugar: o)
heltonbiker

Respuestas:

9

Como he dicho en los comentarios, el registro de imágenes médicas es un tema con mucha investigación disponible, y no soy un experto. Por lo que he leído, la idea básica comúnmente utilizada es definir un mapeo entre dos imágenes (en su caso, una imagen y su imagen especular), luego definir términos de energía para suavidad y similitud de imagen si se aplica el mapeo, y finalmente optimice esta asignación utilizando técnicas de optimización estándar (o, a veces, específicas de la aplicación).

He hackeado un algoritmo rápido en Mathematica para demostrar esto. Este no es un algoritmo que debe usar en una aplicación médica, solo una demostración de las ideas básicas.

Primero, cargo su imagen, la reflejo y divido estas imágenes en pequeños bloques:

src = ColorConvert[Import["http://i.stack.imgur.com/jf709.jpg"], 
   "Grayscale"];
mirror = ImageReflect[src, Left -> Right];
blockSize = 30;
partsS = ImagePartition[src, {blockSize, blockSize}];
partsM = ImagePartition[mirror, {blockSize, blockSize}];
GraphicsGrid[partsS]

Gráficos de Mathematica

Normalmente, haríamos un registro rígido aproximado (usando, por ejemplo, puntos clave o momentos de imagen), pero su imagen está casi centrada, por lo que me saltearé esto.

Si miramos un bloque y su contraparte de imagen especular:

{partsS[[6, 10]], partsM[[6, 10]]}

Gráficos de Mathematica

Podemos ver que son similares, pero cambiaron. La cantidad y la dirección del cambio es lo que estamos tratando de averiguar.

Para cuantificar la similitud de coincidencia, puedo usar la distancia euclidiana al cuadrado:

ListPlot3D[
  ImageData[
   ImageCorrelate[partsM[[6, 10]], partsS[[6, 10]], 
    SquaredEuclideanDistance]]]

Gráficos de Mathematica

Lamentablemente, el uso de estos datos es que la optimización directamente fue más difícil de lo que pensaba, así que en su lugar utilicé una aproximación de segundo orden:

fitTerms = {1, x, x^2, y, y^2, x*y};

fit = Fit[
   Flatten[MapIndexed[{#2[[1]] - blockSize/2, #2[[2]] - 
        blockSize/2, #1} &, 
     ImageData[
      ImageCorrelate[partsM[[6, 10]], partsS[[6, 10]], 
       SquaredEuclideanDistance]], {2}], 1], fitTerms, {x, y}];

Plot3D[fit, {x, -25, 25}, {y, -25, 25}]

Gráficos de Mathematica

La función no es la misma que la función de correlación real, pero está lo suficientemente cerca para un primer paso. Calculemos esto para cada par de bloques:

distancesFit = MapThread[
   Function[{part, template},
    Fit[Flatten[
      MapIndexed[{#2[[2]] - blockSize/2, #2[[1]] - blockSize/2, #1} &,
        ImageData[
        ImageCorrelate[part, template, 
         SquaredEuclideanDistance]], {2}], 1], 
     fitTerms, {x, y}]], {partsM, partsS}, 2];

Esto nos da nuestro primer término energético para la optimización:

variablesX = Array[dx, Dimensions[partsS]];
variablesY = Array[dy, Dimensions[partsS]];

matchEnergyFit = 
  Total[MapThread[#1 /. {x -> #2, y -> #3} &, {distancesFit, 
     variablesX, variablesY}, 2], 3];

variablesX/Ycontiene los desplazamientos para cada bloque y matchEnergyFitaproxima la diferencia euclidiana al cuadrado entre la imagen original y la imagen reflejada con los desplazamientos aplicados.

La optimización de esta energía por sí sola daría malos resultados (si convergiera en absoluto). También queremos que los desplazamientos sean suaves, donde la similitud del bloque no dice nada sobre el desplazamiento (por ejemplo, a lo largo de una línea recta o en el fondo blanco).

Entonces establecemos un segundo término de energía para suavidad:

smoothnessEnergy = Total[Flatten[
    {
     Table[
      variablesX[[i, j - 1]] - 2 variablesX[[i, j]] + 
       variablesX[[i, j + 1]], {i, 1, Length[partsS]}, {j, 2, 
       Length[partsS[[1]]] - 1}],
     Table[
      variablesX[[i - 1, j]] - 2 variablesX[[i, j]] + 
       variablesX[[i + 1, j]], {i, 2, Length[partsS] - 1}, {j, 1, 
       Length[partsS[[1]]]}],
     Table[
      variablesY[[i, j - 1]] - 2 variablesY[[i, j]] + 
       variablesY[[i, j + 1]], {i, 1, Length[partsS]}, {j, 2, 
       Length[partsS[[1]]] - 1}],
     Table[
      variablesY[[i - 1, j]] - 2 variablesY[[i, j]] + 
       variablesY[[i + 1, j]], {i, 2, Length[partsS] - 1}, {j, 1, 
       Length[partsS[[1]]]}]
     }^2]];

Afortunadamente, la optimización restringida está incorporada en Mathematica:

allVariables = Flatten[{variablesX, variablesY}];
constraints = -blockSize/3. < # < blockSize/3. & /@ allVariables;
initialValues = {#, 0} & /@ allVariables;
solution = 
  FindMinimum[{matchEnergyFit + 0.1 smoothnessEnergy, constraints}, 
   initialValues];

Veamos el resultado:

grid = Table[{(j - 0.5)*blockSize - dx[i, j], (i - 0.5)*blockSize - 
      dy[i, j]}, {i, Length[partsS]}, {j, Length[partsS[[1]]]}] /. 
   solution[[2]];
Show[src, Graphics[
  {Red,
   Line /@ grid,
   Line /@ Transpose[grid]
   }]]

Gráficos de Mathematica

El 0.1factor anterior smoothnessEnergyes el peso relativo que obtiene la energía de suavidad en relación con el término de energía de coincidencia de imagen. Estos son resultados para diferentes pesos:

Gráficos de Mathematica

Posibles mejoras:

  • Como dije, primero realice un registro rígido. Con un fondo blanco, el registro simple basado en momentos de la imagen debería funcionar bien.
  • Este es solo un paso. Puede usar las compensaciones que encontró en un paso y mejorarlas en un segundo paso, tal vez con una ventana de búsqueda más pequeña o tamaños de bloque más pequeños
  • He leído artículos donde hacen esto sin bloques en absoluto, pero optimizo un desplazamiento por píxel.
  • Pruebe diferentes funciones de suavidad
Niki Estner
fuente
responde demasiado para leer solo por diversión, pero la imagen final es bastante indicativa: se ve increíble: D
penelope
Esta respuesta fue muy esclarecedora. Necesitaré algo de tiempo para tragarlo, pero lo más probable es que la técnica de registro no rígida sea lo que necesito usar. Afortunadamente, proporcionó algunos detalles conceptuales, por lo que, en el peor de los casos, puedo encontrar un enfoque similar. Mientras tanto, actualizaré la pregunta con más imágenes. Gracias por ahora
heltonbiker
4

Interesante pregunta. Primero, tal vez busque enfoques basados ​​en el detector de puntos clave de interés y la coincidencia. Esto incluiría SIFT (Scale-Invariant Feature Transform), SURF, ORB, etc ... o incluso un enfoque más simple basado únicamente en el operador Harris (csce.uark.edu/~jgauch/library/Features/Harris.1988.pdf ) No está claro en su publicación lo que ha intentado, así que lo siento si soy ingenuo aquí.

Dicho esto, permítanme adoptar un enfoque más simple con la Morfología Matemática (MM) solo por diversión :) Las imágenes para visualizar todos los pasos están al final.

Tomé su imagen de muestra y la convertí al espacio de color L a b * usando ImageMagick y usé solo la banda L *:

convert x.jpg -colorspace Lab -separate %d.png

0.png corresponde a la banda L *. Ahora, estoy seguro de que tiene los datos reales de la imagen, pero estoy lidiando con artefactos de compresión jpg y demás. Para manejar parcialmente este problema, realicé una apertura morfológica seguida de un cierre morfológico con un disco plano de radio 5. Esta es una forma básica de reducir el ruido con MM, y dado el radio del disco, no se cambia gran parte de la imagen. A continuación, mi idea se basó en esta imagen única, que tiene muchas posibilidades de fallar en otros casos. Su región de interés se distingue visualmente por ser más oscura ("más caliente" en su imagen en color), por lo que supuse que un binarizador basado en estadísticas podría funcionar bien. Usé el enfoque de Otsu, que es automático.

En este punto, es posible visualizar claramente la región central de interés. El problema es que, en mi enfoque, quería que fuera un componente cerrado, pero no lo es. Comienzo descartando cada componente conectado que sea más pequeño que el más grande (sin contar el fondo como uno de ellos). Esto tiene más posibilidades de funcionar en otros casos si el resultado de la binarización fue bueno. En su imagen de ejemplo, hay un componente conectado al fondo, por lo que no se descarta pero no causa problemas.

Si todavía me sigue, todavía tenemos que encontrar la supuesta región central de interés real. Aquí está mi opinión al respecto. No importa cuán curva sea la persona (en realidad puedo ver ciertos casos problemáticos), la región se asemeja a una línea vertical. Con ese fin, simplifico la imagen actual al realizar una apertura morfológica con una línea vertical de longitud 100. Esta longitud es puramente arbitraria, si no tiene problemas de escala, entonces este no es un valor difícil de determinar. Ahora de nuevo descartamos componentes, pero fui un poco más cuidadoso en este paso. Solía ​​abrir por área con el complemento de la imagen para descartar lo que consideraba regiones pequeñas, esto podría hacerse de una manera más controlada mediante la realización de algo en forma de análisis granulométrico (también de MM).

Ahora tenemos aproximadamente tres piezas: la parte izquierda de la imagen, la parte central y la parte derecha de la imagen. Se espera que la parte central sea el componente más pequeño de los tres, por lo que se obtiene trivialmente.

Aquí está el resultado final, la imagen inferior derecha es solo la imagen superpuesta a su izquierda con la original. Las figuras individuales no están todas alineadas, perdón por la prisa.

http://i.imgur.com/XRhYv.png

mmgp
fuente
Muchas gracias por su amable interés, pero su enfoque debe considerar ciertas propiedades de mis datos (no una queja, solo un detalle): 1) Los datos reales son una matriz 2D de flotadores, mapeados en color con un rojo-amarillo divergente. mapa de color verde en matplotlib de Python. No creo que trabajar con los datos de color sea conceptualmente correcto, las imágenes se muestran solo con fines de comunicación; 2) Los datos reales se relacionan con la curvatura de la superficie (convexa vs. cóncava), siendo las partes rojas cóncavas y las verdes convexas. El eje simétrico no necesariamente cae en una región cóncava.
heltonbiker
Muy pronto agregaré algunas imágenes más (y reemplazaré esta) por otras en escala de grises, para que las imágenes en sí mismas puedan usarse para pruebas, eliminando el peligro de distorsión del rango dinámico debido al color.
heltonbiker
Los datos aún no están disponibles, desafortunadamente. Las imágenes en escala de grises son, en el mejor de los casos, una aproximación de la misma.
mmgp
Creo que la aproximación probablemente sea suficiente, pero no me importa proporcionar los datos reales. Puedo publicar algunos enlaces públicos de descarga de DropBox, simplemente no sé en qué formato de archivo.
Heltonbiker