xfeatures - Android에서 OpenCV 이미지 비교




python opencv surf match (2)

[편집] 이미지 비교를위한 몇 가지 코드를 고안했습니다. 일치하는 부분은 여전히 ​​약간 결함이 있으며 나는 약간의 assitance를 좋아할 것입니다. 프로젝트는 - GitHub 에서 찾을 수 있습니다.

나는이 두 이미지 Img1Img2를 가지고있다 .

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]

두 번째 숫자와 세 번째 숫자 사이의 차이는 동일하지 않은 크기의 이미지를 비교할 때보 다 훨씬 적지 만 상당히 다릅니다. 그러나 첫 번째 숫자는 가장 큰 변화를 겪습니다.

두 이미지의 내용을 비교하는 가장 빠른 방법은 무엇입니까?

[편집하다]

나는 here 에서 찾은 코드를 사용하고 here .

알아낼 수없는 것은 MatOfKeyPoint 변수 keypointslogoKeypoints 를 초기화하는 방법입니다. 내 코드 단편은 다음과 같습니다.

           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));

분명히 변수 keypointslogoKeypoints 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 기능 사용)를 생성 한 다음 이미지를 비교하는 것이 좋습니다.

희망이 답변은 당신을 도와줍니다 !!


이 질문은 간단한 질문이 아니며 따를 수있는 개념이 다르다는 것을 이해해야합니다. 나는 소스 코드가없는 두 가지 해결책만을 지적하겠다.

  1. 히스토그램 비교 : 두 이미지를 그레이 스케일로 변환하여 [0, ..., 255]의 범위에서 히스토그램을 만들 수 있습니다. 모든 픽셀 값이 계산됩니다. 그런 다음 두 히스토그램을 비교에 사용하십시오. 픽셀 강도의 분포가 일부 임계 값 (모든 픽셀의 90 %) 이상이면이 이미지를 중복으로 간주 할 수 있습니다. 하지만 이것은 가장 단순한 솔루션 중 하나이며 어떤 그림의 분포가 동일하면 안정적이지 않습니다.
  2. 관심 지점 감지기 / 설명자 : 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를 사용하십시오.





image-comparison