Raster diff: làm thế nào để kiểm tra xem hình ảnh có giá trị giống hệt nhau không?


10

Có phương tiện nào để kiểm tra xem có bất kỳ 2 lớp raster nào có nội dung giống hệt nhau không?

Chúng tôi có một vấn đề về dung lượng lưu trữ được chia sẻ của công ty: hiện tại nó lớn đến mức phải mất hơn 3 ngày để tiến hành sao lưu toàn bộ. Điều tra sơ bộ cho thấy một trong những thủ phạm tiêu tốn không gian lớn nhất là bật / tắt các trình quét thực sự nên được lưu trữ dưới dạng các lớp 1 bit với nén CCITT.

một raster hiện tại / không hiện diện điển hình

Hình ảnh mẫu này hiện là 2 bit (vì vậy 3 giá trị có thể) và được lưu dưới dạng tiff nén LZW, 11 MB trong hệ thống tệp. Sau khi chuyển đổi thành 1 bit (vì vậy 2 giá trị có thể) và áp dụng nén CCITT Nhóm 4, chúng tôi giảm xuống còn 1,3 MB, gần như là một mức tiết kiệm đầy đủ.

(Đây thực sự là một công dân cư xử rất tốt, có những người khác được lưu trữ dưới dạng float 32bit!)

Đây là tin tuyệt vời! Tuy nhiên, có gần 7.000 hình ảnh để áp dụng điều này quá. Sẽ thật đơn giản để viết một kịch bản để nén chúng:

for old_img in [list of images]:
    convert_to_1bit_and_compress(old_img)
    remove(old_img)
    replace_with_new(old_img, new_img)

... nhưng nó thiếu một bài kiểm tra quan trọng: phiên bản mới được nén có giống hệt nội dung không?

  if raster_diff(old_img, new_img) == "Identical":
      remove(old_img)
      rename(new_img, old_img)

Có một công cụ hoặc phương pháp nào có thể tự động (dis) chứng minh nội dung của Image-A giống với nội dung của Image-B không?

Tôi có quyền truy cập ArcGIS 10.2 và QGIS, nhưng tôi cũng có thể mở hầu hết mọi thứ khác ngoài việc có thể kiểm tra tất cả các hình ảnh này bằng tay để đảm bảo tính chính xác trước khi ghi đè. Nó sẽ là khủng khiếp để convert nhầm lẫn và ghi đè lên một hình ảnh mà thực sự đã có hơn on / off các giá trị trong đó. Hầu hết chi phí hàng ngàn đô la để thu thập và tạo ra.

một kết quả rất tệ

cập nhật: Người phạm tội lớn nhất là các phao 32 bit có phạm vi lên tới 100.000px cho một bên, vì vậy ~ 30 GB không nén.


1
Một cách để thực hiện raster_diff(old_img, new_img) == "Identical"sẽ là kiểm tra xem giá trị cực đại của giá trị tuyệt đối của chênh lệch bằng 0, trong đó vùng được lấy trên toàn bộ phạm vi lưới. Đây có phải là loại giải pháp bạn đang tìm kiếm? (Nếu vậy, nó cũng cần được tinh chỉnh để kiểm tra xem có bất kỳ giá trị NoData nào cũng phù hợp không.)
whuber

1
@whuber cảm ơn vì đã đảm bảo NoDataxử lý thích hợp ở lại trong cuộc trò chuyện.
matt wilkie

nếu bạn có thể kiểm tra điều đó len(numpy.unique(yourraster)) == 2, thì bạn biết rằng nó có 2 giá trị duy nhất và bạn có thể thực hiện việc này một cách an toàn.
RemcoGerlich

@Remco Thuật toán cơ bản numpy.uniquesẽ đắt hơn về mặt tính toán (cả về thời gian và không gian) so với hầu hết các cách khác để kiểm tra sự khác biệt là một hằng số. Khi phải đối mặt với sự khác biệt giữa hai trình quét điểm nổi rất lớn thể hiện nhiều điểm khác biệt (chẳng hạn như so sánh bản gốc với phiên bản nén bị mất), nó có thể sẽ bị sa lầy mãi mãi hoặc thất bại hoàn toàn.
whuber

1
@Aaron, tôi đã rút khỏi dự án để làm những việc khác. Một phần trong số đó là do thời gian phát triển tiếp tục tăng: quá nhiều trường hợp xử lý tự động, do đó quyết định được đưa ra để ném lại vấn đề cho những người tạo ra hình ảnh thay vì sửa chúng. (ví dụ: "Hạn ngạch đĩa của bạn là X. Bạn tìm hiểu cách làm việc bên trong nó.") Tuy nhiên gdalcompare.pyđã cho thấy lời hứa tuyệt vời ( xem câu trả lời )
matt wilkie

Câu trả lời:


8

Hãy thử chuyển đổi các raster của bạn thành các mảng numpy và sau đó kiểm tra xem liệu chúng có cùng hình dạng và các phần tử với Array_equal không . Nếu chúng giống nhau, kết quả sẽ là True:

ArcGIS:

import arcpy, numpy

raster1 = r'C:\path\to\raster.tif'
raster2 = r'C:\path\to\raster.tif'

r1 = arcpy.RasterToNumPyArray(raster1)
r2 = arcpy.RasterToNumPyArray(raster2)

d = numpy.array_equal(r1,r2)

if d == False:
    print "They differ"

else:
    print "They are the same"

Giáo dục:

import numpy
from osgeo import gdal        

raster1 = r'C:\path\to\raster.tif'
raster2 = r'C:\path\to\raster.tif'

ds1 = gdal.Open(raster1)
ds2 = gdal.Open(raster2)

r1 = numpy.array(ds1.ReadAsArray())
r2 = numpy.array(ds2.ReadAsArray())

d = numpy.array_equal(r1,r2)

if d == False:
    print "They differ"

else:
    print "They are the same"

Điều đó có vẻ ngọt ngào và đơn giản. Tôi tò mò về hai chi tiết (trong đó, dù là kỹ thuật, có thể rất quan trọng). Đầu tiên, giải pháp này có xử lý chính xác các giá trị NoData không? Thứ hai, làm thế nào để so sánh tốc độ của nó với việc sử dụng các hàm dựng sẵn dành cho so sánh lưới, chẳng hạn như tóm tắt khu vực?
whuber

1
Điểm tốt @whuber. Tôi đã thực hiện một điều chỉnh nhanh chóng cho kịch bản cần tính đến hình dạng và các yếu tố. Tôi sẽ kiểm tra các điểm bạn đưa lên và báo cáo kết quả.
Aaron

1
@whuber Về việc NoDataxử lý, RasterToNumPyArraymặc định gán giá trị NoData của raster đầu vào cho mảng. Người dùng có thể chỉ định một giá trị khác, mặc dù điều đó sẽ không áp dụng trong trường hợp của Matt. Về tốc độ, phải mất 4,5 giây để kịch bản so sánh 2 trình quét 4 bit với 6210 cột và 7650 hàng (phạm vi DOQQ). Tôi đã không so sánh phương pháp với bất kỳ tóm tắt khu vực.
Aaron

1
Tôi đã gấp trong tương đương gdal, được điều chỉnh từ gis.stackexchange.com/questions/32995/iêu
matt wilkie

4

Bạn có thể dùng thử với tập lệnh gdalcompare.py http://www.gdal.org/gdalcompare.html . Mã nguồn của tập lệnh có tại http://trac.osgeo.org/gdal/browser/trunk/gdal/swig/python/scripts/gdalcompare.py và vì đây là tập lệnh python nên dễ dàng loại bỏ các tập lệnh không cần thiết kiểm tra và thêm những cái mới cho phù hợp với nhu cầu hiện tại của bạn. Kịch bản dường như thực hiện so sánh pixel bằng cách đọc dữ liệu hình ảnh từ hai dải hình ảnh theo băng tần và đó có lẽ là một phương pháp khá nhanh và có thể sử dụng lại.


1
hấp dẫn, tôi yêu gdal, không biết về kịch bản này. Tài liệu để diễn giải các kết quả rất thưa thớt đến không tồn tại ;-). Trong thử nghiệm ban đầu của tôi, nó báo cáo sự khác biệt trong giải thích màu sắc và bảng màu, có nghĩa là nó có thể quá cụ thể cho nhu cầu hiện tại của tôi. Tôi vẫn đang khám phá nó mặc dù. (lưu ý: câu trả lời này quá ngắn để phù hợp ở đây, chỉ liên kết các câu trả lời không được khuyến khích, vui lòng xem xét đưa ra câu trả lời).
matt wilkie

1

Tôi sẽ đề nghị bạn xây dựng bảng thuộc tính raster của bạn cho mỗi hình ảnh, sau đó bạn có thể so sánh các bảng. Đây không phải là một kiểm tra hoàn chỉnh (như tính toán sự khác biệt giữa hai), nhưng xác suất hình ảnh của bạn khác với cùng các giá trị biểu đồ là rất rất nhỏ. Ngoài ra, nó cung cấp cho bạn số lượng giá trị duy nhất mà không có NoData (từ số lượng hàng trong bảng). Nếu tổng số lượng của bạn nhỏ hơn kích thước hình ảnh, bạn biết rằng bạn có pixel NoData.


Điều này sẽ làm việc với phao 32 bit? Việc xây dựng và so sánh hai bảng có thực sự nhanh hơn (hoặc dễ dàng hơn) so với việc kiểm tra các giá trị chênh lệch của hai trình quét (về nguyên tắc nên chỉ là 0 và NoData)?
whuber

Bạn đúng rằng nó sẽ không hoạt động với float 32-bit và tôi đã không kiểm tra tốc độ. Tuy nhiên, việc xây dựng bảng thuộc tính chỉ cần đọc dữ liệu một lần và có thể giúp tránh nén 1 bit khi bạn biết rằng nó sẽ thất bại. Ngoài ra tôi không biết kích thước của hình ảnh, nhưng đôi khi bạn không thể lưu trữ chúng trong bộ nhớ.
radouxju

@radouxju hình ảnh có phạm vi lên tới 100.000px cho một bên, vì vậy ~ 30GB không nén. Chúng tôi không có máy với nhiều ram (mặc dù có thể là ảo ...)
matt wilkie

Có vẻ như RAM sẽ không phải là vấn đề với điều kiện bạn phải gắn bó với các hoạt động gốc của ArcGIS. Nó khá tốt với việc sử dụng RAM khi xử lý lưới: bên trong nó có thể thực hiện xử lý từng hàng, theo nhóm hàng và theo cửa sổ hình chữ nhật. Các hoạt động cục bộ như trừ một lưới từ lưới khác có thể hoạt động chủ yếu ở tốc độ đầu vào và đầu ra, chỉ cần một bộ đệm (tương đối nhỏ) cho mỗi tập dữ liệu đầu vào. Xây dựng một bảng thuộc tính đòi hỏi một bảng băm bổ sung - sẽ rất nhỏ khi chỉ có một hoặc hai giá trị xuất hiện, nhưng có thể rất lớn đối với các lưới tùy ý.
whuber

numpy sẽ thực hiện nhiều thao tác hoán đổi với mảng 2 * 30Go, đây không phải là ArcGIS nữa. Tôi giả định dựa trên màn hình in rằng hình ảnh là hình ảnh được phân loại (hầu hết chỉ có giá trị mới), vì vậy bạn không mong đợi quá nhiều lớp.
radouxju

0

Giải pháp đơn giản nhất mà tôi tìm thấy là tính toán một số thống kê tóm tắt về các trình quét và so sánh chúng. Tôi thường sử dụng độ lệch chuẩn và giá trị trung bình, mạnh mẽ cho hầu hết các thay đổi, mặc dù có thể đánh lừa chúng bằng cách cố ý thao tác dữ liệu.

mean_obj = arcpy.GetRasterProperties(input_raster, 'MEAN')
mean = float(mean_obj.getOutput(0))
if round(mean, 4) != 0.2010:
    print("raster differs from expected mean.")

std_obj = arcpy.GetRasterProperties(input_raster, 'STD')
std = float(std_obj.getOutput(0))
if round(std, 4) != 0.0161:
    print("raster differs from expected standard deviation.")

2
Một cách rất lớn để đánh lừa các thống kê này là hoán vị nội dung ô (điều này có thể xảy ra và thực hiện khi kích thước hình ảnh không hoàn toàn đúng). Trên các raster rất lớn, cả SD và trung bình đều không thể phát hiện một cách đáng tin cậy một vài thay đổi nhỏ nằm rải rác (đặc biệt là nếu một vài pixel bị bỏ đi). Có thể hiểu được rằng họ sẽ không phát hiện ra việc lấy mẫu lại lưới bán buôn, cung cấp tích chập khối được sử dụng (nhằm mục đích bảo toàn giá trị trung bình và SD). Thay vào đó, có vẻ thận trọng khi so sánh SD về sự khác biệt của lưới điện bằng không.
whuber

0

Cách dễ nhất là trừ đi một raster từ cái kia, nếu kết quả là 0, thì cả hai hình ảnh đều giống nhau. Ngoài ra, bạn có thể xem biểu đồ hoặc cốt truyện theo màu kết quả.


Phép trừ có vẻ như là một cách tốt để tiến hành so sánh. Tuy nhiên, tôi tin rằng biểu đồ sẽ không hữu ích trong việc phát hiện các vấn đề với các giá trị NoData. Ví dụ, giả sử rằng quy trình nén đã loại bỏ đường viền một pixel quanh lưới (điều này có thể xảy ra!) Nhưng nếu không thì chính xác: tất cả sự khác biệt vẫn sẽ bằng không. Ngoài ra, bạn có nhận thấy rằng OP cần phải làm điều này với 7000 bộ dữ liệu raster không? Tôi không chắc anh ấy sẽ thưởng thức việc kiểm tra 7000 lô.
whuber
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.