Algorithmus zum Auffinden ähnlicher Bilder

83

Ich benötige einen Algorithmus, der bestimmen kann, ob zwei Bilder "ähnlich" sind und ähnliche Muster in Bezug auf Farbe, Helligkeit, Form usw. erkennen. Möglicherweise benötige ich einige Hinweise darauf, welche Parameter das menschliche Gehirn verwendet, um Bilder zu "kategorisieren". ..

Ich habe mir hausdorffbasiertes Matching angesehen, aber das scheint hauptsächlich für das Matching transformierter Objekte und Formmuster zu sein.

Kitsune
quelle
Es gibt einige gute Antworten in dieser anderen ähnlichen Frage: stackoverflow.com/questions/25977/…
blak
2
viele "könnte" und "könnte". Versucht jemand all diese Vorschläge und weiß, was am besten ist?
John Ktejik

Antworten:

60

Ich habe etwas Ähnliches getan, indem ich Bilder mithilfe der Wavelet-Transformation in Signaturen zerlegt habe .

Mein Ansatz war es, die signifikantesten n Koeffizienten aus jedem transformierten Kanal auszuwählen und deren Position aufzuzeichnen. Dies erfolgte durch Sortieren der Liste der Tupel (Leistung, Ort) nach abs (Leistung). Ähnliche Bilder haben Ähnlichkeiten, da sie an denselben Stellen signifikante Koeffizienten aufweisen.

Ich fand es am besten, das Bild in das YUV-Format umzuwandeln, wodurch Sie effektiv Ähnlichkeiten in Form (Y-Kanal) und Farbe (UV-Kanäle) gewichten können.

Sie finden meine Implementierung des oben genannten in mactorii , an dem ich leider nicht so viel gearbeitet habe, wie ich sollte :-)

Eine andere Methode, die einige meiner Freunde mit überraschend guten Ergebnissen angewendet haben, besteht darin, die Größe Ihres Bildes einfach auf die Größe eines 4x4-Pixels und eines Speichers zu ändern, die Ihre Signatur sind. Wie ähnlich 2 Bilder sind, kann beispielsweise durch Berechnen des Manhattan-Abstands zwischen den 2 Bildern unter Verwendung entsprechender Pixel bewertet werden. Ich habe nicht die Details, wie sie die Größenänderung durchgeführt haben, daher müssen Sie möglicherweise mit den verschiedenen für diese Aufgabe verfügbaren Algorithmen spielen, um einen geeigneten zu finden.

Freiraum
quelle
7
Die Methode zur Größenänderung auf 4x4 ist eine großartige Idee (nicht, dass Ihre Methode auch nicht großartig ist), aber die erste ist einfacher.
Alix Axel
@freespace, könnten Sie bitte erklären, dass "die Manhattan-Entfernung zwischen den beiden Bildern unter Verwendung entsprechender Pixel berechnet wird"
Ambika
1
@Ambika: Behandle die Farbe jedes Pixels als einen Vektor der Länge 3 und berechne den Manhattan-Abstand zwischen den entsprechenden Pixeln in den zu vergleichenden Bildern. Das gibt Ihnen 4 Manhattan Entfernungen. Wie Sie daraus ein einzelnes Maß ableiten, liegt bei Ihnen. Am naheliegendsten ist es, sie zusammenzufassen.
Freiraum
45

pHash könnte Sie interessieren.

Wahrnehmungshash n. Ein Fingerabdruck einer Audio-, Video- oder Bilddatei, der mathematisch auf dem darin enthaltenen Audio- oder Videoinhalt basiert. Im Gegensatz zu kryptografischen Hash-Funktionen, die auf dem Lawineneffekt kleiner Änderungen der Eingabe beruhen, die zu drastischen Änderungen der Ausgabe führen, sind Wahrnehmungs-Hashes "nahe" beieinander, wenn die Eingaben visuell oder auditorisch ähnlich sind.

Alvis
quelle
8
Ich habe gerade die Website von pHash überprüft. Derzeit haben sie diese Funktion auf ihrer Website, mit der Sie zwei Bilder hochladen können und die Ihnen sagt, ob sie ähnlich sind oder nicht. Ich habe ungefähr 10 Bilder ausprobiert, die ähnlich waren, und 10, die es nicht waren. Die Erfolgsquote war leider nicht so beeindruckend.
Rodrigo-Silveira
2
pHash ist eigentlich ziemlich streng. Vielleicht möchten Sie 'ahash' oder durchschnittlichen Hash verwenden, der tendenziell weniger streng ist. Eine Python-Implementierung finden Sie hier github.com/JohannesBuchner/imagehash/blob/master/…
Rohit
13

Ich habe SIFT verwendet , um dasselbe Objekt in verschiedenen Bildern erneut zu erkennen. Es ist wirklich mächtig, aber ziemlich komplex und könnte übertrieben sein. Wenn die Bilder ziemlich ähnlich sein sollen, können einige einfache Parameter, die auf dem Unterschied zwischen den beiden Bildern basieren, Ihnen einiges sagen. Einige Hinweise:

  • Normalisieren Sie die Bilder, dh stellen Sie die durchschnittliche Helligkeit beider Bilder gleich, indem Sie die durchschnittliche Helligkeit beider Bilder berechnen und die hellste entsprechend der Ration verkleinern (um ein Abschneiden auf höchster Ebene zu vermeiden), insbesondere wenn Sie mehr an Form als an Form interessiert sind Farbe.
  • Summe der Farbdifferenzen über dem normalisierten Bild pro Kanal.
  • Finden Sie Kanten in den Bildern und messen Sie den Abstand zwischen den Kantenpixeln in beiden Bildern. (für Form)
  • Teilen Sie die Bilder in eine Reihe von diskreten Regionen und vergleichen Sie die durchschnittliche Farbe jeder Region.
  • Schwellen Sie die Bilder auf einer (oder einer Reihe von) Ebene (n) und zählen Sie die Anzahl der Pixel, bei denen sich die resultierenden Schwarz / Weiß-Bilder unterscheiden.
jilles de wit
quelle
Können Sie auf den Code verweisen, der siebenähnliche Feturen verwendet, um die Bildähnlichkeit zu berechnen?
Mrgloom
Es tut mir leid, ich bin sicher, dass es öffentlich verfügbaren Code gibt, aber keinen, den ich kenne. Es gibt einige Beispiele auf dieser Seite. Zum Beispiel hier: stackoverflow.com/questions/5461148/…
jilles de wit
Das Accord Framework für .Net ( gemäß-framework.net ) bietet einige großartige Klassen für SURF, BagOfVisualWords, Harris Corner Detection usw. mit einer Reihe verschiedener Kernel und Clustering-Algorithmen.
Dynamichael
6

Mein Labor musste auch dieses Problem lösen, und wir verwendeten Tensorflow. Hier ist eine vollständige App- Implementierung zur Visualisierung der Bildähnlichkeit.

Auf dieser Seite finden Sie ein Tutorial zum Vektorisieren von Bildern für die Ähnlichkeitsberechnung . Hier ist der Python (den vollständigen Workflow finden Sie im Beitrag):

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()
duhaime
quelle
5

Sie könnten Perceptual Image Diff verwenden

Es ist ein Befehlszeilenprogramm, das zwei Bilder mithilfe einer Wahrnehmungsmetrik vergleicht. Das heißt, es wird ein Rechenmodell des menschlichen visuellen Systems verwendet, um zu bestimmen, ob zwei Bilder visuell unterschiedlich sind, sodass geringfügige Änderungen der Pixel ignoriert werden. Darüber hinaus wird die Anzahl der Fehlalarme drastisch reduziert, die durch Unterschiede bei der Zufallszahlengenerierung, dem Betriebssystem oder der Maschinenarchitektur verursacht werden.

Alejandro Bologna
quelle
4

Es ist ein schwieriges Problem! Es hängt davon ab, wie genau Sie sein müssen, und davon, mit welcher Art von Bildern Sie arbeiten. Sie können Histogramme verwenden, um Farben zu vergleichen, aber dies berücksichtigt offensichtlich nicht die räumliche Verteilung dieser Farben innerhalb der Bilder (dh der Formen). Die Kantenerkennung, gefolgt von einer Art Segmentierung (dh Auswahl der Formen), kann ein Muster für den Abgleich mit einem anderen Bild liefern. Sie können Coocurence-Matrizen verwenden, um Texturen zu vergleichen, indem Sie die Bilder als Matrizen von Pixelwerten betrachten und diese Matrizen vergleichen. Es gibt einige gute Bücher über Bildanpassung und Bildverarbeitung - Eine Suche bei Amazon wird einige finden.

Hoffe das hilft!

Ben
quelle
3

Es gibt verwandte Forschungen unter Verwendung von Kohonen-Neuronalen Netzen / selbstorganisierenden Karten

Beide akademischeren Systeme (Google für PicSOM) oder weniger akademische
( http://www.generation5.org/content/2004/aiSomPic.asp , (möglicherweise nicht für alle Arbeit enviroments)) Präsentationen existieren.

EPa
quelle
3

Die Berechnung der Summe der Quadrate der Differenzen der Pixelfarbwerte einer drastisch verkleinerten Version (z. B. 6 x 6 Pixel) funktioniert gut. Identische Bilder ergeben 0, ähnliche Bilder ergeben kleine Zahlen, unterschiedliche Bilder ergeben große.

Die Idee der anderen oben genannten Leute, in YUV einzudringen, klingt zunächst faszinierend - während meine Idee großartig funktioniert, möchte ich, dass meine Bilder als "anders" berechnet werden, damit sie ein korrektes Ergebnis liefern - selbst aus der Sicht eines farbenblinden Beobachters.

chris
quelle
2

Das klingt nach einem Sehproblem. Vielleicht möchten Sie sich mit Adaptive Boosting sowie dem Burns Line Extraction-Algorithmus befassen. Die Konzepte in diesen beiden sollten bei der Lösung dieses Problems helfen. Die Kantenerkennung ist ein noch einfacherer Einstieg, wenn Sie mit Vision-Algorithmen noch nicht vertraut sind, da hier die Grundlagen erläutert werden.

Soweit Parameter für die Kategorisierung:

  • Farbpalette & Position (Verlaufsberechnung, Histogramm der Farben)
  • Enthaltene Formen (Ada. Boosting / Training zum Erkennen von Formen)
willasaywhat
quelle
2

Abhängig davon, wie viele genaue Ergebnisse Sie benötigen, können Sie die Bilder einfach in nxn Pixelblöcke aufteilen und analysieren. Wenn Sie im ersten Block unterschiedliche Ergebnisse erhalten, können Sie die Verarbeitung nicht beenden, was zu einigen Leistungsverbesserungen führt.

Zur Analyse der Quadrate können Sie beispielsweise die Summe der Farbwerte erhalten.


quelle
1

Sie könnten eine Art Blockanpassungs-Bewegungsschätzung zwischen den beiden Bildern durchführen und die Gesamtsumme der Residuen und Bewegungsvektorkosten messen (ähnlich wie bei einem Video-Encoder). Dies würde die Bewegung kompensieren; Führen Sie für Bonuspunkte eine Schätzung der affinen Transformationsbewegung durch (gleicht Zooms und Dehnungen und ähnliches aus). Sie können auch überlappende Blöcke oder optischen Fluss ausführen.

Dunkler Shikari
quelle
1

In einem ersten Durchgang können Sie versuchen, Farbhistogramme zu verwenden. Sie müssen jedoch Ihre Problemdomäne wirklich eingrenzen. Generische Bildanpassung ist ein sehr schwieriges Problem.

Dima
quelle
1

Entschuldigung für die späte Teilnahme an der Diskussion.

Wir können sogar die ORB-Methode verwenden, um ähnliche Merkmalspunkte zwischen zwei Bildern zu erkennen. Der folgende Link gibt eine direkte Implementierung von ORB in Python

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

Sogar openCV hat eine direkte Implementierung von ORB. Wenn Sie weitere Informationen haben, folgen Sie dem unten angegebenen Forschungsartikel.

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

Vivek Srinivasan
quelle
0

Im anderen Thread gibt es einige gute Antworten dazu, aber ich frage mich, ob etwas mit einer Spektralanalyse funktionieren würde. Zerlegen Sie das Bild in Phasen- und Amplitudeninformationen und vergleichen Sie diese. Dies kann einige Probleme mit Zuschneiden, Transformation und Intensitätsunterschieden vermeiden. Jedenfalls spekuliere ich nur, da dies ein interessantes Problem zu sein scheint. Wenn Sie http://scholar.google.com durchsucht haben , könnten Sie sicher mehrere Artikel dazu finden.

neuroguy123
quelle
Die Spektralanalyse erfolgt mit Fourier-Transformation. Es gibt kein Farbhistogramm, da Sie das Bild aus den beiden Teilen - imaginär und real - rekonstruieren können. (Ich weiß nicht, ob es funktionieren wird, ich möchte Sie nur wissen lassen, dass es nicht zu dieser Kategorie gehört.)
Nlucaroni
Ja, eine Fourier-Transformation habe ich gemeint.
Neuroguy123