Làm thế nào tôi có thể định lượng sự khác biệt giữa hai hình ảnh?


179

Đây là những gì tôi muốn làm:

Tôi thường xuyên chụp ảnh với webcam. Sắp xếp giống như một điều mất thời gian. Tuy nhiên, nếu không có gì thực sự thay đổi, nghĩa là bức ảnh trông khá giống nhau, tôi không muốn lưu trữ ảnh chụp mới nhất.

Tôi tưởng tượng có một số cách định lượng sự khác biệt và tôi sẽ phải xác định một cách thực nghiệm một ngưỡng.

Tôi đang tìm kiếm sự đơn giản hơn là sự hoàn hảo. Tôi đang sử dụng python.


Câu trả lời:


269

Ý tưởng chung

Tùy chọn 1: Tải cả hai hình ảnh dưới dạng mảng ( scipy.misc.imread) và tính toán chênh lệch phần tử (pixel-by-pixel). Tính định mức chênh lệch.

Tùy chọn 2: Tải cả hai hình ảnh. Tính toán một số vectơ đặc trưng cho mỗi trong số chúng (như biểu đồ). Tính khoảng cách giữa các vectơ đặc trưng hơn là hình ảnh.

Tuy nhiên, có một số quyết định để thực hiện đầu tiên.

Câu hỏi

Bạn nên trả lời những câu hỏi này trước:

  • Là hình ảnh của cùng một hình dạng và kích thước?

    Nếu không, bạn có thể cần thay đổi kích thước hoặc cắt chúng. Thư viện PIL sẽ giúp làm điều đó trong Python.

    Nếu chúng được chụp với cùng các cài đặt và cùng một thiết bị, chúng có thể giống nhau.

  • Là hình ảnh phù hợp?

    Nếu không, bạn có thể muốn chạy tương quan chéo trước, để tìm sự liên kết tốt nhất trước. SciPy có chức năng để làm điều đó.

    Nếu máy ảnh và cảnh vẫn còn, hình ảnh có thể được căn chỉnh tốt.

  • Là tiếp xúc của hình ảnh luôn luôn giống nhau? (Độ sáng / độ tương phản có giống nhau không?)

    Nếu không, bạn có thể muốn bình thường hóa hình ảnh.

    Nhưng hãy cẩn thận, trong một số tình huống điều này có thể làm sai nhiều hơn là tốt. Ví dụ, một pixel sáng đơn trên nền tối sẽ làm cho hình ảnh được chuẩn hóa trở nên rất khác biệt.

  • Là thông tin màu sắc quan trọng?

    Nếu bạn muốn nhận thấy sự thay đổi màu sắc, bạn sẽ có một vectơ giá trị màu cho mỗi điểm, thay vì giá trị vô hướng như trong hình ảnh tỷ lệ xám. Bạn cần chú ý hơn khi viết mã như vậy.

  • Có các cạnh khác biệt trong hình ảnh? Họ có khả năng di chuyển?

    Nếu có, trước tiên bạn có thể áp dụng thuật toán phát hiện cạnh (ví dụ: tính toán độ dốc với biến đổi Sobel hoặc Prewitt, áp dụng một số ngưỡng), sau đó so sánh các cạnh trên hình ảnh đầu tiên với các cạnh trên thứ hai.

  • Có nhiễu trong ảnh không?

    Tất cả các cảm biến gây ô nhiễm hình ảnh với một số lượng nhiễu. Cảm biến giá rẻ có nhiều tiếng ồn hơn. Bạn có thể muốn áp dụng một số giảm nhiễu trước khi so sánh hình ảnh. Blur là cách tiếp cận đơn giản nhất (nhưng không phải là tốt nhất) ở đây.

  • Những loại thay đổi nào bạn muốn thông báo?

    Điều này có thể ảnh hưởng đến việc lựa chọn định mức để sử dụng cho sự khác biệt giữa các hình ảnh.

    Xem xét sử dụng định mức Manhattan (tổng của các giá trị tuyệt đối) hoặc định mức bằng không (số phần tử không bằng 0) để đo mức độ hình ảnh đã thay đổi. Cái trước sẽ cho bạn biết hình ảnh bị tắt bao nhiêu, cái sau sẽ chỉ cho biết có bao nhiêu pixel khác nhau.

Thí dụ

Tôi cho rằng hình ảnh của bạn được căn chỉnh tốt, cùng kích thước và hình dạng, có thể có độ phơi sáng khác nhau. Để đơn giản, tôi chuyển đổi chúng thành thang độ xám ngay cả khi chúng là hình ảnh màu (RGB).

Bạn sẽ cần những hàng nhập khẩu này:

import sys

from scipy.misc import imread
from scipy.linalg import norm
from scipy import sum, average

Chức năng chính, đọc hai hình ảnh, chuyển đổi sang thang độ xám, so sánh và in kết quả:

def main():
    file1, file2 = sys.argv[1:1+2]
    # read images as 2D arrays (convert to grayscale for simplicity)
    img1 = to_grayscale(imread(file1).astype(float))
    img2 = to_grayscale(imread(file2).astype(float))
    # compare
    n_m, n_0 = compare_images(img1, img2)
    print "Manhattan norm:", n_m, "/ per pixel:", n_m/img1.size
    print "Zero norm:", n_0, "/ per pixel:", n_0*1.0/img1.size

Cách so sánh. img1img2là mảng 2D SciPy ở đây:

def compare_images(img1, img2):
    # normalize to compensate for exposure difference, this may be unnecessary
    # consider disabling it
    img1 = normalize(img1)
    img2 = normalize(img2)
    # calculate the difference and its norms
    diff = img1 - img2  # elementwise for scipy arrays
    m_norm = sum(abs(diff))  # Manhattan norm
    z_norm = norm(diff.ravel(), 0)  # Zero norm
    return (m_norm, z_norm)

Nếu tệp là hình ảnh màu, imreadtrả về mảng 3D, các kênh RGB trung bình (trục mảng cuối cùng) để thu được cường độ. Không cần phải làm điều đó cho hình ảnh thang độ xám (ví dụ .pgm):

def to_grayscale(arr):
    "If arr is a color image (3D array), convert it to grayscale (2D array)."
    if len(arr.shape) == 3:
        return average(arr, -1)  # average over the last axis (color channels)
    else:
        return arr

Bình thường hóa là chuyện nhỏ, bạn có thể chọn bình thường hóa thành [0,1] thay vì [0,255]. arrlà một mảng SciPy ở đây, vì vậy tất cả các hoạt động đều là phần tử khôn ngoan:

def normalize(arr):
    rng = arr.max()-arr.min()
    amin = arr.min()
    return (arr-amin)*255/rng

Chạy mainchức năng:

if __name__ == "__main__":
    main()

Bây giờ bạn có thể đặt tất cả điều này trong một tập lệnh và chạy với hai hình ảnh. Nếu chúng ta so sánh hình ảnh với chính nó, không có sự khác biệt:

$ python compare.py one.jpg one.jpg
Manhattan norm: 0.0 / per pixel: 0.0
Zero norm: 0 / per pixel: 0.0

Nếu chúng ta làm mờ hình ảnh và so sánh với bản gốc, có một số khác biệt:

$ python compare.py one.jpg one-blurred.jpg 
Manhattan norm: 92605183.67 / per pixel: 13.4210411116
Zero norm: 6900000 / per pixel: 1.0

Toàn bộ tập lệnh so sánh PS .

Cập nhật: kỹ thuật liên quan

Vì câu hỏi là về một chuỗi video, trong đó các khung hình có thể gần giống nhau và bạn tìm kiếm điều gì đó bất thường, tôi muốn đề cập đến một số phương pháp thay thế có thể có liên quan:

  • trừ nền và phân đoạn (để phát hiện các đối tượng nền trước)
  • dòng quang thưa (để phát hiện chuyển động)
  • so sánh biểu đồ hoặc một số thống kê khác thay vì hình ảnh

Tôi thực sự khuyên bạn nên xem cuốn sách Học tập OpenCV của Chương, Chương 9 (Phần hình ảnh và phân đoạn) và 10 (Theo dõi và chuyển động). Cái trước dạy sử dụng phương pháp trừ nền, cái sau cung cấp một số thông tin về phương pháp dòng quang. Tất cả các phương thức được thực hiện trong thư viện OpenCV. Nếu bạn sử dụng Python, tôi khuyên bạn nên sử dụng OpenCV ≥ 2.3 và cv2mô-đun Python của nó .

Phiên bản đơn giản nhất của phép trừ nền:

  • tìm hiểu giá trị trung bình và độ lệch chuẩn cho mỗi pixel của nền
  • so sánh các giá trị pixel hiện tại với phạm vi (- 2σ, μ + 2σ) hoặc (- σ, μ +)

Các phiên bản nâng cao hơn thực hiện tính đến chuỗi thời gian cho mỗi pixel và xử lý các cảnh không tĩnh (như di chuyển cây hoặc cỏ).

Ý tưởng của dòng quang là lấy hai hoặc nhiều khung và gán vectơ vận tốc cho mọi pixel (luồng quang dày đặc) hoặc cho một số trong số chúng (luồng quang thưa). Để ước tính lưu lượng quang thưa thớt, bạn có thể sử dụng phương pháp Lucas-Kanade (nó cũng được triển khai trong OpenCV). Rõ ràng, nếu có nhiều luồng (trung bình cao trên các giá trị tối đa của trường vận tốc), thì một cái gì đó đang di chuyển trong khung và các hình ảnh tiếp theo sẽ khác hơn.

So sánh biểu đồ có thể giúp phát hiện những thay đổi đột ngột giữa các khung liên tiếp. Cách tiếp cận này đã được sử dụng trong Courbon et al, 2010 :

Độ tương tự của các khung liên tiếp. Khoảng cách giữa hai khung liên tiếp được đo. Nếu nó quá cao, có nghĩa là khung hình thứ hai bị hỏng và do đó hình ảnh bị loại bỏ. Các Kullback-Leibler khoảng cách , hoặc entropy lẫn nhau, trên biểu đồ của hai khung:

$$ d (p, q) = \ sum_i p (i) \ log (p (i) / q (i)) $$

Trong đó pq là biểu đồ của các khung được sử dụng. Ngưỡng được cố định trên 0,2.


Tôi nhận được một RuntimeWarning: invalid value encountered in double_scalarsdòng 44 ( return (arr-amin)*255/rng) và một ValueError: array must not contain infs or NaNsdòng 30 ( z_norm = norm(diff.ravel(), 0))
BioGeek

@BioGeek đó là nếu rngbằng không. Chỉ cần thêm một kiểm tra và thiết lậprng = 1
haisi

76

Một giải pháp đơn giản:

Mã hóa hình ảnh dưới dạng jpeg và tìm kiếm sự thay đổi đáng kể về kích thước tệp .

Tôi đã triển khai một cái gì đó tương tự với hình thu nhỏ của video và đã có rất nhiều thành công và khả năng mở rộng.


3
Đây là một giải pháp rất dễ dàng, đơn giản và tốt hơn nhiều so với bất kỳ so sánh pixel-khôn ngoan nào. Nếu có một chút nhiễu trong hình ảnh trên webcam của bạn hoặc nếu hình ảnh bị dịch chuyển bởi một pixel, thì so sánh trực tiếp sẽ thu được tất cả những thay đổi vô nghĩa này. Một cách tiếp cận mạnh mẽ hơn sẽ là tính toán biến đổi cosine rời rạc và sau đó so sánh các hình ảnh trong miền tần số. Sử dụng nén JPEG như thế này sẽ mang lại cho bạn hầu hết các lợi ích mà không cần đi sâu vào lý thuyết Fourier.
AndrewF

Thích nó Mặc dù các giải pháp khác cũng hoạt động, nhưng điều này có một lợi thế lớn cho một tình huống phổ biến: nếu bạn không muốn lưu hình ảnh "cơ sở" thì sao? chỉ lưu tập tin kích thước dưới dạng băm và sau đó so sánh chỉ số với cơ số. Trong trường hợp của tôi, tôi có 4 hình ảnh, một trong số đó là simillar và 3 hình khác thì hoàn toàn khác nhau. Chỉ cần chia tỷ lệ cho cùng kích thước, để jpg và trừ. Thực sự tốt đẹp.
Diego Andrés Díaz Espinoza

60

Bạn có thể so sánh hai hình ảnh bằng cách sử dụng các chức năng từ PIL .

import Image
import ImageChops

im1 = Image.open("splash.png")
im2 = Image.open("splash2.png")

diff = ImageChops.difference(im2, im1)

Đối tượng diff là một hình ảnh trong đó mỗi pixel là kết quả của phép trừ các giá trị màu của pixel đó trong hình ảnh thứ hai từ hình ảnh đầu tiên. Sử dụng hình ảnh khác bạn có thể làm một số điều. Đơn giản nhất là diff.getbbox()chức năng. Nó sẽ cho bạn biết hình chữ nhật tối thiểu chứa tất cả các thay đổi giữa hai hình ảnh của bạn.

Bạn có thể có thể thực hiện xấp xỉ các công cụ khác được đề cập ở đây bằng cách sử dụng các hàm từ PIL.


2
Tôi muốn lưu hình ảnh khác biệt. có nghĩa là đối tượng khác biệt giữ sự khác biệt của hình ảnh. Tôi có lưu nó không?
Sagar

2
@Anthony bạn có thể gọi save () trên đối tượng diff chỉ định tên hình ảnh. như thế này: diff.save ("diff.png") nó sẽ lưu hình ảnh khác biệt cho bạn.
Sagar

20

Hai phương pháp phổ biến và tương đối đơn giản là: (a) khoảng cách Euclide đã đề xuất hoặc (b) tương quan chéo bình thường hóa. Tương quan chéo bình thường hóa có xu hướng mạnh mẽ hơn đáng kể đối với những thay đổi ánh sáng so với tương quan chéo đơn giản. Wikipedia đưa ra một công thức cho mối tương quan chéo được chuẩn hóa . Các phương thức phức tạp hơn cũng tồn tại, nhưng chúng đòi hỏi nhiều công việc hơn một chút.

Sử dụng cú pháp giống như numpy,

dist_euclidean = sqrt (tổng ((i1 - i2) ^ 2)) / i1.size

dist_manhattan = sum (abs (i1 - i2)) / i1.size

dist_ncc = sum ((i1 - trung bình (i1)) * (i2 - trung bình (i2))) / (
  (i1.size - 1) * stdev (i1) * stdev (i2))

giả định rằng i1i2là mảng ảnh thang độ xám 2D.


3
Các chức năng tương quan chéo hình ảnh được tích hợp vào SciPy ( docs.scipy.org/doc/scipy/reference/generated/ trộm ) và một phiên bản nhanh sử dụng FFT có sẵn trong stsci python ( stsci.edu/resource/software_hardware/py stsci_python )
endolith

14

Một điều tầm thường để thử:

Lấy mẫu lại cả hai hình ảnh thành các hình thu nhỏ (ví dụ 64 x 64) và so sánh các hình thu nhỏ từng pixel với một ngưỡng nhất định. Nếu các hình ảnh gốc gần giống nhau, các hình thu nhỏ được ghép lại sẽ rất giống nhau hoặc thậm chí giống hệt nhau. Phương pháp này xử lý nhiễu có thể xảy ra đặc biệt là trong các cảnh thiếu sáng. Nó thậm chí có thể tốt hơn nếu bạn đi thang độ xám.


nhưng làm thế nào bạn sẽ so sánh các pixel?
tàu sân bay

Khi bạn có hình thu nhỏ, bạn chỉ cần so sánh từng pixel một. Bạn sẽ tính "khoảng cách" của các giá trị RGB, nếu bạn đang làm việc với màu hoặc chỉ là sự khác biệt giữa các tông màu xám nếu bạn ở thang độ xám.
Ates Goral

1
"So sánh từng pixel một". Điều đó nghĩa là gì? Thử nghiệm có nên thất bại nếu MỘT trong số 64 ^ 2 pixel cho mỗi pixel không thành công không?
Federico A. Ramponi

Ý tôi là "so sánh các pixel của từng pixel với một ngưỡng nhất định" là đưa ra một thuật toán mờ để so sánh các pixel. Nếu chênh lệch được tính toán (phụ thuộc vào thuật toán mờ của bạn) vượt quá một ngưỡng nhất định, hình ảnh sẽ "không giống nhau".
Ates Goral

1
Ví dụ rất đơn giản, không có "thuật toán mờ": vòng lặp song song qua mọi pixel (so sánh pixel # n của hình ảnh # 1 với pixel # n của hình ảnh # 2) và thêm sự khác biệt về giá trị cho một biến
mk12

7

Tôi đang giải quyết cụ thể câu hỏi làm thế nào để tính toán nếu chúng "đủ khác nhau". Tôi giả sử bạn có thể tìm ra cách trừ từng pixel một.

Đầu tiên, tôi sẽ chụp một loạt ảnh không có gì thay đổi và tìm ra mức tối đa mà bất kỳ pixel nào thay đổi chỉ vì các biến thể trong chụp, nhiễu trong hệ thống hình ảnh, tạo tác nén JPEG và thay đổi từng khoảnh khắc trong ánh sáng . Có lẽ bạn sẽ thấy rằng sự khác biệt 1 hoặc 2 bit sẽ được mong đợi ngay cả khi không có gì di chuyển.

Sau đó, đối với bài kiểm tra "thực", bạn muốn có một tiêu chí như thế này:

  • tương tự nếu tối đa P pixel khác nhau không quá E.

Vì vậy, có lẽ, nếu E = 0,02, P = 1000, điều đó có nghĩa là (sẽ) có nghĩa là "khác biệt" nếu bất kỳ pixel đơn lẻ nào thay đổi hơn ~ 5 đơn vị (giả sử hình ảnh 8 bit) hoặc hơn 1000 pixel có bất kỳ lỗi nào cả.

Đây chủ yếu là một kỹ thuật "xử lý" tốt để nhanh chóng xác định hình ảnh đủ gần để không cần kiểm tra thêm. Các hình ảnh "thất bại" sau đó có thể nhiều hơn đối với một kỹ thuật phức tạp / đắt tiền hơn sẽ không có kết quả dương tính nếu máy ảnh bị rung, chẳng hạn, hoặc mạnh mẽ hơn đối với các thay đổi ánh sáng.

Tôi điều hành một dự án nguồn mở, OpenImageIO , có chứa một tiện ích gọi là "idiff" so sánh sự khác biệt với các ngưỡng như thế này (thực sự thậm chí còn phức tạp hơn). Ngay cả khi bạn không muốn sử dụng phần mềm này, bạn có thể muốn xem nguồn để xem chúng tôi đã làm như thế nào. Nó được sử dụng khá nhiều về mặt thương mại và kỹ thuật ngưỡng này đã được phát triển để chúng tôi có thể có một bộ thử nghiệm để kết xuất và xử lý hình ảnh, với "hình ảnh tham chiếu" có thể có những khác biệt nhỏ so với nền tảng hoặc khi chúng tôi thực hiện một số điều chỉnh nhỏ thuật toán tha, vì vậy chúng tôi muốn có một hoạt động "khớp trong dung sai".


6

Tôi gặp vấn đề tương tự tại nơi làm việc, tôi đang viết lại điểm cuối biến đổi hình ảnh của chúng tôi và tôi muốn kiểm tra xem phiên bản mới có tạo ra cùng hoặc gần giống với phiên bản cũ không. Vì vậy, tôi đã viết này:

https://github.com/nicolashahn/diffimg

Hoạt động trên các hình ảnh có cùng kích thước và ở mức độ mỗi pixel, đo lường sự khác biệt về giá trị ở mỗi kênh: R, G, B (, A), lấy chênh lệch trung bình của các kênh đó và sau đó tính trung bình chênh lệch tất cả các pixel và trả về một tỷ lệ.

Ví dụ: với hình ảnh 10 x 10 pixel màu trắng và cùng hình ảnh nhưng một pixel đã đổi thành màu đỏ, sự khác biệt ở pixel đó là 1/3 hoặc 0,33 ... (RGB 0,0,0 so với 255,0,0 ) và tại tất cả các pixel khác là 0. Với tổng số 100 pixel, chênh lệch 0,33 ... / 100 = a ~ 0,33% trong hình ảnh.

Tôi tin rằng điều này sẽ hoạt động hoàn hảo cho dự án của OP (Tôi nhận ra đây là một bài viết rất cũ, nhưng đăng cho StackOverflowers trong tương lai, những người cũng muốn so sánh hình ảnh trong python).


5

Hầu hết các câu trả lời sẽ không giải quyết với mức độ chiếu sáng.

Trước tiên tôi sẽ bình thường hóa hình ảnh đến một mức độ ánh sáng tiêu chuẩn trước khi thực hiện so sánh.


Nếu bạn đang chụp ảnh định kỳ và các cặp liền kề khác nhau, có lẽ bạn có thể đủ khả năng để giữ ảnh đầu tiên sau khi ai đó bật đèn.
walkytalky

5

Một cách hay, đơn giản khác để đo sự tương đồng giữa hai hình ảnh:

import sys
from skimage.measure import compare_ssim
from skimage.transform import resize
from scipy.ndimage import imread

# get two images - resize both to 1024 x 1024
img_a = resize(imread(sys.argv[1]), (2**10, 2**10))
img_b = resize(imread(sys.argv[2]), (2**10, 2**10))

# score: {-1:1} measure of the structural similarity between the images
score, diff = compare_ssim(img_a, img_b, full=True)
print(score)

Nếu những người khác quan tâm đến một cách mạnh mẽ hơn để so sánh độ tương tự của hình ảnh, tôi kết hợp một hướng dẫnứng dụng web để đo lường và trực quan hóa các hình ảnh tương tự bằng cách sử dụng Tensorflow.


3
Vâng, skimagethực sự tốt đẹp để sử dụng cho ứng dụng này. Tôi sử dụng from skimage.measure import compare_ssim, compare_mserất nhiều. tài liệu skimage.measure .
ximiki

3

Bạn đã thấy Thuật toán tìm câu hỏi hình ảnh tương tự chưa? Kiểm tra nó để xem gợi ý.

Tôi sẽ đề xuất một phép biến đổi sóng con của các khung của bạn (Tôi đã viết một phần mở rộng C cho việc sử dụng chuyển đổi Haar); sau đó, so sánh các chỉ số của các yếu tố sóng con (tỷ lệ) lớn nhất giữa hai hình ảnh, bạn sẽ có được một xấp xỉ tương tự về số.


2

Tôi xin lỗi nếu điều này quá muộn để trả lời, nhưng vì tôi đã làm điều gì đó tương tự, tôi nghĩ rằng tôi có thể đóng góp bằng cách nào đó.

Có lẽ với OpenCV bạn có thể sử dụng khớp mẫu. Giả sử bạn đang sử dụng webcam như bạn đã nói:

  1. Đơn giản hóa các hình ảnh (có thể ngưỡng?)
  2. Áp dụng khớp mẫu và kiểm tra max_val với minMaxLoc

Mẹo: max_val (hoặc min_val tùy theo phương pháp được sử dụng) sẽ cung cấp cho bạn số, số lớn. Để có sự khác biệt về tỷ lệ phần trăm, hãy sử dụng so khớp mẫu với cùng một hình ảnh - kết quả sẽ là 100% của bạn.

Mã giả để làm gương:

previous_screenshot = ...
current_screenshot = ...

# simplify both images somehow

# get the 100% corresponding value
res = matchTemplate(previous_screenshot, previous_screenshot, TM_CCOEFF)
_, hundred_p_val, _, _ = minMaxLoc(res)

# hundred_p_val is now the 100%

res = matchTemplate(previous_screenshot, current_screenshot, TM_CCOEFF)
_, max_val, _, _ = minMaxLoc(res)

difference_percentage = max_val / hundred_p_val

# the tolerance is now up to you

Hy vọng nó giúp.


1

Khoảng cách động đất có thể chính xác là những gì bạn cần. Nó có thể là của abit nặng để thực hiện trong thời gian thực mặc dù.


Tôi thực sự không cảm thấy câu trả lời này rất hay: "Tôi đang tìm kiếm sự đơn giản hơn là sự hoàn hảo. Tôi đang sử dụng python."
PilouPili

Tôi nghĩ khi chủ đề câu hỏi này nhận được rất nhiều lưu lượng truy cập và tiêu đề thu hút hầu hết người xem là về cách định lượng sự khác biệt giữa hai hình ảnh, nó có giá trị ở đây.
Danoram

1

Điều gì về tính toán Khoảng cách Manhattan của hai hình ảnh. Điều đó mang lại cho bạn giá trị n * n. Sau đó, bạn có thể làm một cái gì đó như trung bình hàng để giảm xuống n giá trị và hàm trên đó để có được một giá trị duy nhất.


1

Tôi đã gặp rất nhiều may mắn với hình ảnh jpg được chụp bằng cùng một máy ảnh trên chân máy bằng cách (1) đơn giản hóa rất nhiều (như đi từ rộng 3000 pixel đến rộng 100 pixel hoặc thậm chí ít hơn) (2) làm phẳng từng mảng jpg thành một vectơ (3) hình ảnh tuần tự tương quan theo cặp với thuật toán tương quan đơn giản để có được hệ số tương quan bình phương (4) hệ số tương quan bình phương để có được bình phương r (nghĩa là phần biến thiên trong một hình ảnh được giải thích bởi sự thay đổi trong tiếp theo) (5) nói chung trong ứng dụng của tôi nếu r-vuông <0,9, tôi nói hai hình ảnh khác nhau và có gì đó xảy ra ở giữa.

Điều này là mạnh mẽ và nhanh chóng trong việc thực hiện của tôi (Mathematica 7)

Thật đáng để chơi xung quanh với một phần của hình ảnh mà bạn quan tâm và tập trung vào đó bằng cách cắt tất cả các hình ảnh đến khu vực nhỏ đó, nếu không thì sẽ bị bỏ qua một thay đổi quan trọng.

Tôi không biết cách sử dụng Python, nhưng chắc chắn nó cũng có tương quan, phải không?


1

bạn có thể tính toán biểu đồ của cả hai hình ảnh và sau đó tính Hệ số Bhattacharyya , đây là thuật toán rất nhanh và tôi đã sử dụng nó để phát hiện các thay đổi bắn trong video cricket (trong C sử dụng openCV)


Bạn có thể tự tính hệ số trên ảnh không?
endolith

Bạn sẽ phải tính toán biểu đồ cho hình ảnh (với kích thước bin của biểu đồ theo yêu cầu).
vishalv2050

1

Kiểm tra cách Haar Wavelets được thực hiện bởi isk-daemon . Bạn có thể sử dụng mã imgdb C ++ để tính toán sự khác biệt giữa các hình ảnh đang hoạt động:

isk-daemon là một máy chủ cơ sở dữ liệu nguồn mở có khả năng thêm tìm kiếm hình ảnh dựa trên nội dung (trực quan) vào bất kỳ trang web hoặc phần mềm liên quan đến hình ảnh nào.

Công nghệ này cho phép người dùng của bất kỳ trang web hoặc phần mềm nào liên quan đến hình ảnh phác thảo trên một widget mà hình ảnh họ muốn tìm và yêu cầu trang web trả lời cho họ những hình ảnh giống nhau nhất hoặc chỉ cần yêu cầu thêm hình ảnh tương tự ở mỗi trang chi tiết hình ảnh.


1

Tôi có cùng một vấn đề và đã viết một mô-đun python đơn giản để so sánh hai hình ảnh có cùng kích thước bằng ImageChops của gối để tạo ra một hình ảnh khác biệt đen / trắng và tổng hợp các giá trị biểu đồ.

Bạn có thể nhận được điểm này trực tiếp hoặc giá trị phần trăm so với khác biệt toàn màu đen so với trắng.

Nó cũng chứa một hàm is_equal đơn giản, với khả năng cung cấp ngưỡng mờ dưới (và bao gồm) hình ảnh vượt qua như nhau.

Cách tiếp cận không phức tạp lắm, nhưng có lẽ được sử dụng cho những người khác đang đấu tranh với cùng một vấn đề.

https://pypi.python.org/pypi/imgcompare/


1

Một cách tiếp cận có nguyên tắc hơn là sử dụng một mô tả toàn cầu để so sánh các hình ảnh, chẳng hạn như GIST hoặc TRUNG TÂM. Hàm băm, như được mô tả ở đây , cũng cung cấp một giải pháp tương tự.


1
import os
from PIL import Image
from PIL import ImageFile
import imagehash
  
#just use to the size diferent picture
def compare_image(img_file1, img_file2):
    if img_file1 == img_file2:
        return True
    fp1 = open(img_file1, 'rb')
    fp2 = open(img_file2, 'rb')

    img1 = Image.open(fp1)
    img2 = Image.open(fp2)

    ImageFile.LOAD_TRUNCATED_IMAGES = True
    b = img1 == img2

    fp1.close()
    fp2.close()

    return b





#through picturu hash to compare
def get_hash_dict(dir):
    hash_dict = {}
    image_quantity = 0
    for _, _, files in os.walk(dir):
        for i, fileName in enumerate(files):
            with open(dir + fileName, 'rb') as fp:
                hash_dict[dir + fileName] = imagehash.average_hash(Image.open(fp))
                image_quantity += 1

    return hash_dict, image_quantity

def compare_image_with_hash(image_file_name_1, image_file_name_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.
    recommend to use
    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_1 = None
    hash_2 = None
    with open(image_file_name_1, 'rb') as fp:
        hash_1 = imagehash.average_hash(Image.open(fp))
    with open(image_file_name_2, 'rb') as fp:
        hash_2 = imagehash.average_hash(Image.open(fp))
    dif = hash_1 - hash_2
    if dif < 0:
        dif = -dif
    if dif <= max_dif:
        return True
    else:
        return False


def compare_image_dir_with_hash(dir_1, dir_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.

    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_dict_1, image_quantity_1 = get_hash_dict(dir_1)
    hash_dict_2, image_quantity_2 = get_hash_dict(dir_2)

    if image_quantity_1 > image_quantity_2:
        tmp = image_quantity_1
        image_quantity_1 = image_quantity_2
        image_quantity_2 = tmp

        tmp = hash_dict_1
        hash_dict_1 = hash_dict_2
        hash_dict_2 = tmp

    result_dict = {}

    for k in hash_dict_1.keys():
        result_dict[k] = None

    for dif_i in range(0, max_dif + 1):
        have_none = False

        for k_1 in result_dict.keys():
            if result_dict.get(k_1) is None:
                have_none = True

        if not have_none:
            return result_dict

        for k_1, v_1 in hash_dict_1.items():
            for k_2, v_2 in hash_dict_2.items():
                sub = (v_1 - v_2)
                if sub < 0:
                    sub = -sub
                if sub == dif_i and result_dict.get(k_1) is None:
                    result_dict[k_1] = k_2
                    break
    return result_dict


def main():
    print(compare_image('image1\\815.jpg', 'image2\\5.jpg'))
    print(compare_image_with_hash('image1\\815.jpg', 'image2\\5.jpg', 7))
    r = compare_image_dir_with_hash('image1\\', 'image2\\', 10)
    for k in r.keys():
        print(k, r.get(k))


if __name__ == '__main__':
    main()
  • đầu ra:

    Sai
    Đúng
    image2 \ 5.jpg image1 \ 815.jpg
    image2 \ 6.jpg image1 \ 819.jpg
    image2 \ 7.jpg image1 \ 900.jpg
    image2 \ 8.jpg image1 \ 998.jpg
    image2 \ 9.jpg image1 \ 1012 .jpg

  • hình ảnh ví dụ:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg


0

Tôi nghĩ rằng bạn chỉ có thể tính khoảng cách euclide (tức là sqrt (tổng bình phương của sự khác biệt, pixel theo pixel)) giữa độ chói của hai hình ảnh và xem xét chúng bằng nhau nếu điều này nằm dưới ngưỡng thực nghiệm nào đó. Và bạn nên làm nó tốt hơn một hàm C.


0

Có nhiều số liệu ngoài kia để đánh giá xem hai hình ảnh trông như thế nào / chúng trông như thế nào.

Tôi sẽ không đi sâu vào bất kỳ mã nào ở đây, vì tôi nghĩ nó nên là một vấn đề khoa học, ngoài vấn đề kỹ thuật.

Nói chung, câu hỏi liên quan đến nhận thức của con người về hình ảnh, vì vậy mỗi thuật toán có sự hỗ trợ về đặc điểm hệ thống thị giác của con người.

Phương pháp cổ điển là:

Công cụ dự đoán sự khác biệt có thể nhìn thấy: một thuật toán để đánh giá độ trung thực của hình ảnh ( https: //www.spiedigitall Library.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-alerskym-for-the- đánh giá / 10.1117 / 12.135952.short? SSO = 1 )

Đánh giá chất lượng hình ảnh: Từ khả năng hiển thị lỗi đến độ tương tự cấu trúc ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )

FSIM: Chỉ số tương tự tính năng để đánh giá chất lượng hình ảnh ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )

Trong số đó, SSIM (Đánh giá chất lượng hình ảnh: Từ khả năng hiển thị lỗi đến độ tương tự cấu trúc) là dễ tính toán nhất và chi phí cũng nhỏ, như đã báo cáo trong một bài báo khác "Đánh giá chất lượng hình ảnh dựa trên độ tương tự độ dốc" ( https: //www.semanticscholar .org / paper / Image-Quality-Assessment-Dựa-Gradient-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).

Có nhiều cách tiếp cận khác. Hãy xem Google Scholar và tìm kiếm một cái gì đó như "sự khác biệt về thị giác", "đánh giá chất lượng hình ảnh", v.v., nếu bạn quan tâm / thực sự quan tâm đến nghệ thuật.


0

Có một giải pháp đơn giản và nhanh chóng bằng cách sử dụng numpy bằng cách tính sai số bình phương trung bình:

before = np.array(get_picture())
while True:
    now = np.array(get_picture())
    MSE = np.mean((now - before)**2)

    if  MSE > threshold:
        break

    before = now
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.