래스터 차이 : 이미지의 값이 동일한 지 확인하는 방법은 무엇입니까?


10

주어진 2 개의 래스터 레이어가 동일한 내용을 가지고 있는지 확인하는 수단이 있습니까?

회사 공유 스토리지 볼륨에 문제가 있습니다. 현재 전체 백업을 수행하는 데 3 일이 걸리기에는 너무 큽니다. 예비 조사에 따르면 가장 큰 공간을 소비하는 범인 중 하나는 실제로 CCITT 압축을 사용하여 1 비트 레이어로 저장해야하는 온 / 오프 래스터입니다.

전형적인 현재 / 비 존재 래스터

이 샘플 이미지는 현재 2 비트 (3 가지 가능한 값)이며 파일 시스템에서 11MB의 LZW 압축 tiff로 저장됩니다. 1 비트 (가능한 2 개의 값)로 변환하고 CCITT Group 4 압축을 적용한 후에는 1.3MB로 줄어 듭니다.

(이것은 실제로 매우 잘 행동하는 시민입니다. 다른 사람들은 32 비트 부동으로 저장됩니다!)

이것은 환상적인 소식입니다! 그러나 이것을 적용하기에는 거의 7,000 개의 이미지가 있습니다. 압축 할 스크립트를 작성하는 것은 간단합니다.

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

...하지만 중요한 테스트가 누락되었습니다. 새로 압축 된 버전이 컨텐츠와 동일합니까?

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

Image-A의 내용이 Image-B의 내용과 가치가 동일하다는 것을 자동으로 증명할 수있는 도구 나 방법이 있습니까?

ArcGIS 10.2 및 QGIS에 액세스 할 수 있지만 덮어 쓰기 전에 정확성을 보장하기 위해 이러한 모든 이미지를 수동으로 검사 할 필요가없는 것 외에는 대부분 열려 있습니다. 실제로 ON / OFF 값보다 많은 값을 가진 이미지를 실수로 변환하고 덮어 쓰는 것은 끔찍한 일입니다. 수집하고 생성하는 데 대부분 수천 달러가 소요됩니다.

매우 나쁜 결과

업데이트 : 가장 큰 범죄자는 최대 30px의 압축되지 않은 32 비트 수레입니다.


1
구현하는 한 가지 방법 raster_diff(old_img, new_img) == "Identical"은 차이의 절대 값의 구역 최대 값이 0과 같은지 확인하는 것입니다. 여기서 영역은 전체 그리드 범위에서 사용됩니다. 찾고있는 솔루션입니까? (그렇다면 NoData 값도 일치하는지 확인하기 위해 다시 조정해야합니다.)
whuber

1
@whuber는 적절한 NoData처리가 대화에 머 무르도록 해 주셔서 감사합니다 .
matt wilkie 21시 59 분

당신 len(numpy.unique(yourraster)) == 2이 그것을 확인할 수 있다면 , 당신은 2 개의 고유 값을 가지고 있으며 이것을 안전하게 할 수 있음을 알고 있습니다.
RemcoGerlich

@Remco 기본 알고리즘 numpy.unique은 차이가 일정하다는 것을 확인하는 다른 대부분의 방법보다 시간과 공간 측면에서 계산 비용이 많이 듭니다. 원본을 손실 된 압축 버전과 비교하는 것과 같이 많은 차이점을 보이는 두 개의 매우 큰 부동 소수점 래스터 간의 차이점에 직면하면 영원히 쇠약하거나 완전히 실패 할 수 있습니다.
whuber

1
@Aaron, 다른 일을하기 위해 프로젝트를 시작했습니다. 그 중 일부는 개발 시간이 계속 증가했기 때문입니다. 너무 많은 경우를 자동으로 처리 할 수 ​​없었기 때문에 이미지를 수정하는 대신 이미지를 생성하는 사람들에게 문제를 던지기로 결정했습니다. (예 : "디스크 할당량은 X입니다. 내부 작업 방법을 배우십시오.") 그러나 gdalcompare.py큰 약속을 보였습니다 ( 답변 참조 )
matt wilkie

답변:


8

래스터를 numpy 배열로 변환 한 다음 array_equal 과 모양 및 요소가 동일한 지 확인하십시오 . 동일한 경우 결과는 다음 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"

GDAL :

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"

달콤하고 단순 해 보입니다. 나는 두 가지 세부 사항에 대해 궁금하다. 첫째,이 솔루션은 NoData 값을 올바르게 처리합니까? 둘째, 구역 요약과 같은 그리드 비교를위한 내장 함수를 사용하여 속도를 어떻게 비교합니까?
whuber

1
좋은 점 @ whuber. 모양과 요소를 고려해야하는 스크립트를 빠르게 조정했습니다. 제기 한 사항을 확인하고 결과를보고하겠습니다.
Aaron

1
@whuber NoData처리 와 관련하여 RasterToNumPyArray기본적으로 입력 래스터의 NoData 값을 배열에 할당합니다. Matt의 경우에는 적용되지 않지만 사용자는 다른 값을 지정할 수 있습니다. 속도와 관련하여 스크립트가 2 개의 4 비트 래스터와 6210 개의 열 및 7650 개의 행 (DOQQ 범위)을 비교하는 데 4.5 초가 걸렸습니다. 이 방법을 구역 요약과 비교하지 않았습니다.
Aaron

1
gis.stackexchange.com/questions/32995/…에서 적응 된 gdal 등가로 접었습니다.
matt wilkie

4

gdalcompare.py 스크립트 http://www.gdal.org/gdalcompare.html을 사용해보십시오 . 스크립트의 소스 코드는 http://trac.osgeo.org/gdal/browser/trunk/gdal/swig/python/scripts/gdalcompare.py에 있으며 파이썬 스크립트이기 때문에 불필요한 스크립트를 쉽게 제거 할 수 있습니다 현재 요구에 맞는 새로운 테스트 및 추가 스크립트는 밴드별로 두 이미지의 이미지 데이터를 읽어 픽셀 단위로 비교하는 것으로 보이며 아마도 매우 빠르고 재사용 가능한 방법 일 것입니다.


1
흥미롭고, 나는 gdal을 좋아하고,이 대본을 몰랐다. 결과를 해석하기위한 문서는 존재하지 않지만 드물게 ;-)입니다. 초기 테스트에서 색상 해석과 팔레트의 차이를보고합니다. 즉, 현재 요구에 맞지 않을 수 있습니다. 그래도 여전히 탐색 중입니다. (참고 :이 답변은 너무 짧기 때문에 여기에 잘 맞지 않습니다. 링크 전용 답변은 권장되지 않습니다.
matt wilkie

1

각 이미지에 대해 래스터 속성 테이블 을 작성하고 테이블을 비교할 것을 제안합니다 . 이것은 완전한 검사가 아니며 (두 값의 차이를 계산하는 것과 같음) 이미지가 동일한 히스토그램 값으로 다를 가능성은 매우 작습니다. 또한 NoData가없는 고유 한 값의 수를 제공합니다 (테이블의 행 수에서). 총 개수가 이미지 크기보다 작 으면 NoData 픽셀이있는 것입니다.


이것이 32 비트 플로트에서 작동합니까? 두 테이블을 만들고 비교하는 것이 실제로 두 래스터의 차이 값을 검사하는 것보다 더 빠르거나 더 쉬운가?
whuber

32 비트 플로트에서는 작동하지 않으며 속도를 확인하지 않았습니다. 그러나 속성 테이블을 작성하면 데이터를 한 번만 읽어야하며 실패 할 경우 1 비트 압축을 피하는 데 도움이됩니다. 또한 이미지의 크기를 모르지만 때로는 메모리에 저장할 수 없습니다.
radouxju

@ radouxju 이미지의 크기는 한면에 최대 100,000px이므로 ~ 30GB의 압축되지 않습니다. 우리는 (아마도 가상으로하지만 ...) 그렇게 많은 램과 시스템이없는
매트 윌키

ArcGIS 기본 작업을 사용하는 경우 RAM이 문제가되지 않을 것 같습니다. 그리드를 처리 할 때 RAM 사용이 좋습니다. 내부적으로 행 단위, 행 그룹 및 직사각형 창으로 처리 할 수 ​​있습니다. 하나의 그리드를 다른 그리드에서 빼는 것과 같은 로컬 연산은 본질적으로 입력 및 출력 속도로 작동 할 수 있으며 각 입력 데이터 세트마다 하나의 (상대적으로 작은) 버퍼 만 필요합니다. 속성 테이블을 생성하려면 추가 해시 테이블이 필요합니다. 하나 또는 두 개의 값만 표시 될 때는 아주 적지 만 임의의 그리드에는 막대 할 수 있습니다.
whuber

numpy는 2 * 30Go 배열로 많은 스와핑을 수행하지만 더 이상 ArcGIS는 아닙니다. 나는 인쇄 화면을 기반으로 이미지가 이미지를 분류하고 (대부분 값이 거의 없음) 가정하므로 많은 클래스를 기대하지는 않습니다.
radouxju

0

내가 찾은 가장 간단한 해결책은 래스터에 대한 요약 통계를 계산하고 비교하는 것입니다. 나는 일반적으로 표준 편차와 평균을 사용하는데, 이는 대부분의 변경에 강하지 만 데이터를 의도적으로 조작하여 속일 수 있습니다.

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
이러한 통계를 속이는 한 가지 방법은 셀 내용을 바꾸는 것입니다 (이미지 크기가 정확하지 않은 경우 발생할 수 있음). 매우 큰 래스터에서는 SD 나 평균이 흩어져있는 작은 변화 (특히 몇 개의 픽셀 만 떨어 뜨린 경우)를 안정적으로 감지하지 못합니다. 입방 형 회선이 사용 된 경우 (평균과 SD를 보존하기 위해) 그리드의 도매 리샘플링을 감지하지 못할 것입니다. 그리드의 차이의 SD를 0과 비교하는 것이 신중한 것처럼 보입니다.
whuber

0

가장 쉬운 방법은 한 래스터를 다른 래스터에서 빼는 것입니다. 결과가 0이면 두 이미지가 동일합니다. 또한 색상별로 히스토그램 또는 플롯을 볼 수 있습니다.


빼기는 비교를 수행하는 좋은 방법 인 것 같습니다. 그러나 히스토그램은 NoData 값의 문제를 감지하는 데별로 유용하지 않을 것이라고 생각합니다. 예를 들어, 압축 절차에서 그리드 주변의 1 픽셀 경계선이 제거되었지만 (그렇게 발생할 수 있습니다!) 정확하다고 가정합니다. 모든 차이는 여전히 0입니다. 또한 OP가 7000 개의 래스터 데이터 세트로이 작업을 수행해야한다는 것을 알고 계셨습니까? 나는 그가 7000 플롯을 조사하는 것을 좋아할 지 확신하지 못한다.
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.