답변:
아래는이 문제를 해결하기위한 세 가지 방법입니다 (다른 방법도 많이 있습니다).
첫 번째는 컴퓨터 비전, 키포인트 일치에 대한 표준 접근법입니다. 이를 구현하려면 약간의 배경 지식이 필요할 수 있으며 느려질 수 있습니다.
두 번째 방법은 기본 이미지 처리 만 사용하며 첫 번째 방법보다 빠르며 구현하기가 쉽습니다. 그러나 이해하기 쉽고, 견고성이 부족합니다. 크기가 조정되거나 회전되거나 변색 된 이미지에서는 일치하지 않습니다.
세 번째 방법은 빠르고 강력하지만 구현하기가 가장 어렵습니다.
키포인트 매칭
100 개의 랜덤 포인트를 선택하는 것보다 100 개의 중요한 포인트를 선택하는 것이 좋습니다. 이미지의 특정 부분은 다른 부분 (특히 가장자리와 모서리)보다 더 많은 정보를 가지고 있으며 스마트 이미지 일치에 사용하려는 부분입니다. Google " 키포인트 추출 "및 " 키포인트 일치 "를 통해 주제에 관한 학술 논문을 찾을 수 있습니다. 요즘 SIFT 키포인트 는 다양한 스케일, 회전 및 조명에서 이미지를 일치시킬 수 있기 때문에 가장 인기가 있습니다. 일부 SIFT 구현은 여기 에서 찾을 수 있습니다 .
키포인트 일치와 단점 중 하나는 순진한 구현의 실행 시간입니다. O (n ^ 2m). 여기서 n은 각 이미지의 키포인트 수이고 m은 데이터베이스의 이미지 수입니다. 일부 영리한 알고리즘은 쿼드 트리 또는 이진 공간 파티셔닝과 같이 가장 가까운 일치 항목을 더 빨리 찾을 수 있습니다.
대체 솔루션 : 히스토그램 방법
덜 강력하지만 잠재적으로 더 빠른 다른 솔루션은 각 이미지에 대해 기능 히스토그램을 작성하고 입력 이미지의 히스토그램에 가장 가까운 히스토그램을 가진 이미지를 선택하는 것입니다. 나는 이것을 언더 그레이드로 구현했고, 3 가지 컬러 히스토그램 (빨강, 녹색, 파랑)과 2 가지 텍스처 히스토그램, 방향과 스케일을 사용했습니다. 아래에 세부 정보를 제공하지만 데이터베이스 이미지와 매우 유사한 이미지를 일치시키는 경우에만 효과적입니다. 크기 조정, 회전 또는 변색 된 이미지는이 방법으로 실패 할 수 있지만 자르기와 같은 작은 변경으로 인해 알고리즘이 중단되지는 않습니다.
색상 히스토그램 계산은 간단합니다. 히스토그램 버킷의 범위와 각 범위에 대해 해당 범위의 색상이있는 픽셀 수를 선택하십시오. 예를 들어 "녹색"히스토그램을 고려하여 히스토그램에 대해 4 개의 버킷 (0-63, 64-127, 128-191 및 192-255)을 선택한다고 가정합니다. 그런 다음 각 픽셀에 대해 녹색 값을보고 해당 버킷에 탈리를 추가합니다. 계산을 완료하면 각 버킷 총계를 전체 이미지의 픽셀 수로 나누어 녹색 채널에 대한 정규화 된 히스토그램을 얻습니다.
텍스처 방향 히스토그램의 경우 이미지에서 가장자리 감지를 시작했습니다. 각 모서리 점에는 모서리와 수직 인 방향을 가리키는 법선 벡터가 있습니다. 법선 벡터의 각도를 0과 PI 사이의 6 버킷 중 하나로 양자화했습니다 (가장자리는 180도 대칭이므로 -PI와 0 사이의 각도를 0과 PI 사이로 변환했습니다). 각 방향의 가장자리 지점 수를 계산 한 후 텍스처 방향을 나타내는 정규화되지 않은 히스토그램이 있으며, 각 버킷을 이미지의 총 가장자리 지점 수로 나누어 정규화했습니다.
텍스처 스케일 히스토그램을 계산하기 위해 각 에지 포인트에 대해 같은 방향으로 가장 가까운 다음 에지 포인트까지의 거리를 측정했습니다. 예를 들어, 모서리 지점 A의 방향이 45 도인 경우 알고리즘은 방향이 45도 (또는 합리적인 편차 내) 인 다른 모서리 지점을 찾을 때까지 해당 방향으로 진행합니다. 각 에지 포인트에 대해이 거리를 계산 한 후 해당 값을 히스토그램에 덤프하고 총 에지 포인트 수로 나누어 정규화합니다.
이제 각 이미지마다 5 개의 히스토그램이 있습니다. 두 이미지를 비교하려면 각 히스토그램 버킷 간 차이의 절대 값을 취한 다음이 값을 합산합니다. 예를 들어 이미지 A와 B를 비교하기 위해
|A.green_histogram.bucket_1 - B.green_histogram.bucket_1|
녹색 막대 그래프의 각 버킷에 대해 다른 막대 그래프에 대해 반복 한 다음 모든 결과를 요약합니다. 결과가 작을수록 일치하는 것이 좋습니다. 데이터베이스의 모든 이미지에 대해 반복하면 가장 작은 결과가 일치합니다. 알고리즘이 일치하는 항목을 찾지 못했다고 판단하는 임계 값을 원할 것입니다.
세 번째 선택-요점 + 의사 결정 트리
다른 두 방법보다 훨씬 빠른 세 번째 방법은 시맨틱 텍스트 온 포리스트 (PDF)를 사용하는 것입니다. 여기에는 간단한 키포인트를 추출하고 수집 결정 트리를 사용하여 이미지를 분류합니다. 이는 비용이 많이 드는 매칭 프로세스를 피하고 키포인트가 SIFT보다 훨씬 단순하므로 키포인트 추출이 훨씬 빠르기 때문에 단순한 SIFT 키포인트 일치보다 빠릅니다. 그러나 히스토그램 방법에 없었던 중요한 기능인 SIFT 방법의 회전, 스케일 및 조명에 대한 불변성을 유지합니다.
업데이트 :
내 실수-시맨틱 텍스트 온 포레스트 (Semantic Texton Forests) 논문은 이미지 매칭에 관한 것이 아니라 지역 라벨링에 관한 것이다. 일치하는 원래 논문은 다음과 같습니다 . 무작위 트리를 사용한 키포인트 인식 . 또한 아래의 논문은 계속해서 아이디어를 개발하고 최신 기술을 나타냅니다 (c. 2010).
내가 아는 가장 좋은 방법은 Perceptual Hash를 사용하는 것입니다. 다음에서 사용할 수있는 해시의 훌륭한 오픈 소스 구현이있는 것으로 보입니다.
주요 아이디어는 원본 이미지 파일에서 두드러진 기능을 식별하고 이미지 데이터를 직접 해시하는 대신 해당 기능의 간단한 표현을 해싱하여 각 이미지를 작은 해시 코드 또는 '지문'으로 축소하는 것입니다. 즉, 이미지를 작은 지문 크기의 이미지로 축소하고 지문을 비교하는 등의 단순한 접근 방식에서는 오 탐지율이 훨씬 낮아집니다.
phash는 여러 유형의 해시를 제공하며 이미지, 오디오 또는 비디오에 사용할 수 있습니다.
이 게시물은 내 솔루션의 출발점이었고 여기에 많은 좋은 아이디어가 있었으므로 결과를 공유 할 수있었습니다. 주요 통찰력은 파시 속도를 활용하여 키 포인트 기반 이미지 일치의 속도 저하를 극복 할 수있는 방법을 찾았다는 것입니다.
일반적인 솔루션의 경우 여러 전략을 사용하는 것이 가장 좋습니다. 각 알고리즘은 특정 유형의 이미지 변환에 가장 적합하며이를 활용할 수 있습니다.
가장 빠른 알고리즘; 바닥에서 가장 느리다 (더 정확하지만). 더 빠른 레벨에서 일치하는 것이 발견되면 느린 것을 건너 뛸 수 있습니다.
나는 phash에 대해 매우 좋은 결과를 얻고 있습니다. 크기가 조정 된 이미지에는 정확도가 좋습니다. 수정 된 이미지 (자르기, 회전, 대칭 등)에는 적합하지 않습니다. 해싱 속도를 처리하려면 건초 더미의 해시를 유지하기 위해 디스크 캐시 / 데이터베이스를 사용해야합니다.
phash의 가장 좋은 점은 해시 데이터베이스를 구축하면 (초당 약 1000 개 이미지), 특히 전체 해시 데이터베이스를 메모리에 저장할 수있을 때 검색 속도가 매우 빠르다는 것입니다. 해시는 8 바이트에 불과하므로 상당히 실용적입니다.
예를 들어 백만 개의 이미지가있는 경우 백만 개의 64 비트 해시 값 (8MB) 배열이 필요합니다. 일부 CPU에서는 L2 / L3 캐시에 적합합니다! 실제 사용에서 나는 1 기가 -hamm / sec 이상의 corei7 비교를 보았습니다. CPU에 대한 메모리 대역폭의 문제 일뿐입니다. 10 억 이미지 데이터베이스는 64 비트 CPU (8GB RAM 필요)에서 실용적이며 검색은 1 초를 초과하지 않습니다!
수정 / 자른 이미지의 경우 SIFT와 같은 변형 불변 기능 / 키 포인트 감지기가 보일 것입니다. SIFT는 자르기 / 회전 / 미러 등을 감지하는 좋은 키포인트를 생성합니다. 그러나 디스크립터 비교는 파싱에 사용되는 해밍 거리에 비해 매우 느립니다. 이것은 중요한 제한 사항입니다. 최대 1 개의 IxJxK 디스크립터가 하나의 이미지를 룩업하는 것과 비교하기 때문에 많은 비교가 필요합니다 (I = 건초 더미 이미지 수, J = 건초 더미 이미지 당 목표 키포인트, K = 바늘 이미지 당 목표 키포인트).
속도 문제를 해결하기 위해 발견 된 각 키 포인트 주위에 피쉬를 사용하고 피처 크기 / 반경을 사용하여 하위 사각형을 결정했습니다. 이 작업을 제대로 수행하기위한 요령은 (바늘 이미지에서) 다른 하위 정사 수준을 생성하기 위해 반경을 늘리거나 줄이는 것입니다. 일반적으로 첫 번째 수준 (비 스케일)은 일치하지만 종종 몇 가지가 더 필요합니다. 왜 이것이 작동하는지 100 % 확신 할 수는 없지만 파싱이 작동하기에는 너무 작은 기능을 사용할 수 있다고 상상할 수 있습니다 (파싱은 이미지를 32x32로 축소합니다).
또 다른 문제는 SIFT가 키포인트를 최적으로 배포하지 않는다는 것입니다. 가장자리가 많은 이미지 섹션이 있으면 키포인트가 클러스터링되고 다른 영역에는 아무런 영향이 없습니다. 배포를 향상시키기 위해 OpenCV에서 GridAdaptedFeatureDetector를 사용하고 있습니다. 어떤 격자 크기가 가장 좋은지 잘 모르겠습니다. 작은 격자를 사용하고 있습니다 (이미지 방향에 따라 1x3 또는 3x1).
지형 감지 전에 모든 건초 더미 이미지 (및 바늘)를 더 작은 크기로 조정하려고합니다 (최대 크기에 따라 210px 사용). 이렇게하면 이미지의 노이즈가 줄어들고 (컴퓨터 비전 알고리즘에서는 항상 문제가 됨)보다 두드러진 기능에 탐지기에 초점을 맞출 수 있습니다.
인물 이미지의 경우 얼굴 인식을 시도하여 크기를 조정할 이미지 크기와 격자 크기를 결정하는 데 사용할 수 있습니다 (예 : 가장 큰 얼굴 크기는 100px로 조정). 피처 감지기는 여러 스케일 레벨 (피라미드 사용)을 설명하지만 사용할 스케일 수에는 제한이 있습니다 (물론 조정할 수 있습니다).
키포인트 감지기는 원하는 기능 수보다 적은 수를 반환 할 때 가장 잘 작동합니다. 예를 들어 400을 요청하고 300을 돌려 받으면 좋습니다. 매번 400을 다시 얻는다면, 몇 가지 좋은 기능을 생략해야 할 것입니다.
바늘 이미지는 건초 더미 이미지보다 키포인트가 적을 수 있지만 여전히 좋은 결과를 얻을 수 있습니다. 더 많은 것을 추가한다고해서 반드시 큰 이익을 얻을 수있는 것은 아닙니다. 예를 들어 J = 400 및 K = 40 인 경우 내 적중률은 약 92 %입니다. J = 400 및 K = 400 인 경우 적중률은 96 %까지만 올라갑니다.
스케일링, 회전, 미러링 등을 해결하기 위해 해밍 기능의 최고 속도를 활용할 수 있습니다. 다중 패스 기술을 사용할 수 있습니다. 각 반복에서 하위 사각형을 변환하고 다시 해시하고 검색 기능을 다시 실행하십시오.
나는 아이디어가 있는데, 그것이 효과가 있고 매우 빠를 가능성이 높습니다. 이미지를 80x60 해상도 또는 비슷한 수준으로 서브 샘플링하고 그레이 스케일로 변환 할 수 있습니다 (서브 샘플링 후 더 빠름). 비교하려는 두 이미지를 처리하십시오. 그런 다음 두 이미지 (쿼리 이미지와 db의 각 이미지) 사이의 정규 제곱 차이 합계 또는 두 이미지가 비슷한 경우 1에 더 가까운 반응을 제공하는 더 나은 정규 교차 상관을 실행하십시오. 그런 다음 이미지가 비슷한 경우보다 정교한 기술로 진행하여 동일한 이미지인지 확인할 수 있습니다. 분명히이 알고리즘은 데이터베이스의 이미지 수 측면에서 선형이므로 최신 하드웨어에서는 초당 최대 10000 개의 이미지가 매우 빠릅니다. 회전에 불변이 필요한 경우이 작은 이미지에 대해 지배적 인 그래디언트를 계산할 수 있습니다. 그러면 전체 좌표계를 표준 방향으로 회전시킬 수 있지만 속도가 느려집니다. 그리고 아니요, 여기에 확장 할 불변성이 없습니다.
좀 더 일반적인 것을 원하거나 큰 데이터베이스 (수백만 개의 이미지)를 사용하려면 이미지 검색 이론을 살펴 봐야합니다 (지난 5 년간 논문이 많이 나타남). 다른 답변에는 몇 가지 지침이 있습니다. 그러나 그것은 과잉 일 수 있으며 제안 된 히스토그램 접근법이 그 일을 할 것입니다. 많은 다른 빠른 접근 방식의 조합이 더 좋을 것이라고 생각하지만.
우리 회사는 매월 제조업체에서 약 2,200 만 개의 이미지를 가져 왔습니다. 카탈로그에 업로드하는 이미지가 새로운 이미지 인지 확인하는 빠른 솔루션을 찾고있었습니다 .
이상적인 솔루션을 찾기 위해 인터넷을 광범위하게 검색했다고 말하고 싶습니다. 나는 심지어 내 자신의 가장자리 감지 알고리즘을 개발했습니다.
여러 모델의 속도와 정확성을 평가했습니다. 흰색 배경을 가진 내 이미지는 파싱과 매우 잘 작동합니다. 마찬가지로 redcalx가 말했다, 나는 phash 또는 ahash을 추천합니다. MD5 해싱 또는 기타 암호화 해시를 사용 하지 마십시오 . 그렇지 않으면 정확한 이미지 일치 만 원합니다. 이미지 사이에서 발생하는 크기 조정이나 조작은 다른 해시를 생성합니다.
phash / ahash의 경우 다음을 확인하십시오. imagehash
내 코드와 정확성을 게시하여 * redcalx '* 게시물을 확장하고 싶었습니다.
내가하는 일 :
from PIL import Image
from PIL import ImageFilter
import imagehash
img1=Image.open(r"C:\yourlocation")
img2=Image.open(r"C:\yourlocation")
if img1.width<img2.width:
img2=img2.resize((img1.width,img1.height))
else:
img1=img1.resize((img2.width,img2.height))
img1=img1.filter(ImageFilter.BoxBlur(radius=3))
img2=img2.filter(ImageFilter.BoxBlur(radius=3))
phashvalue=imagehash.phash(img1)-imagehash.phash(img2)
ahashvalue=imagehash.average_hash(img1)-imagehash.average_hash(img2)
totalaccuracy=phashvalue+ahashvalue
내 결과 중 일부는 다음과 같습니다.
item1 item2 totalsimilarity
desk1 desk1 3
desk1 phone1 22
chair1 desk1 17
phone1 chair1 34
도움이 되었기를 바랍니다!
100 개의 임의의 점을 선택하면 비슷한 (또는 때로는 다른 유형의) 이미지가 동일하게 표시되어 원하는 것으로 생각하지 않을 수 있습니다. 이미지가 다른 형식 (png, jpeg 등)이거나 크기가 다르거 나 메타 데이터가 다른 경우 MD5 해시는 작동하지 않습니다. 모든 이미지를 더 작은 크기로 줄이는 것이 좋은 방법입니다. 좋은 이미지 라이브러리 / 빠른 언어를 사용하는 한 픽셀 대 픽셀 비교를 수행하는 데 너무 오래 걸리지 않으며 크기가 충분히 작습니다.
당신은 그것들을 작게 만들려고 시도 할 수 있습니다. 동일한 경우 더 큰 크기에 대해 다른 비교를 수행하십시오-속도와 정확성의 좋은 조합 일 수 있습니다 ...
많은 수의 이미지가있는 경우 여러 해시를 사용하여 확률 적이지만 효율적인 결과를 얻는 Bloom 필터를 살펴보십시오 . 이미지 수가 많지 않으면 md5와 같은 암호화 해시이면 충분합니다.