I played around in java's JMF for a day and soon had a small app that recorded one still frame per second. Now I could review the recorded images when getting home at the end of the day. Hovever, 1 frame per second equates to 36000 images over the 10 hour work day that I'm not at home! I don't really want to record motion video - yet. I'm still happy with working with images,.. albeit a lot of them. So now I've got a haystack of images, and presumably somewhere inside of them is the needle of interesting footage.
I searched pretty hard for a Java image comparison class or library and could not find anything. Just a whole bunch of forum posts declaring how advanced the topic can get. So sleeves up, I created my own rudimentary ImageCompare class. (Download Link). It's not bulletproof, and its not lightspeed, but for my purposes it's done the job perfectly.
The class breaks up the images into smaller regions and compares the brightness of each corresponding region. If any particular pair of regions are vastly different then something must have changed in that part of the image.
How to use:
// Create a compare object specifying the 2 images for comparison.
ImageCompare ic = new ImageCompare("c:\\test1.jpg", "c:\\test2.jpg");
// Set the comparison parameters.
// (num vertical regions, num horizontal regions, sensitivity, stabilizer)
ic.setParameters(8, 6, 5, 10);
// Display some indication of the differences in the image.
ic.setDebugMode(2);
// Compare.
ic.compare();
// Display if these images are considered a match according to our parameters.
System.out.println("Match: " + ic.match());
// If its not a match then write a file to show changed regions.
if (!ic.match()) saveJPG(ic.getChangeIndicator(), "c:\\changes.jpg");
The setParameters() accepts four parameters.
- The number of vertical columns in the comparison grid.
- The number of horizontal rows in the comparison grid.
- A threshold value. If the difference in brightness exceeds this then the region is considered different.
- A stabilization factor. In future I will calculate this automatically since it is proportional to parameters 1 and 2.
After running compare(), match() will hold the result.
Example:
The above code was run on the following two images:


The console output looked like this:
|0,0,0,0,0,0,1,0|... and the image output (changes.jpg) looked like this:
|0,0,0,0,0,0,0,1|
|0,0,0,0,0,0,0,3|
|0,0,0,0,0,1,1,8|
|0,0,0,0,0,0,0,8|
|0,0,0,0,0,1,0,0|
Match: false

On my todo list:
- Provide an array/vector of changed regions, or number of changed regions.
- Heuristically determine a stabilizing factor, thus not having to specifying one.
- Allow for the input of area vectors before comparison for the purpose of excluding or only checking these areas.
- I'd also like to integrate this into a more real time solution that then exposes events and the like.
What you see here is a very alpha stage development. Take it and use it if you like, but do so at your own risk,.. or frustration. I'll try post some updates to this code as and when significant changes have been made.
Follow-up post: http://mindmeat.blogspot.com/2008/11/java-image-comparison.html
7 comments:
Ah, so your domestic worker (pictured in the photos obviously), snatched your blue china wall-piece. It's so hard to find good help these days.
Hi, I'm work around real time motion detection solution. If you are interested we work together lorenzo83@email.it. Good work!!
Here's a follow up post with some updates regarding the content of this article.
http://mindmeat.blogspot.com/2008/11/java-image-comparison.html
Hi Patrick
I was surfing in the net searching searching information about image processing and staff. While I was surfing I find your web http://mindmeat.blogspot.com/2008/07/java-image-comparison.html. I am working real time motion detection and I need some help with my project. Would you help me or give me some advices? Maybe I can also help you with some of your staff.
Thanks
Charles
Hi, i found your method useful for motion detect on mobile devices. I made just one modification:
Some times you do not need to save shots where difference is result of candlelight changes, just because - imho there is no motion!
To solve this problem add next rows to public void compare():
//Calculating average brightness for source images
int sDiff = getAverageBrightness(img2) - getAverageBrightness(img1))/(comparex * comparey);
// Calcilatting verage brightness for blocks (in cicle)
int diff = Math.abs(b1 - b2 + sDiff);
Enjoy!
Hi,i am an student from chennai.i am currently doing a project on finerprint recognition.i found your code really useful.thank you.but i would ike to know on what algorithm the code is based on.thank you
@niranjini: i love the question. but i don't know the answer. i really just sat down one day, downloaded jmf, and started dismantling pictures from my webcam.
i did refer to the site http://homepages.inf.ed.ac.uk/rbf/HIPR2/linedet.htm for my line detection. otherwise, and there might be names for the techniques, i just trialed and erred my way through until i had some reasonable data to work with.
btw: my follow up post at: http://mindmeat.blogspot.com/2008/11/java-image-comparison.html offers some improvements.
Post a Comment