Domanda

Ho bisogno di un algoritmo in grado di determinare se due immagini sono "simili" e riconoscere modelli simili di colore, luminosità, forma, ecc.Potrei aver bisogno di alcune indicazioni su quali parametri utilizza il cervello umano per "categorizzare" le immagini...

Ho esaminato l'abbinamento basato su Hausdorff, ma sembra principalmente per abbinare oggetti trasformati e modelli di forma.

È stato utile?

Soluzione

Ho fatto qualcosa di simile, scomponendo le immagini in firme utilizzando trasformata wavelet.

Il mio approccio è stato quello di scegliere quello più significativo N coefficienti di ciascun canale trasformato e registrandone la posizione.Ciò è stato fatto ordinando l'elenco delle tuple (potenza, posizione) in base a abs(potenza).Immagini simili condivideranno somiglianze in quanto avranno coefficienti significativi negli stessi luoghi.

Ho scoperto che era meglio trasformare l'immagine nel formato YUV, che consente effettivamente di ponderare la somiglianza nella forma (canale Y) e nel colore (canali UV).

Puoi trovare la mia implementazione di quanto sopra in mactorii, su cui purtroppo non ho lavorato quanto avrei dovuto :-)

Un altro metodo, che alcuni miei amici hanno utilizzato con risultati sorprendentemente buoni, è semplicemente ridimensionare l'immagine per dire, un pixel 4x4 e memorizzare la tua firma.Quanto sono simili 2 immagini può essere valutato, ad esempio, calcolando the Distanza da Manhattan tra le 2 immagini, utilizzando i pixel corrispondenti.Non ho i dettagli su come hanno eseguito il ridimensionamento, quindi potresti dover giocare con i vari algoritmi disponibili per quell'attività per trovarne uno adatto.

Altri suggerimenti

pHash potrebbe interessarti.

hash percettivo n.un'impronta digitale di un file audio, video o immagine che si basa matematicamente sul contenuto audio o visivo in esso contenuto.A differenza delle funzioni di hash crittografiche che si basano sull'effetto valanga di piccoli cambiamenti nell'input che portano a cambiamenti drastici nell'output, gli hash percettivi sono "vicini" tra loro se gli input sono visivamente o uditivamente simili.

ho usato VAGLIARE per rilevare nuovamente lo stesso oggetto in immagini diverse.È davvero potente ma piuttosto complesso e potrebbe essere eccessivo.Se si suppone che le immagini siano abbastanza simili, alcuni semplici parametri basati sulla differenza tra le due immagini possono dirti parecchio.Alcuni suggerimenti:

  • Normalizza le immagini, ad es.rendi uguale la luminosità media di entrambe le immagini calcolando la luminosità media di entrambe e ridimensionando la più luminosa in base alla razione (per evitare il ritaglio al livello più alto)), soprattutto se sei più interessato alla forma che al colore.
  • Somma della differenza di colore rispetto all'immagine normalizzata per canale.
  • trova i bordi nelle immagini e misura la distanza tra i pixel del bordo in entrambe le immagini.(per la forma)
  • Dividi le immagini in una serie di regioni distinte e confronta il colore medio di ciascuna regione.
  • Soglia le immagini a uno (o una serie di) livelli e conta il numero di pixel in cui le immagini in bianco/nero risultanti differiscono.

Potresti usare Diff. immagine percettiva

È un'utilità da riga di comando che confronta due immagini utilizzando una metrica percettiva.Cioè, utilizza un modello computazionale del sistema visivo umano per determinare se due immagini sono visivamente diverse, quindi i piccoli cambiamenti nei pixel vengono ignorati.Inoltre, riduce drasticamente il numero di falsi positivi causati da differenze nella generazione di numeri casuali, nel sistema operativo o nell'architettura della macchina.

È un problema difficile!Dipende da quanto devi essere preciso e dal tipo di immagini con cui stai lavorando.Puoi utilizzare gli istogrammi per confrontare i colori, ma ciò ovviamente non tiene conto della distribuzione spaziale di tali colori all'interno delle immagini (ad es.le forme).Rilevamento dei bordi seguito da una sorta di segmentazione (ad es.individuando le forme) può fornire un modello per la corrispondenza con un'altra immagine.È possibile utilizzare matrici di cooperazione per confrontare trame, considerando le immagini come matrici di valori di pixel e confrontando tali matrici.Ci sono alcuni buoni libri là fuori sulla corrispondenza delle immagini e sulla visione artificiale: una ricerca su Amazon ne troverà alcuni.

Spero che questo ti aiuti!

Anche il mio laboratorio doveva risolvere questo problema e abbiamo utilizzato Tensorflow.Ecco un applicazione completa implementazione per visualizzare la somiglianza delle immagini.

Per un tutorial sulla vettorizzazione delle immagini per il calcolo della somiglianza, dai un'occhiata questa pagina.Ecco il Python (di nuovo, vedi il post per il flusso di lavoro completo):

from __future__ import absolute_import, division, print_function

"""

This is a modification of the classify_images.py
script in Tensorflow. The original script produces
string labels for input images (e.g. you input a picture
of a cat and the script returns the string "cat"); this
modification reads in a directory of images and 
generates a vector representation of the image using
the penultimate layer of neural network weights.

Usage: python classify_images.py "../image_dir/*.jpg"

"""

# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================

"""Simple image classification with Inception.

Run image classification with Inception trained on ImageNet 2012 Challenge data
set.

This program creates a graph from a saved GraphDef protocol buffer,
and runs inference on an input JPEG image. It outputs human readable
strings of the top 5 predictions along with their probabilities.

Change the --image_file argument to any jpg image to compute a
classification of that image.

Please see the tutorial and website for a detailed description of how
to use this script to perform image recognition.

https://tensorflow.org/tutorials/image_recognition/
"""

import os.path
import re
import sys
import tarfile
import glob
import json
import psutil
from collections import defaultdict
import numpy as np
from six.moves import urllib
import tensorflow as tf

FLAGS = tf.app.flags.FLAGS

# classify_image_graph_def.pb:
#   Binary representation of the GraphDef protocol buffer.
# imagenet_synset_to_human_label_map.txt:
#   Map from synset ID to a human readable string.
# imagenet_2012_challenge_label_map_proto.pbtxt:
#   Text representation of a protocol buffer mapping a label to synset ID.
tf.app.flags.DEFINE_string(
    'model_dir', '/tmp/imagenet',
    """Path to classify_image_graph_def.pb, """
    """imagenet_synset_to_human_label_map.txt, and """
    """imagenet_2012_challenge_label_map_proto.pbtxt.""")
tf.app.flags.DEFINE_string('image_file', '',
                           """Absolute path to image file.""")
tf.app.flags.DEFINE_integer('num_top_predictions', 5,
                            """Display this many predictions.""")

# pylint: disable=line-too-long
DATA_URL = 'http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz'
# pylint: enable=line-too-long


class NodeLookup(object):
  """Converts integer node ID's to human readable labels."""

  def __init__(self,
               label_lookup_path=None,
               uid_lookup_path=None):
    if not label_lookup_path:
      label_lookup_path = os.path.join(
          FLAGS.model_dir, 'imagenet_2012_challenge_label_map_proto.pbtxt')
    if not uid_lookup_path:
      uid_lookup_path = os.path.join(
          FLAGS.model_dir, 'imagenet_synset_to_human_label_map.txt')
    self.node_lookup = self.load(label_lookup_path, uid_lookup_path)

  def load(self, label_lookup_path, uid_lookup_path):
    """Loads a human readable English name for each softmax node.

    Args:
      label_lookup_path: string UID to integer node ID.
      uid_lookup_path: string UID to human-readable string.

    Returns:
      dict from integer node ID to human-readable string.
    """
    if not tf.gfile.Exists(uid_lookup_path):
      tf.logging.fatal('File does not exist %s', uid_lookup_path)
    if not tf.gfile.Exists(label_lookup_path):
      tf.logging.fatal('File does not exist %s', label_lookup_path)

    # Loads mapping from string UID to human-readable string
    proto_as_ascii_lines = tf.gfile.GFile(uid_lookup_path).readlines()
    uid_to_human = {}
    p = re.compile(r'[n\d]*[ \S,]*')
    for line in proto_as_ascii_lines:
      parsed_items = p.findall(line)
      uid = parsed_items[0]
      human_string = parsed_items[2]
      uid_to_human[uid] = human_string

    # Loads mapping from string UID to integer node ID.
    node_id_to_uid = {}
    proto_as_ascii = tf.gfile.GFile(label_lookup_path).readlines()
    for line in proto_as_ascii:
      if line.startswith('  target_class:'):
        target_class = int(line.split(': ')[1])
      if line.startswith('  target_class_string:'):
        target_class_string = line.split(': ')[1]
        node_id_to_uid[target_class] = target_class_string[1:-2]

    # Loads the final mapping of integer node ID to human-readable string
    node_id_to_name = {}
    for key, val in node_id_to_uid.items():
      if val not in uid_to_human:
        tf.logging.fatal('Failed to locate: %s', val)
      name = uid_to_human[val]
      node_id_to_name[key] = name

    return node_id_to_name

  def id_to_string(self, node_id):
    if node_id not in self.node_lookup:
      return ''
    return self.node_lookup[node_id]


def create_graph():
  """Creates a graph from saved GraphDef file and returns a saver."""
  # Creates graph from saved graph_def.pb.
  with tf.gfile.FastGFile(os.path.join(
      FLAGS.model_dir, 'classify_image_graph_def.pb'), 'rb') as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())
    _ = tf.import_graph_def(graph_def, name='')


def run_inference_on_images(image_list, output_dir):
  """Runs inference on an image list.

  Args:
    image_list: a list of images.
    output_dir: the directory in which image vectors will be saved

  Returns:
    image_to_labels: a dictionary with image file keys and predicted
      text label values
  """
  image_to_labels = defaultdict(list)

  create_graph()

  with tf.Session() as sess:
    # Some useful tensors:
    # 'softmax:0': A tensor containing the normalized prediction across
    #   1000 labels.
    # 'pool_3:0': A tensor containing the next-to-last layer containing 2048
    #   float description of the image.
    # 'DecodeJpeg/contents:0': A tensor containing a string providing JPEG
    #   encoding of the image.
    # Runs the softmax tensor by feeding the image_data as input to the graph.
    softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')

    for image_index, image in enumerate(image_list):
      try:
        print("parsing", image_index, image, "\n")
        if not tf.gfile.Exists(image):
          tf.logging.fatal('File does not exist %s', image)

        with tf.gfile.FastGFile(image, 'rb') as f:
          image_data =  f.read()

          predictions = sess.run(softmax_tensor,
                          {'DecodeJpeg/contents:0': image_data})

          predictions = np.squeeze(predictions)

          ###
          # Get penultimate layer weights
          ###

          feature_tensor = sess.graph.get_tensor_by_name('pool_3:0')
          feature_set = sess.run(feature_tensor,
                          {'DecodeJpeg/contents:0': image_data})
          feature_vector = np.squeeze(feature_set)        
          outfile_name = os.path.basename(image) + ".npz"
          out_path = os.path.join(output_dir, outfile_name)
          np.savetxt(out_path, feature_vector, delimiter=',')

          # Creates node ID --> English string lookup.
          node_lookup = NodeLookup()

          top_k = predictions.argsort()[-FLAGS.num_top_predictions:][::-1]
          for node_id in top_k:
            human_string = node_lookup.id_to_string(node_id)
            score = predictions[node_id]
            print("results for", image)
            print('%s (score = %.5f)' % (human_string, score))
            print("\n")

            image_to_labels[image].append(
              {
                "labels": human_string,
                "score": str(score)
              }
            )

        # close the open file handlers
        proc = psutil.Process()
        open_files = proc.open_files()

        for open_file in open_files:
          file_handler = getattr(open_file, "fd")
          os.close(file_handler)
      except:
        print('could not process image index',image_index,'image', image)

  return image_to_labels


def maybe_download_and_extract():
  """Download and extract model tar file."""
  dest_directory = FLAGS.model_dir
  if not os.path.exists(dest_directory):
    os.makedirs(dest_directory)
  filename = DATA_URL.split('/')[-1]
  filepath = os.path.join(dest_directory, filename)
  if not os.path.exists(filepath):
    def _progress(count, block_size, total_size):
      sys.stdout.write('\r>> Downloading %s %.1f%%' % (
          filename, float(count * block_size) / float(total_size) * 100.0))
      sys.stdout.flush()
    filepath, _ = urllib.request.urlretrieve(DATA_URL, filepath, _progress)
    print()
    statinfo = os.stat(filepath)
    print('Succesfully downloaded', filename, statinfo.st_size, 'bytes.')
  tarfile.open(filepath, 'r:gz').extractall(dest_directory)


def main(_):
  maybe_download_and_extract()
  if len(sys.argv) < 2:
    print("please provide a glob path to one or more images, e.g.")
    print("python classify_image_modified.py '../cats/*.jpg'")
    sys.exit()

  else:
    output_dir = "image_vectors"
    if not os.path.exists(output_dir):
      os.makedirs(output_dir)

    images = glob.glob(sys.argv[1])
    image_to_labels = run_inference_on_images(images, output_dir)

    with open("image_to_labels.json", "w") as img_to_labels_out:
      json.dump(image_to_labels, img_to_labels_out)

    print("all done")
if __name__ == '__main__':
  tf.app.run()

Alcune soluzioni software di riconoscimento delle immagini in realtà non sono puramente basate su algoritmi, ma fanno uso di rete neurale concetto invece.Guardare http://en.wikipedia.org/wiki/Artificial_neural_network e precisamente NeuronDotNet che include anche campioni interessanti: http://neurondotnet.freehostia.com/index.html

Esiste una ricerca correlata che utilizza le reti neurali Kohonen/mappe autoorganizzanti

Entrambi i sistemi più accademici (Google per PicSOM) o meno accademici
( http://www. generation5.org/content/2004/aiSomPic.asp , (forse non è adatto a tutti gli ambienti di lavoro)) esistono presentazioni.

Calcolando la somma dei quadrati delle differenze dei valori di colore dei pixel di una versione drasticamente ridotta (es:6x6 pixel) funziona bene.Immagini identiche producono 0, immagini simili producono numeri piccoli, immagini diverse producono numeri grandi.

L'idea degli altri ragazzi sopra di entrare in YUV sembra inizialmente intrigante: sebbene la mia idea funzioni alla grande, voglio che le mie immagini vengano calcolate come "diverse" in modo da produrre un risultato corretto, anche dal punto di vista di un osservatore daltonico.

Sembra un problema di vista.Potresti voler esaminare Adaptive Boosting e l'algoritmo Burns Line Extraction.I concetti in questi due dovrebbero aiutare ad affrontare questo problema.Il rilevamento dei bordi è un punto di partenza ancora più semplice se sei nuovo agli algoritmi di visione, poiché spiega le nozioni di base.

Per quanto riguarda i parametri per la categorizzazione:

  • Tavolozza colori e posizione (calcolo del gradiente, istogramma dei colori)
  • Forme contenute (Ada.Potenziamento/Allenamento per rilevare forme)

A seconda della precisione dei risultati di cui hai bisogno, puoi semplicemente suddividere le immagini in blocchi di n x n pixel e analizzarle.Se ottieni risultati diversi nel primo blocco, non puoi interrompere l'elaborazione, con conseguenti miglioramenti delle prestazioni.

Per analizzare i quadrati puoi ad esempio ottenere la somma dei valori dei colori.

È possibile eseguire una sorta di stima del movimento di corrispondenza dei blocchi tra le due immagini e misurare la somma complessiva dei residui e dei costi del vettore di movimento (proprio come si farebbe con un codificatore video).Ciò compenserebbe il movimento;per i punti bonus, esegui la stima del movimento di trasformazione affine (compensa zoom, allungamenti e simili).Potresti anche creare blocchi sovrapposti o flusso ottico.

Come primo passaggio, puoi provare a utilizzare gli istogrammi a colori.Tuttavia, devi davvero restringere il dominio problematico.La corrispondenza generica delle immagini è un problema molto difficile.

Ho trovato molto utile questo articolo che spiega come funziona:

http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html

Mi scuso per essermi unito tardi alla discussione.

Possiamo anche utilizzare la metodologia ORB per rilevare punti con caratteristiche simili tra due immagini.Il collegamento seguente fornisce l'implementazione diretta di ORB in Python

http://scikit-image.org/docs/dev/auto_examples/plot_orb.html

Anche openCV ha un'implementazione diretta di ORB.Se hai maggiori informazioni segui l'articolo di ricerca fornito di seguito.

https://www.researchgate.net/publication/292157133_Image_Matching_Using_SIFT_SURF_BRIEF_and_ORB_Performance_Comparison_for_Distorted_Images

Ci sono alcune buone risposte nell'altro thread su questo argomento, ma mi chiedo se qualcosa che coinvolga un'analisi spettrale funzionerebbe?Cioè, scomponi l'immagine nelle sue informazioni di fase e ampiezza e confrontale.Ciò potrebbe evitare alcuni dei problemi legati al ritaglio, alla trasformazione e alle differenze di intensità.Ad ogni modo, sono solo mie speculazioni poiché sembra un problema interessante.Se hai cercato http://scholar.google.com Sono sicuro che potresti produrre diversi documenti su questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top