Thuật toán tìm hình ảnh tương tự


83

Tôi cần một thuật toán có thể xác định xem hai hình ảnh có 'giống nhau' hay không và nhận ra các mẫu tương tự về màu sắc, độ sáng, hình dạng, v.v. Tôi có thể cần một số gợi ý về những thông số mà não người sử dụng để 'phân loại' hình ảnh. ..

Tôi đã xem xét đối sánh dựa trên hausdorff nhưng điều đó dường như chủ yếu để đối sánh các đối tượng và mẫu hình dạng đã được biến đổi.


Có một số câu trả lời hay cho câu hỏi tương tự khác này: stackoverflow.com/questions/25977/…
blak

2
rất nhiều 'coulds' và 'mights'. Bất cứ ai cũng thử tất cả những gợi ý này, và biết điều gì là tốt nhất?
john ktejik

Câu trả lời:


60

Tôi đã làm điều gì đó tương tự, bằng cách phân tách hình ảnh thành chữ ký bằng cách sử dụng biến đổi wavelet .

Cách tiếp cận của tôi là chọn n hệ số quan trọng nhất từ mỗi kênh được chuyển đổi và ghi lại vị trí của chúng. Điều này được thực hiện bằng cách sắp xếp danh sách các bộ giá trị (công suất, vị trí) theo abs (công suất). Các hình ảnh tương tự sẽ có điểm giống nhau ở chỗ chúng sẽ có hệ số đáng kể ở cùng một vị trí.

Tôi thấy tốt nhất là chuyển đổi hình ảnh sang định dạng YUV, điều này cho phép bạn cân bằng hiệu quả sự tương đồng về hình dạng (kênh Y) và màu sắc (kênh UV).

Bạn có thể tìm thấy cách triển khai của tôi ở trên trong mactorii , tiếc là tôi đã không làm việc nhiều như tôi nên có :-)

Một phương pháp khác, mà một số người bạn của tôi đã sử dụng với kết quả tốt đáng ngạc nhiên, là chỉ cần thay đổi kích thước hình ảnh của bạn xuống, chẳng hạn như pixel 4x4 và lưu trữ đó là chữ ký của bạn. Có thể cho điểm 2 hình ảnh giống nhau như thế nào bằng cách tính khoảng cách Manhattan giữa 2 hình ảnh, sử dụng các pixel tương ứng. Tôi không có chi tiết về cách họ thực hiện việc thay đổi kích thước, vì vậy bạn có thể phải chơi với các thuật toán khác nhau có sẵn cho nhiệm vụ đó để tìm một thuật toán phù hợp.


7
Phương pháp thay đổi kích thước thành 4x4 là một ý tưởng tuyệt vời (không phải là phương pháp của bạn cũng không tuyệt vời) nhưng cách đầu tiên đơn giản hơn.
Alix Axel

@freespace, bạn có thể vui lòng giải thích điều này "tính toán khoảng cách Manhattan giữa 2 hình ảnh, sử dụng pixel tương ứng"
Ambika

1
@Ambika: coi màu của mỗi pixel như một vectơ có độ dài 3 và tính khoảng cách Manhattan giữa các pixel tương ứng trong các hình ảnh được so sánh. Điều đó cho bạn 4 khoảng cách Manhattan. Làm thế nào bạn có được một thước đo duy nhất từ ​​đó là tùy thuộc vào bạn. Rõ ràng nhất là tổng hợp chúng lại với nhau.
freespace

45

pHash có thể khiến bạn quan tâm.

tri giác băm n. dấu vân tay của tệp âm thanh, video hoặc hình ảnh được toán học dựa trên nội dung âm thanh hoặc hình ảnh có bên trong. Không giống như các hàm băm mật mã dựa vào hiệu ứng tuyết lở của những thay đổi nhỏ trong đầu vào dẫn đến những thay đổi mạnh mẽ trong đầu ra, các hàm băm cảm nhận "gần gũi" với nhau nếu các đầu vào giống nhau về mặt trực quan hoặc thính giác.


8
Chỉ cần kiểm tra trang web của pHash. Họ hiện có tính năng này trên trang web của họ cho phép bạn tải lên hai hình ảnh và nó cho bạn biết liệu chúng có giống nhau hay không. Tôi đã thử khoảng 10 hình ảnh tương tự và 10 hình ảnh không giống nhau. Thật không may, tỷ lệ thành công không quá ấn tượng.
rodrigo-silveira

2
pHash thực sự khá nghiêm ngặt, bạn có thể muốn sử dụng 'ahash' hoặc băm trung bình, có xu hướng ít nghiêm ngặt hơn. Bạn có thể tìm thấy cách triển khai python tại đây github.com/Johannes domainsner/imagehash/blob/master/
Rohit

13

Tôi đã sử dụng SIFT để phát hiện lại cùng một đối tượng trong các hình ảnh khác nhau. Nó thực sự mạnh mẽ nhưng khá phức tạp và có thể quá mức cần thiết. Nếu các hình ảnh được cho là khá giống nhau, một số thông số đơn giản dựa trên sự khác biệt giữa hai hình ảnh có thể cho bạn biết khá nhiều. Một số gợi ý:

  • Chuẩn hóa hình ảnh, tức là làm cho độ sáng trung bình của cả hai hình ảnh giống nhau bằng cách tính toán độ sáng trung bình của cả hai và giảm mức sáng nhất theo khẩu phần (để tránh cắt ở mức cao nhất)) đặc biệt nếu bạn quan tâm đến hình dạng hơn màu sắc.
  • Tổng chênh lệch màu so với hình ảnh chuẩn hóa trên mỗi kênh.
  • tìm các cạnh trong hình ảnh và đo khoảng cách giữa các pixel cạnh trong cả hai hình ảnh. (cho hình dạng)
  • Chia hình ảnh thành một tập hợp các vùng rời rạc và so sánh màu trung bình của từng vùng.
  • Đặt ngưỡng hình ảnh ở một (hoặc một tập hợp) cấp độ và đếm số lượng pixel mà các hình ảnh đen / trắng thu được khác nhau.

bạn có thể trỏ đến mã sử dụng các tìm nạp giống như sàng lọc để tính độ giống nhau của hình ảnh không?
mrgloom

Tôi xin lỗi, tôi chắc chắn rằng có mã công khai, nhưng không có mã nào mà tôi biết. Có một số ví dụ trên trang web này. Ví dụ ở đây: stackoverflow.com/questions/5461148/…
jilles de wit

Accord Framework cho .Net ( accord-framework.net ) có một số lớp tuyệt vời để thực hiện SURF, BagOfVisualWords, Harris Corner Detection, v.v. với một loạt các nhân và thuật toán phân cụm khác nhau.
dynamichael

6

Phòng thí nghiệm của tôi cũng cần giải quyết vấn đề này và chúng tôi đã sử dụng Tensorflow. Đây là cách triển khai ứng dụng đầy đủ để hình dung sự giống nhau của hình ảnh.

Để có hướng dẫn về vector hóa hình ảnh để tính toán độ tương đồng, hãy xem trang này . Đây là Python (một lần nữa, hãy xem bài đăng để biết quy trình làm việc đầy đủ):

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()

5

Bạn có thể sử dụng Perceptual Image Diff

Đó là một tiện ích dòng lệnh so sánh hai hình ảnh bằng cách sử dụng một số liệu cảm nhận. Nghĩa là, nó sử dụng mô hình tính toán của hệ thống thị giác của con người để xác định xem hai hình ảnh có khác nhau về mặt thị giác hay không, vì vậy những thay đổi nhỏ về pixel sẽ bị bỏ qua. Thêm vào đó, nó làm giảm đáng kể số lần dương tính giả gây ra bởi sự khác biệt về sự khác biệt về tạo số ngẫu nhiên, hệ điều hành hoặc kiến ​​trúc máy.


4

Đó là một bài toán khó! Nó phụ thuộc vào mức độ chính xác của bạn và nó phụ thuộc vào loại hình ảnh bạn đang làm việc với. Bạn có thể sử dụng biểu đồ để so sánh màu sắc, nhưng điều đó rõ ràng không tính đến sự phân bố không gian của những màu đó trong ảnh (tức là các hình dạng). Việc phát hiện cạnh theo sau bởi một số loại phân đoạn (tức là chọn ra các hình dạng) có thể cung cấp một mẫu để đối sánh với hình ảnh khác. Bạn có thể sử dụng ma trận coocurence để so sánh các kết cấu, bằng cách coi hình ảnh là ma trận của các giá trị pixel và so sánh các ma trận đó. Có một số cuốn sách hay về đối sánh hình ảnh và thị giác máy - Tìm kiếm trên Amazon sẽ tìm thấy một số.

Hi vọng điêu nay co ich!



3

Có nghiên cứu liên quan sử dụng mạng nơ-ron Kohonen / bản đồ tự tổ chức

Cả hai hệ thống học thuật hơn (Google cho PicSOM) hoặc ít học thuật hơn
( http://www.generation5.org/content/2004/aiSomPic.asp , (có thể không phù hợp với tất cả các môi trường làm việc)) đều tồn tại.


3

Tính toán tổng bình phương của sự khác biệt của các giá trị màu pixel của một phiên bản thu nhỏ đáng kể (ví dụ: 6x6 pixel) hoạt động tốt. Các hình ảnh giống nhau cho kết quả bằng 0, các hình ảnh giống nhau mang lại số lượng nhỏ, các hình ảnh khác nhau mang lại số lượng lớn.

Ý tưởng đột nhập YUV của những người khác ở trên nghe có vẻ hấp dẫn - trong khi ý tưởng của tôi hoạt động tuyệt vời, tôi muốn hình ảnh của mình được tính là "khác biệt" để nó mang lại kết quả chính xác - ngay cả từ góc độ của một người quan sát bị mù màu.


2

Điều này nghe có vẻ như một vấn đề về thị lực. Bạn có thể muốn xem xét Tăng cường thích ứng cũng như thuật toán Khai thác dòng Burns. Các khái niệm trong hai điều này sẽ giúp tiếp cận vấn đề này. Phát hiện cạnh là một nơi đơn giản hơn để bắt đầu nếu bạn chưa quen với các thuật toán thị giác, vì nó giải thích những điều cơ bản.

Đối với các tham số để phân loại:

  • Bảng màu & Vị trí (Tính toán độ dốc, biểu đồ màu sắc)
  • Hình dạng chứa (Ada. Tăng cường / Đào tạo để phát hiện hình dạng)

2

Tùy thuộc vào mức độ chính xác kết quả bạn cần, bạn có thể chỉ cần chia nhỏ hình ảnh theo khối nxn pixel và phân tích chúng. Nếu bạn nhận được các kết quả khác nhau trong khối đầu tiên, bạn không thể ngừng xử lý, dẫn đến một số cải tiến về hiệu suất.

Ví dụ, để phân tích các ô vuông, bạn có thể lấy tổng các giá trị màu.



1

Bạn có thể thực hiện một số loại ước tính chuyển động khớp khối giữa hai hình ảnh và đo lường tổng phần dư và chi phí vectơ chuyển động (giống như cách làm trong bộ mã hóa video). Điều này sẽ bù đắp cho chuyển động; để có điểm thưởng, hãy thực hiện ước tính chuyển động chuyển đổi afin (bù trừ cho việc thu phóng và kéo dài và tương tự). Bạn cũng có thể làm các khối chồng chéo hoặc luồng quang học.


1

Lần đầu tiên vượt qua, bạn có thể thử sử dụng biểu đồ màu. Tuy nhiên, bạn thực sự cần phải thu hẹp miền vấn đề của mình. Đối sánh hình ảnh chung là một vấn đề rất khó.


1

Xin lỗi vì đã tham gia muộn trong cuộc thảo luận.

Chúng tôi thậm chí có thể sử dụng phương pháp ORB để phát hiện các điểm đặc trưng giống nhau giữa hai hình ảnh. Liên kết sau cung cấp triển khai trực tiếp ORB trong python

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

Ngay cả openCV cũng đã triển khai trực tiếp ORB. Nếu bạn biết thêm thông tin, hãy theo dõi bài báo nghiên cứu dưới đây.

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


0

Có một số câu trả lời tốt trong chủ đề khác về vấn đề này, nhưng tôi tự hỏi liệu điều gì đó liên quan đến phân tích quang phổ có hoạt động không? Tức là, chia nhỏ hình ảnh thành thông tin về pha và biên độ của nó và so sánh chúng. Điều này có thể tránh một số vấn đề với sự khác biệt về cắt xén, chuyển đổi và cường độ. Dù sao, đó chỉ là tôi suy đoán vì đây có vẻ là một vấn đề thú vị. Nếu bạn đã tìm kiếm http://scholar.google.com, tôi chắc chắn rằng bạn có thể tìm ra một số tài liệu về vấn đề này.


phân tích quang phổ là Fth Fourier Transform, không có biểu đồ màu vì bạn có thể tái tạo lại hình ảnh từ hai phần - ảo và thực. (không biết nó có hoạt động không, chỉ cho bạn biết nó không nằm trong danh mục đó).
nlucaroni 16/09/08

Đúng, ý tôi là Biến đổi Fourier.
neuroguy123, 16/09/08
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.