una - Buscar imágenes similares en(puro) PHP/MySQL
subir y mostrar archivos pdf con php y mysql (4)
Mis usuarios están cargando imágenes en mi sitio web y me gustaría ofrecerles primero las que ya están cargadas. Mi idea es 1. crear algún tipo de "hash" de imagen de cada imagen existente 2. crear un hash de la imagen recién cargada y compararla con la otra en la base de datos
He encontrado algunas soluciones interesantes como http://www.pureftpd.org/project/libpuzzle o http://phash.org/ etc. pero tienen uno o más problemas
- necesitan alguna extensión no estándar para PHP (o no están en PHP) - estaría bien para mí, pero me gustaría crearla como un complemento de mi popular CMS, que se usa en muchos entornos de alojamiento sin mi control.
- están comparando dos imágenes pero necesito comparar una con muchas (p. ej., miles) y hacerlo una por una sería muy poco efectivo / lento ... ...
Me gustaría encontrar solo imágenes MUY similares (por ejemplo, tamaño diferente, jpg resaved o factor de compresión jpg diferente).
La única idea que tengo es cambiar el tamaño de la imagen a, por ejemplo, 5px * 5px * 256 colores, crear una representación de cadena y luego encontrar la misma. Pero supongo que puede haber creado pequeñas diferencias en los colores incluso con solo dos imágenes iguales con un tamaño diferente, por lo que encontrar el 100% de lo mismo sería inútil.
Por lo tanto, necesitaría un buen formato de esa representación de cadena de imagen que el que podría usarse con alguna función SQL para encontrar una forma similar u otra. Por ejemplo, phash crea hashes de percepción, así que cuando dos números están cerca, las imágenes también deberían estar cerca, así que solo necesito encontrar las distancias más cercanas. Pero es de nuevo la biblioteca externa.
¿Hay alguna manera fácil?
Bajándolo de una manera académica, lo que estás buscando es una función de similitud que toma dos imágenes y devuelve un indicador de cuán lejos / similar están las dos imágenes. Este indicador podría ser fácilmente un número decimal que oscila entre -1 y 1 (muy lejos de estar muy cerca). Una vez que tenga esta función, puede establecer una imagen como referencia y comparar todas las imágenes con ella. Luego, encontrar las imágenes similares a una es tan simple como encontrar el factor de similitud más cercano que se realiza con una simple búsqueda en un campo doble dentro de un RDBMS como MySQL.
Ahora todo lo que queda es cómo definir la función de similitud. Para ser honesto, este es un problema específico. Depende de lo que llames similar. Pero la covariance suele ser un buen punto de partida, solo necesita que sus dos imágenes sean del mismo tamaño, lo que creo que no es gran cosa. Sin embargo, puede encontrar muchas otras ideas buscando "medidas de similitud entre dos imágenes".
Escalado la imagen a 8x8, luego convierto RGB a HSV de 1 byte, por lo que el hash del resultado es una cadena de 172 bytes.
HSVHSVHSVHSVHSVHSVHSVHSV... (from 8x8 block, 172 bytes long)
0fff0f3ffff4373f346fff00...
No es 100% exacto (no se encuentran algunos duplicados) pero funciona bien y parece que no hay resultados falsos positivos.
He tenido este mismo problema antes.
Siéntase libre de copiar lo que hice, y con suerte le ayudará / resolverá su problema.
Como lo resolví
Mi primera idea que falló, similar a lo que puedes estar pensando, es que terminé haciendo cadenas para cada imagen (sin importar el tamaño). Pero rápidamente resolví que esto llena tu base de datos súper rápido y no fue efectivo.
La siguiente opción (que funciona) era una imagen más pequeña (como su idea de 5px
), e hice exactamente eso, pero con imágenes de 10px
* 10px
. La forma en que creé el "hash" para cada imagen era la función imagecolorat()
.
Al recibir los colores rgb
para la imagen, los redondeé a los 50
más cercanos, para que los colores fueran menos específicos. Ese número ( 50
) es lo que desea cambiar dependiendo de qué tan específico desea que sean sus búsquedas.
por ejemplo:
// Pixel RGB
rgb(105, 126, 225) // Original
rgb(100, 150, 250) // After rounding numbers to nearest 50
Después de hacer esto a cada píxel ( 10px
* 10px
le devolverá 100 rgb()
), los convertí en una matriz y los almacené en la base de datos como base64_encode()
y serialize()
.
Al hacer la búsqueda de imágenes que son similares, hice el mismo proceso exacto a la imagen que querían cargar, y luego extraje ''hashes'' de imágenes de la base de datos para compararlos todos, y ver qué tenían los rgb
redondos coincidentes.
Consejos
Cuanto más grande sea
50
en el redondeo dergb
, menos específica será su búsqueda (y viceversa).Si desea que su SQL sea más específico, puede ser mejor almacenar información adicional / específica sobre la imagen en la base de datos, de modo que pueda limitar las búsquedas que obtiene en la base de datos. ej . si la relación de aspecto es
4:3
, solo extraiga las imágenes alrededor de4:3
de la base de datos. (etc)Puede ser difícil obtener esto perfectamente
5px
*5px
, por lo que una sugerencia es phpthumb . Lo utilicé con la sintaxis:
phpthumb.php?src=IMAGE_NAME_HERE.png&w=10&h=10&zc=1 // &w= width of your image // &h= height of your image // &zc= zoom control. 0:Keep aspect ratio, 1:Change to suit your width+height
Buena suerte amigo, espero poder ayudar.
Para una implementación sencilla de php echa un vistazo: https://github.com/kennethrapp/phasher
Sin embargo, me pregunto si hay una función mySql nativa para "comparar" (vea la clase php arriba)