유사성을 위해 이미지를 비교하는 간단하고 빠른 방법
유사성을 위해 두 이미지를 비교하는 간단하고 빠른 방법이 필요합니다. 즉, 정확히 같은 것을 포함하지만 약간 다른 배경을 가질 수 있고 몇 픽셀만큼 이동 / 크기 조정 될 수 있다면 높은 가치를 얻고 싶습니다.
(더 구체적인 경우, 하나의 그림은 아이콘이고 다른 그림은 스크린 샷의 하위 영역이며 해당 하위 영역이 정확히 아이콘인지 여부를 알고 싶습니다.)
나는 OpenCV 를 가지고 있지만 여전히 익숙하지 않습니다.
내가 지금까지 생각한 한 가지 가능성 : 두 그림을 10x10 셀로 나누고 그 100 셀 각각에 대해 색상 막대 그래프를 비교하십시오. 그런 다음 일부 구성 임계 값을 설정할 수 있으며 얻은 값이 해당 임계 값보다 높으면 비슷한 것으로 가정합니다.
나는 그것이 얼마나 잘 작동하는지 아직 시도하지 않았지만 충분할 것이라고 생각합니다. 이미지는 이미 사용 사례와 거의 비슷하므로 매우 높은 임계 값을 사용할 수 있습니다.
나는 이것에 대해 수십 가지 다른 가능한 해결책이 있다고 생각합니다 (작업이 매우 유사하기 때문에 유사성을 감지하고 싶기 때문에 작업 자체가 매우 간단하기 때문에). 무엇을 제안 하시겠습니까?
이미지에서 서명 / 지문 / 해시를 얻는 것과 관련하여 매우 관련이 있거나 유사한 몇 가지 질문이 있습니다.
- OpenCV / SURF 디스크립터에서 이미지 해시 / 지문 / 서명을 생성하는 방법은 무엇입니까?
- 많은 이미지의 유사성을 비교하는 이미지 지문
- 거의 중복 된 이미지 감지
- OpenCV : 지문 이미지 및 데이터베이스와 비교 .
- 더 , 더 , 더 , 더 , 더 , 더 , 더 , 더
또한 지문을 얻는 기능을 가진 이러한 구현을 우연히 발견했습니다.
- pHash
- 논문에 기반한 imgSeek ( GitHub 저장소 ) (GPL) 빠른 다중 해상도 이미지 쿼리
- 이미지 일치 . 내가 찾던 것과 매우 유사합니다. 모든 종류의 이미지 에 대한 이미지 서명을 기반으로 한 pHash와 유사하게 Goldberg et al . Python과 Elasticsearch를 사용합니다.
- iqdb
- ImageHash . pHash를 지원합니다.
- 이미지 중복 제거기 (imagededup) . CNN, PHash, DHash, WHash, AHash를 지원합니다.
지각 적 이미지 해시에 대한 몇 가지 토론 : here
약간의 주제 : 오디오 지문을 만드는 방법에는 여러 가지가 있습니다. 노래에 대한 지문 기반 조회를 제공하는 웹 서비스 인 MusicBrainz 는 Wiki에서 좋은 개요를 제공합니다 . 그들은 현재 AcoustID 를 사용 하고 있습니다. 일치하는 (또는 대부분 정확한) 일치를 찾기위한 것입니다. 유사한 일치 항목을 찾으려면 (또는 일부 스 니펫이나 노이즈가 높은 경우) Echoprint를 살펴 보십시오 . 관련 SO 질문이 있습니다 . 오디오에서 해결 된 것 같습니다. 이 모든 솔루션은 아주 잘 작동합니다.
퍼지 검색에 대한 일반적인 질문이 여기 있습니다 . 예를 들어 지역에 민감한 해싱 과 가장 가까운 이웃 검색이 있습니다.
스크린 샷 또는 아이콘을 변형 (확장, 회전, 기울이기 등) 할 수 있습니까? 내 머리 위에 도움이 될만한 몇 가지 방법이 있습니다.
- @carlosdc가 언급 한 간단한 유클리드 거리 (변환 된 이미지에는 작동하지 않으며 임계 값이 필요합니다).
- (정규화 된) 상호 상관 -이미지 영역을 비교하는 데 사용할 수있는 간단한 메트릭입니다. 단순한 유클리드 거리보다 강력하지만 변환 된 이미지에서는 작동하지 않으므로 다시 임계 값이 필요합니다.
- 히스토그램 비교 -정규화 된 히스토그램을 사용하는 경우이 방법이 효과적이며 아핀 변환의 영향을받지 않습니다. 문제는 올바른 임계 값을 결정하는 것입니다. 또한 색상 변화 (밝기, 대비 등)에 매우 민감합니다. 이전 두 가지와 결합 할 수 있습니다.
- MSER (Maximally Stable Extremal Regions) , SURF 또는 SIFT 와 같은 주요 지점 / 영역 탐지기 . 이것들은 매우 강력한 알고리즘이며 간단한 작업에는 너무 복잡 할 수 있습니다. 좋은 점은 아이콘이 하나만있는 정확한 영역을 가질 필요가 없다는 것입니다. 이러한 탐지기는 올바른 일치를 찾을 수있을만큼 강력합니다. 이러한 방법에 대한 좋은 평가는이 백서에 있습니다 : 지역 불변 피처 탐지기 : 측량 .
이들 중 대부분은 이미 OpenCV로 구현되어 있습니다 (예 : cvMatchTemplate 메소드 (히스토그램 일치 사용) 참조 : http://dasl.mem.drexel.edu/~noahKuntz/openCVTut6.html) . 두드러진 점 / 영역 검출기도 사용할 수 있습니다 ( OpenCV 기능 감지 참조) .
나는 최근에 같은 문제에 직면 하여이 문제 (두 이미지를 비교하는 간단하고 빠른 알고리즘)를 해결하기 위해 img_hash 모듈 을 opencv_contrib에 기여합니다 . 이 링크 에서 세부 정보를 찾을 수 있습니다 .
img_hash 모듈은 사용하기 쉬운 6 개의 이미지 해시 알고리즘을 제공합니다.
코드 예
#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/img_hash.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
void compute(cv::Ptr<cv::img_hash::ImgHashBase> algo)
{
auto input = cv::imread("lena.png");
cv::Mat similar_img;
//detect similiar image after blur attack
cv::GaussianBlur(input, similar_img, {7,7}, 2, 2);
cv::imwrite("lena_blur.png", similar_img);
cv::Mat hash_input, hash_similar;
algo->compute(input, hash_input);
algo->compute(similar_img, hash_similar);
std::cout<<"gaussian blur attack : "<<
algo->compare(hash_input, hash_similar)<<std::endl;
//detect similar image after shift attack
similar_img.setTo(0);
input(cv::Rect(0,10, input.cols,input.rows-10)).
copyTo(similar_img(cv::Rect(0,0,input.cols,input.rows-10)));
cv::imwrite("lena_shift.png", similar_img);
algo->compute(similar_img, hash_similar);
std::cout<<"shift attack : "<<
algo->compare(hash_input, hash_similar)<<std::endl;
//detect similar image after resize
cv::resize(input, similar_img, {120, 40});
cv::imwrite("lena_resize.png", similar_img);
algo->compute(similar_img, hash_similar);
std::cout<<"resize attack : "<<
algo->compare(hash_input, hash_similar)<<std::endl;
}
int main()
{
using namespace cv::img_hash;
//disable opencl acceleration may(or may not) boost up speed of img_hash
cv::ocl::setUseOpenCL(false);
//if the value after compare <= 8, that means the images
//very similar to each other
compute(ColorMomentHash::create());
//there are other algorithms you can try out
//every algorithms have their pros and cons
compute(AverageHash::create());
compute(PHash::create());
compute(MarrHildrethHash::create());
compute(RadialVarianceHash::create());
//BlockMeanHash support mode 0 and mode 1, they associate to
//mode 1 and mode 2 of PHash library
compute(BlockMeanHash::create(0));
compute(BlockMeanHash::create(1));
}
이 경우 ColorMomentHash는 최상의 결과를 제공합니다.
- 가우스 블러 공격 : 0.567521
- 시프트 어택 : 0.229728
- 크기 조정 공격 : 0.229358
각 알고리즘의 장단점
img_hash의 성능도 좋습니다
PHash 라이브러리와 속도 비교 (ukbench의 100 개 이미지)
If you want to know the recommend thresholds for these algorithms, please check this post(http://qtandopencv.blogspot.my/2016/06/introduction-to-image-hash-module-of.html). If you are interesting about how do I measure the performance of img_hash modules(include speed and different attacks), please check this link(http://qtandopencv.blogspot.my/2016/06/speed-up-image-hashing-of-opencvimghash.html).
Does the screenshot contain only the icon? If so, the L2 distance of the two images might suffice. If the L2 distance doesn't work, the next step is to try something simple and well established, like: Lucas-Kanade. Which I'm sure is available in OpenCV.
If you want to get an index about the similarity of the two pictures, I suggest you from the metrics the SSIM index. It is more consistent with the human eye. Here is an article about it: Structural Similarity Index
It is implemented in OpenCV too, and it can be accelerated with GPU: OpenCV SSIM with GPU
If you can be sure to have precise alignment of your template (the icon) to the testing region, then any old sum of pixel differences will work.
If the alignment is only going to be a tiny bit off, then you can low-pass both images with cv::GaussianBlur before finding the sum of pixel differences.
If the quality of the alignment is potentially poor then I would recommend either a Histogram of Oriented Gradients or one of OpenCV's convenient keypoint detection/descriptor algorithms (such as SIFT or SURF).
If for matching identical images - code for L2 distance
// Compare two images by getting the L2 error (square-root of sum of squared error).
double getSimilarity( const Mat A, const Mat B ) {
if ( A.rows > 0 && A.rows == B.rows && A.cols > 0 && A.cols == B.cols ) {
// Calculate the L2 relative error between images.
double errorL2 = norm( A, B, CV_L2 );
// Convert to a reasonable scale, since L2 error is summed across all pixels of the image.
double similarity = errorL2 / (double)( A.rows * A.cols );
return similarity;
}
else {
//Images have a different size
return 100000000.0; // Return a bad value
}
Fast. But not robust to changes in lighting/viewpoint etc. Source
If you want to compare image for similarity,I suggest you to used OpenCV. In OpenCV, there are few feature matching and template matching. For feature matching, there are SURF, SIFT, FAST and so on detector. You can use this to detect, describe and then match the image. After that, you can use the specific index to find number of match between the two images.
참고 URL : https://stackoverflow.com/questions/4196453/simple-and-fast-method-to-compare-images-for-similarity
'Programing' 카테고리의 다른 글
Entity Framework 4 / POCO-어디에서 시작합니까? (0) | 2020.05.17 |
---|---|
문자열에서 첫 번째 문자를 제거하는 가장 빠른 방법 (0) | 2020.05.17 |
도메인 기반 디자인이란 무엇입니까? (0) | 2020.05.17 |
JDBC 및 MySQL로 "통신 링크 실패"해결 (0) | 2020.05.16 |
유닉스 / 리눅스 시스템에서 실행중인 프로세스로 커맨드 라인 인수를 얻는 방법? (0) | 2020.05.16 |