2013-02-13 52 views
19

[EDIT] Tôi đã nghĩ ra một số mã để so sánh hình ảnh. Phần phù hợp vẫn còn một chút thiếu sót và tôi rất thích một số sự thừa nhận. Dự án có thể được tìm thấy tại - GitHub.So sánh hình ảnh OpenCV trong Android

tôi có hai hình ảnh những img1img2:

enter image description hereenter image description here

Khi tôi sử dụng lệnh sau đây trong 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 
} 

tôi nhận được một giá trị gấp đôi cho l2_norm. Giá trị kép này thay đổi cho các cặp hình ảnh trùng lặp. Nhưng nếu các hình ảnh khác nhau, thì một ngoại lệ được ném ra. Đây có phải là cách tôi xác định hình ảnh trùng lặp không? Hoặc là có một phương pháp tốt hơn? Tôi đã Googled rộng rãi và không thể tìm thấy một câu trả lời thực sự thuyết phục. Tôi muốn mã và giải thích về cách tôi so sánh hai hình ảnh và nhận giá trị boolean là true hoặc false tùy thuộc vào hình ảnh.

EDIT

Scalar blah= Core.sumElems(img2); 
    Scalar blah1=Core.sumElems(img1); 

    if(blah.equals(blah1)) 
    { 
     tv.setText("same image"); 
    } 
    } 

Tôi đã thử điều này, nhưng điều kiện if là không bao giờ hài lòng. Tôi giả sử có một vài khác biệt, nhưng không có chức năng compare cho Scalar. Tôi làm gì?

EDIT

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

Phương pháp này được một lần nữa sai lầm. Mặc dù nó có thể được sử dụng để so sánh hình ảnh với độ chính xác cao, nhưng nó không thành công khi hình ảnh có kích thước khác nhau.

Khi hình ảnh có kích thước khác nhau và tôi in các giá trị vô hướng tôi có được điều này:

[9768383.0, 1.0052889E7, 1.0381814E7, 0.0] [1.5897384E7, 1.6322252E7, 1.690251E7, 0.0]

Các biến thể giữa các con số thứ hai và thứ ba mặc dù không nhiều là khá lớn so với khi những hình ảnh của cùng một kích thước được so sánh. Tuy nhiên, số đầu tiên bị thay đổi nhiều nhất.

Cách nào là cách nhanh nhất để so sánh nội dung của hai hình ảnh?

[EDIT]

Tôi đang sử dụng mã tôi thấy here.

Điều tôi không thể tìm ra là cách khởi tạo các biến số MatOfKeyPointkeypointslogoKeypoints. Dưới đây là đoạn mã của tôi:

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

Tôi rõ ràng là không thể khởi tạo các biến keypointslogoKeypoints để null vì tôi sẽ nhận được một con trỏ null thì ngoại lệ. Làm thế nào để tôi khởi tạo chúng?

+0

Hướng dẫn OpenCV này hy vọng cung cấp một số thông tin về chủ đề; http://goo.gl/gwN6e. – harism

+2

try-catch là * không * giống như if-else! Nếu một ngoại lệ đã được ném (bắt khối), một cái gì đó đã đi hoàn toàn sai! – sschrass

+0

@SatelliteSD - Tôi biết điều đó. Đó là lý do tại sao tôi hỏi nếu có một phương pháp tốt hơn. –

Trả lời

25

Bạn nên hiểu rằng đây không phải là một câu hỏi đơn giản và bạn có các khái niệm khác nhau mà bạn có thể làm theo. Tôi sẽ chỉ chỉ ra hai giải pháp mà không có mã nguồn.

  1. Histogram so: Bạn có thể chuyển đổi tất cả các hình ảnh thành màu xám quy mô tạo ra một biểu đồ trong khoảng [0, ..., 255]. Mỗi giá trị pixel sẽ được tính. Sau đó sử dụng cả hai biểu đồ để so sánh. Nếu phân bố cường độ pixel bằng hoặc cao hơn một số ngưỡng (có lẽ là 90% của tất cả các pixel), bạn có thể xem xét hình ảnh này là trùng lặp. NHƯNG: Đây là một trong những giải pháp đơn giản nhất và nó không ổn định nếu bất kỳ hình ảnh nào có phân phối bằng nhau.
  2. Máy dò điểm ưa thích/-Descriptors: Hãy xem qua trình phát hiện và mô tả hình ảnh SIFT/SURF. Một máy dò sẽ cố gắng xác định các mức độ độc đáo của cường độ trong một hình ảnh. Một bộ mô tả sẽ được tính tại vị trí này I (x, y). Một matcher bình thường với một cách tiếp cận bruteforce và khoảng cách euclide có thể phù hợp với những hình ảnh này bằng cách sử dụng các mô tả của chúng. Nếu một hình ảnh là một bản sao tỷ lệ của các trận đấu nhất định nên rất cao. Giải pháp này là tốt để thực hiện và có thể có đủ hướng dẫn về chủ đề này.

Tôi hy vọng điều này sẽ hữu ích. Vui lòng hỏi nếu bạn có câu hỏi.

[UPDATE-1] Một C++ - hướng dẫn: http://morf.lv/modules.php?name=tutorials&lasit=2#.UR-ewKU3vCk

Một số JavaCV-hướng dẫn: http://code.google.com/p/javacv/w/list

[UPDATE-2] Dưới đây là một ví dụ với SIFT-Detector và SIFT -Descriptor sử dụng các tham số mặc định. RANSAC-Ngưỡng cho homography là 65, lỗi reprojection (epsilon) là 10, xác thực chéo được kích hoạt. Bạn có thể thử đếm kết quả phù hợp. Nếu Inliner-Outlier-Ratio quá cao, bạn có thể thấy cặp này là trùng lặp. Matching img1 and img2 using SIFT-detector and SIFT-descriptor Ví dụ: Những hình ảnh này tạo 180 điểm chính trong IMG1 và 198 trong IMG2. Các descriptors phù hợp là 163 trong đó chỉ có 3 là các ngoại lệ. Vì vậy, điều này mang lại một tỷ lệ thực sự tốt mà chỉ có thể có nghĩa là những hình ảnh này có thể trùng lặp.

[UPDATE-3] Tôi không hiểu tại sao bạn có thể khởi tạo MatOfKeypoints. I've read the API và có một nhà xây dựng công cộng. VÀ: Bạn có thể sử dụng Mat của hình ảnh bạn muốn phân tích. Điều này rất hay. =)

MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage); 

Để sử dụng Đối sánh BRUTEFORCE_SL2 Descriptor-Matcher khiến bạn cần khoảng cách euclide cho SURF hoặc SIFT.

+0

Bạn có thể thêm liên kết vào hướng dẫn không? –

+0

Tôi đã thêm một số tài liệu bổ sung. –

+0

Tôi đã chỉnh sửa câu hỏi của mình. –

1

Sử dụng cv2.absDiff để tính toán sự khác biệt giữa các hình ảnh và cv2.sumElems để nhận tổng của tất cả các điểm ảnh khác nhau.

Sau đó, tạo ra một ngưỡng mà theo đó bạn đánh giá xem có hai hình ảnh giống nhau hay không.

+0

Bạn có thể làm sáng tỏ? Tôi phải thiết lập một ngưỡng cho absDiff. Vì vậy, đó là sai lầm. Hoặc có lẽ bạn có thể cho tôi biết giá trị ngưỡng an toàn nhất là gì? –

+0

đầu tiên, xin lỗi bạn sẽ phải sử dụng cv.sum vì sumelems dường như chỉ là python. Thứ hai, bạn cần sự thay đổi cho giá trị trả về từ tổng! Bạn có thể bọc nó trong một phương thức trả về true hoặc false dựa trên giá trị trả về của tổng và ngưỡng của bạn. – sschrass

+0

Điều gì sẽ là ngưỡng tốt? –

0

Bạn có thể thử đoạn mã sau:

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 
} 

đây trong mã so sánh chức năng sẽ so sánh hai hình ảnh và sau đó nếu có có dis giống nhau giữa các hình ảnh sau đó sau đó giá trị ma trận đặc biệt sẽ là 255 và tất cả các giá trị khác sẽ bằng không.Sau đó, bạn có thể đếm số giá trị khác 0 để xác định xem các hình ảnh có bằng nhau hay không. Điều này sẽ chỉ hoạt động với hình ảnh chính xác.

Nếu bạn muốn so sánh hình ảnh bỏ qua các hiệu ứng ánh sáng, tôi đề nghị bạn tạo hình ảnh cạnh trước (Sử dụng chức năng bất thường của OpenCV) và sau đó so sánh hình ảnh.

Hy vọng câu trả lời này sẽ giúp bạn !!

Các vấn đề liên quan