OpenCV image comparison in Android
You should understand that this is not a simple question and you have different concepts you could follow. I will only point out two solution without source-code.
- Histogram comparison: You could convert both images into grey-scale make a histogram in the range of [0,...,255]. Every pixel-value will be counted. Then use both histograms for comparison. If the distribution of pixel-intensities equals or is above some treshold (perhaps 90% of all pixels), you could consider this images as duplicates. BUT: This is one of the simplest solutions and it isn't stable if any picture has an equal distribution.
- Interest-Point-Detectors/-Descriptors: Take a look at SIFT/SURF image-detectors and descriptors. A detector will try to determine unique keypoits of intensities in an image. A descriptor will be computed at this location I(x,y). A normal matcher with a bruteforce-approach and euclidean distance can match these images using their descriptors. If an image is a duplicate the rate of given matches should very high. This solution is good to implement and there could be enough tutorials regarding this topic.
I'll hope this helps. Please ask if you have questions.
[UPDATE-1]
A C++-tutorial: http://morf.lv/modules.php?name=tutorials&lasit=2#.UR-ewKU3vCk
Some JavaCV-tutorials: http://code.google.com/p/javacv/w/list
[UPDATE-2]
Here is an example with SIFT-Detector and SIFT-Descriptor using default parameters. RANSAC-Threshold for homography is 65, reprojection-error (epsilon) is 10, cross-validation enabled. You could try to count the matched. If the Inliner-Outlier-Ratio is too high you could see this pair as duplicates.
For example: These images produce 180 keypoints in IMG1 and 198 in IMG2. The matched descriptors are 163 of which only 3 are outliers. So this gives a really good ratio which only could mean that these images could be duplicates.
[UPDATE-3]
I don't understand why you can initialize the MatOfKeypoints. I've read the API and there's a public constructor. AND: You can use the Mat of the image you want to analyse. This is very nice. =)
MatOfKeyPoint reference = new MatOfKeyPoint(matOfReferenceImage);
For Matching use a BRUTEFORCE_SL2 Descriptor-Matcher cause you will need the euclidean distance for SURF or SIFT.
OpenCV for ANDROID image compare
The best method for what you ask is using local features detectors like OpenCV's SIFT, SURF and ORB, for example.
You need at least one picture from the object you want to detect. Afterwards, those algorithms can compare that image with other images to see if they are similar enough.
Here is the Documentation for the algorithms.
- ORB and others:
http://docs.opencv.org/modules/features2d/doc/feature_detection_and_description.html
- SURF and SIFT ('nonfree'):
http://docs.opencv.org/modules/nonfree/doc/feature_detection.html
The way these algorithms work for that task is by selecting interesting points for each image, and compare them to see if they match. If several matches are found, it is most likely the images have the same object.
Tutorials (from Feature Detection and below):
http://docs.opencv.org/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.html
You can also find C++ samples related to this topic here (samples are also within OpenCV download package):
- eg. "matching_to_many_images.cpp"
- "video_homography.cpp"
http://code.opencv.org/projects/opencv/repository/revisions/master/show/samples/cpp
And Android Java samples here (unrelated but also helpful):
http://code.opencv.org/projects/opencv/repository/revisions/master/show/samples/android
Or Python samples which are actually the more updated ones for this topic (at the time this post was written):
http://code.opencv.org/projects/opencv/repository/revisions/master/show/samples/python2
As a final note, like @BDFun said in the comment, this is not trivial to do.
More - if you want an overview of OpenCV Feature detection and description, check this post.
Compare two Images in android using opencv
I figured it out.
Actually i have to make use of the function from the Core OpenCV. i.e.
Core.compare(src1, src2, dst, cmpop);
I was not aware about this core class.
best way to compare images for similarity in android
First off, let's correct you. Neither your OpenCV snippet not Android can directly compare if two images are "similar". They can compare if they are exactly the same. That's not the same thing. You'd have to decide if its good enough.
Secondly, OpenCV is overkill for this. If the two images are Bitmaps in memory, just loop over the byte arrays of the two files. If they're on disk, just compare the byte by byte data of the two files.
You said you "got the paths of all images, then converted to Bitmap". Yeah, that would take a ton of memory. Instead, if you want to compare all the files, do this:
val map = mutableMapOf()
fileNames.each {
val hash = hash_file(it)
if (map.contains(hash)) {
//In this case, the two file stored in it and map[hash] are the same
}
else {
map[hash] = it
}
}
Here hash_file is any well known hash function. MD5 would work fine.
Now if you actually want similarity- good luck, you're going to need to learn a lot of AI and machine learning to determine that. Or find someone who already has a model for an appropriate training set.
Related Topics
What Is the Android UI Thread Stack Size Limit and How to Overcome It
Communication Between Broadcastreceiver and Activity - Android
Creating a Dialogpreference from Xml
Swiperefreshlayout + Webview When Scroll Position Is at Top
Android/Eclipse Panic: Could Not Open
How to Implement Pagination in Android Listview
Change Shape Solid Color at Runtime Inside Drawable Xml Used as Background
Textbox Hidden Below Keyboard in Android Webview
Javamail API in Android Using Xoauth
Upload an Image Using Google Volley
Android: How to Create Fade-In/Fade-Out Sound Effects for Any Music File That My App Plays
Get Latitude and Longitude with Geocoder and Android Google Maps API V2
Android Studio: Default Project Directory
Communicating with Serial Usb Device Over Android