xfeatures - Android에서 OpenCV 이미지 비교
python opencv surf match (2)
[편집] 이미지 비교를위한 몇 가지 코드를 고안했습니다. 일치하는 부분은 여전히 약간 결함이 있으며 나는 약간의 assitance를 좋아할 것입니다. 프로젝트는 - GitHub 에서 찾을 수 있습니다.
나는이 두 이미지 Img1 과 Img2를 가지고있다 .
openCV에서 다음 명령을 사용할 때
Mat img1 = Highgui.imread("mnt/sdcard/IMG-20121228.jpg");
Mat img2 = Highgui.imread("mnt/sdcard/IMG-20121228-1.jpg");
try{
double l2_norm = Core.norm( img1, img2 );
tv.setText(l2_norm+"");
} catch(Exception e) {
//image is not a duplicate
}
나는 l2_norm에 대해 double 값을 얻는다. 이 이중 값은 중복 이미지 쌍에 따라 다릅니다. 그러나 이미지가 다르면 예외가 발생합니다. 이 방법으로 중복 된 이미지를 식별합니까? 아니면 더 좋은 방법이 있습니까? 나는 광범위하게 봤 거든 정말 설득력있는 대답을 찾을 수 없었다. 나는 두 개의 이미지를 비교하고 이미지에 따라 true
또는 false
의 부울 값을 얻는 방법에 대한 코드와 설명을 원합니다.
편집하다
Scalar blah= Core.sumElems(img2);
Scalar blah1=Core.sumElems(img1);
if(blah.equals(blah1))
{
tv.setText("same image");
}
}
나는 이것을 시도했지만 if
조건이 결코 만족스럽지 않습니다. 몇 가지 차이점이 있다고 가정하고 있지만 Scalar
대한 compare
기능은 없습니다. 나는 무엇을해야합니까?
편집하다
try{
Scalar blah= Core.sumElems(img2);
Scalar blah1=Core.sumElems(img1);
String b=blah.toString();
String b1=blah1.toString();
System.out.println(b+" "+b1);
double comp=b.compareTo(b1);
tv.setText(""+comp);
}
이 방법은 다시 결함이 있습니다. 상당한 정확도로 이미지를 비교하는 데 사용할 수 있지만 이미지의 크기가 다른 경우에는 실패합니다.
이미지의 크기가 다른데 스칼라 값을 출력하면 다음과 같이됩니다.
[9768383.0, 1.0052889E7, 1.0381814E7, 0.0] [1.5897384E7, 1.6322252E7, 1.690251E7, 0.0]
두 번째 숫자와 세 번째 숫자 사이의 차이는 동일하지 않은 크기의 이미지를 비교할 때보 다 훨씬 적지 만 상당히 다릅니다. 그러나 첫 번째 숫자는 가장 큰 변화를 겪습니다.
두 이미지의 내용을 비교하는 가장 빠른 방법은 무엇입니까?
[편집하다]
알아낼 수없는 것은 MatOfKeyPoint
변수 keypoints
및 logoKeypoints
를 초기화하는 방법입니다. 내 코드 단편은 다음과 같습니다.
FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);
//FeatureDetector detector = FeatureDetector.create(FeatureDetector.FAST);
//Imgproc.cvtColor(img1, img1, Imgproc.COLOR_RGBA2RGB);
//Imgproc.cvtColor(img2, img2, Imgproc.COLOR_RGBA2RGB);
DescriptorExtractor SurfExtractor = DescriptorExtractor
.create(DescriptorExtractor.SURF);
//extract keypoints
MatOfKeyPoint keypoints, logoKeypoints;
long time= System.currentTimeMillis();
detector.detect(img1, keypoints);
Log.d("LOG!", "number of query Keypoints= " + keypoints.size());
detector.detect(img2, logoKeypoints);
Log.d("LOG!", "number of logo Keypoints= " + logoKeypoints.size());
Log.d("LOG!", "keypoint calculation time elapsed" + (System.currentTimeMillis() -time));
//Descript keypoints
long time2 = System.currentTimeMillis();
Mat descriptors = new Mat();
Mat logoDescriptors = new Mat();
Log.d("LOG!", "logo type" + img2.type() + " intype" + img1.type());
SurfExtractor.compute(img1, keypoints, descriptors);
SurfExtractor.compute(img2, logoKeypoints, logoDescriptors);
Log.d("LOG!", "Description time elapsed" + (System.currentTimeMillis()- time2));
분명히 변수 keypoints
및 logoKeypoints
null cuz 초기화 할 수 없습니다. 그런 다음 null 포인터 예외가 나타납니다. 어떻게 초기화합니까?
https://code.i-harness.com
다음 코드를 시도해 볼 수 있습니다.
Mat img1 = Highgui.imread("mnt/sdcard/IMG-20121228.jpg");
Mat img2 = Highgui.imread("mnt/sdcard/IMG-20121228-1.jpg");
Mat result = new Mat();
Core.compare(img1,img2,result,Core.CMP_NE);
int val = Core.countNonZero(result);
if(val == 0) {
//Duplicate Image
} else {
//Different Image
}
여기에서 코드 비교 함수는 두 이미지를 비교 한 다음 이미지 사이에 유사성이 있으면 특정 행렬 값이 255가되고 다른 모든 값은 0이됩니다. 그런 다음 0이 아닌 값의 수를 계산하여 이미지가 동일한 지 여부를 판별 할 수 있습니다. 이는 정확히 동일한 이미지에만 적용됩니다.
조명 효과를 무시한 이미지를 비교하려면 먼저 가장자리 이미지 (OpenCV의 canny 기능 사용)를 생성 한 다음 이미지를 비교하는 것이 좋습니다.
희망이 답변은 당신을 도와줍니다 !!
이 질문은 간단한 질문이 아니며 따를 수있는 개념이 다르다는 것을 이해해야합니다. 나는 소스 코드가없는 두 가지 해결책만을 지적하겠다.
- 히스토그램 비교 : 두 이미지를 그레이 스케일로 변환하여 [0, ..., 255]의 범위에서 히스토그램을 만들 수 있습니다. 모든 픽셀 값이 계산됩니다. 그런 다음 두 히스토그램을 비교에 사용하십시오. 픽셀 강도의 분포가 일부 임계 값 (모든 픽셀의 90 %) 이상이면이 이미지를 중복으로 간주 할 수 있습니다. 하지만 이것은 가장 단순한 솔루션 중 하나이며 어떤 그림의 분포가 동일하면 안정적이지 않습니다.
- 관심 지점 감지기 / 설명자 : SIFT / SURF 이미지 감지기 및 설명자를 살펴보십시오. 탐지기는 이미지에서 강도의 고유 키포를 결정하려고 시도합니다. 기술자는이 위치 I (x, y)에서 계산 될 것이다. bruteforce-approach와 euclidean distance를 가진 정규 matcher는 설명자를 사용하여이 이미지들을 일치시킬 수 있습니다. 이미지가 중복 된 경우 일치하는 비율이 매우 높아야합니다. 이 솔루션은 구현하기에 좋으며이 주제와 관련하여 충분한 자습서가있을 수 있습니다.
나는 이것이 도움이되기를 바랍니다. 질문이 있으면 물어보십시오.
[업데이트 1] C ++ 튜토리얼 : http://morf.lv/modules.php?name=tutorials&lasit=2#.UR-ewKU3vCk
일부 JavaCV 자습서 : http://code.google.com/p/javacv/w/list
[UPDATE-2] 다음은 SIFT-Detector와 SIFT-Descriptor가 기본 매개 변수를 사용하는 예입니다. RANSAC- 호모 그래피의 임계 값은 65이며 재 투영 오류 (ε)는 10이며 교차 유효성 검사가 사용됩니다. 일치하는 항목을 계산하려고 할 수 있습니다. Inliner-Outlier-Ratio가 너무 높으면이 쌍을 중복으로 볼 수 있습니다. 예 :이 이미지는 IMG2의 IMG1 및 198에서 180 개의 키포인트를 생성합니다. 일치하는 디스크립터는 163 개이며 그 중 3 개만이 아웃 라이어입니다. 따라서이 이미지가 중복 될 수 있다는 의미 일 수있는 정말 좋은 비율을 제공합니다.
[업데이트 -3] 왜 MatOfKeypoints를 초기화 할 수 있는지 이해할 수 없습니다. API를 읽었으며 public 생성자가 있습니다. AND : 분석 할 이미지의 매트를 사용할 수 있습니다. 이거 좋은데. =)
MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage);
매칭의 경우 SURF 또는 SIFT의 유클리드 거리가 필요하므로 BRUTEFORCE_SL2 Descriptor-Matcher를 사용하십시오.