C# - Image comparison (fast one) - c#

At the moment I've got an database with over 100.000 images, they ain't the same size or anything like that but I want to make the following for my compagny:
I insert/upload an image and the system returns the image which is most likely the same. I don't know what algorithm to use but it needs to be fast. I can pre-process all the other images and put some info in the database which I use for the comparison.
Now what I want to know what the fastest way is to compare the images (with a good chance of being the same image). And what data I should save into the database (I could probably figure this one out myself if I got the algorithm).
It shouldn't take more then 5 minutes to compare the uploaded image to all the images in the database.
Thanks in advance!
Julian
Look at www.tineye.com, they have some kind of algorithm that I'm looking for. Guessing they use a very complex one, I just need one that does same thing but with lesser rate of succes.

The way I would do it is I'd generate a really small (say.. 1/50 of the original image size) image from every image you're comparing against, and store the thumbnail image path along with the original size in the database. I'd keep the thumbnails as uncompressed bmp's for speed and loss-free-ness (I just made that word up!), since they're so small anyway.
To compare your new image against the other ones, shrink it down by the same amount and compare it against the others pixel by pixel, with a certain threshold (say.. 10% difference from the original).
If it passes this test, you can do a full blown pixel by pixel compare against the original image.
edit: I just want to mention that I went down the probabilistic way before too. It worked OK, but building the meta data for the images took forever, and there were a lot of false positives. Instinctively, I think that calculating local averages for each grid rectangle of your image (which is what shrinking your image down does) would give similar, if not better results.

The best way for comparison is convert image to gray scale format and compare intensity of gray color. Its the fastest way used in real-time systems.
Also if you want to achieve higher qaullity and use colored images - use CIE 1994 or CIE 2000 as color difference formula

Related

Simple algorithm to crop empty borders from an image by code?

Currently I'm seeking for a rather fast and reasonably accurate algorithm in C#/.NET to do these steps in code:
Load an image into memory.
Starting from the color at position (0,0), find the unoccupied space.
Crop away this unnecessary space.
I've illustrated what I want to achieve:
What I can imagine is to get the color of the pixel at (0,0) and then do some unsafe line-by-line/column-by-column walking through all pixels until I meet a pixel with another color, then cut away the border.
I just fear that this is really really slow.
So my question is:
Are you aware of any quick algorithmns (ideally without any 3rd party libraries) to cut away "empty" borders from an in-memory image/bitmap?
Side-note: The algorithm should be "reasonable accurate", not 100% accurate. Some tolerance like one line too much or too few cropped would be way OK.
Addition 1:
I've just finished implementing my brute force algorithm in the simplest possible manner. See the code over at Pastebin.com.
If you know your image is centered, you might try walking diagonally ( ie (0,0), (1,1), ...(n,n) ) until you have a hit, then backtrack one line at a time checking until you find an "empty" line (in each dimension). For the image you posted, it would cut a lot of comparisons.
You should be able to do that from 2 opposing corners concurrently to get some multi-core action.
Of course, hopefully you dont it the pathelogical case of 1 pixel wide line in the center of the image :) Or the doubly pathological case of disconnected objects in your image such that the whole image is centered, but nothing crosses the diagonal.
One improvement you could make is to give your "hit color" some tolerance (adjustable maybe?)
The algorithm you are suggesting is a brute force algorithm and will work all the time for all type of images.
but for special cases like, subject image is centered and is a continuous blob of colors (as you have displayed in your example), binary sort kind of algorithm can be applied.
start from center line (0,length/2) and start in one direction at a time, examine the lines as we do in binary search.
do it for all the sides.
this will reduce complexity to log n to the base 2
For starters, your current algorithm is basically the best possible.
If you want it to run faster, you could code it in c++. This tends to be more efficient than managed unsafe code.
If you stay in c#, you can parallel extensions to run it on multiple cores. That wont reduce the load on the machine but it will reduce the latency, if any.
If you happen to have a precomputed thumbnail for the image, you can apply your algo on the thumbnail first to get a rough idea.
First, you can convert your bitmap to a byte[] using LockBits(), this will be much faster than GetPixel() and won't require you to go unsafe.
As long as you don't naively search the whole image and instead search one side at a time, you nailed the algorithm 95%. Just make you are not searching already cropped pixels, as this might actually make the algorithm worse than the naive one if you have two adjacent edges that crop a lot.
A binary search can improve a tiny bit, but it's not that significant as it will maybe save you a line of search for each direction in the best case scenario.
Although i prefer the answer of Tarang, i'd like to give some hints on how to 'isolate' objects in an image by refering to a given foregroundcolor and backgroundcolor, which is called 'segmentation' and used when working in the field of 'optical inspection', where an image is not just cropped to some detected object but objects are counted and also measured, things you can measure on an object is area, contour, diameter etc..
First of all, usually you'll start really to walk through your image beginning at x/y coordinates 0,0 and walk from left to right and top to bottom until you'll find a pixel that has another value as the background. The sensitivity of the segmentation is given by defining the grayscale value of the background as well as the grayscale value of the foreground. You possibly will walk through the image as said, by coordinates, but from the programs view you'll just walk through an array of pixels. That means you'll have to deal with the formula that calculates the x/y coordinate to the pixel's index in the pixel array. This formula sure needs width and height of the image.
For your concern of cropping, i think when you've found the so called 'pivot point' of your foreground object, you'll usually walk along the found object by using a formula that detects neighbor pixels of the same foregeground value. If there is only one object to detect as in your case, it's easy to store those pixels coordinates that are north-most, east-most, south-most and west-most. These 4 coordinates mark the rectangle your object fits in. With this information you can calculate the new images (cropped image) width and height.

Bitmaps in WPF - give watermarking effect and then recover images individually

I am working on a project where I need to play with two bitmaps. I am putting them in a grid one over the other with reduced opacity (to give a watermark effect).
I am rendering the grid to a bitmap using RenderTargetBitmap and saving the bitmap to a file.
Now my requirement is to load the rendered bitmap again and recover the original pictures separately. Is there any way to recover the original images again. I am not able to think any algorithm to implement this.
My aim is to give a watermarking effect and then recover the images individually.
No. The information is lost during "flattening" of the image.
You need to save both images and information about their properties (position, opacity) into single file. And restore it on load.
If your goal is to simulate watermarking and allow later 'dewatermarking', then assuming that you have your watermarking bitmap present at decoding time, you probably can do that. Sure you cannot use your initial approach - just simple merging of two layers is not reversible.
You need to use some reversible transformation, like rotating source image pixel RGB values vector, using watermark image pixel RGB values as parameters. While dewatermarking you just use negative values from watermark image.
Well, RGB vector is not ideal - you can go out of RGB space while rotating it. Probably you can find color space (or some other transformation in RGB space), better suited to your goal.
(English is not my first or even second language, thereby I apologize if you can't understand my idea - just ask over.)
Why don't you try to make it two layers of bitmap?
i wonder if you can use TIFF format, where you can store multiple images. that way on display you can choose to show with/without watermark.

Algorithm to detect if a pixel is within a boundary

We're currently creating a simple application for image manipulation in Silverlight, and we've hit a bit of a snag. We want users to be able to select an area of an image (either by drawing a freehand line around their chosen area or by creating a polygon around it), and then be able to apply effects to the pixels within that selection.
Creating a selection of images is easy enough, but we want a really fast algorithm for deciding which pixels should be manipulated (ie. something to detect which pixels are within the user's selection).
We've thought of three possibilities so far, but we're sure that there must be a really efficient and quick way of doing this that's better than these.
1. Pixel by pixel.
We just go through every pixel in an image and check whether it's within the user selection. Obviously this is far too slow!
2. Using a Line Crossing Algorithim.
The type of thing seen here.
3. Flood Fill.
Select the pixels along the path of the selection and then perform a flood fill within that selection. This might work fine.
This must a problem that's commonly solved, so we're guessing there's a ton more solutions that we've not even thought of.
What would you recommend?
Flood fill algorithm is a good choice.
Take a look at this implementation:
Queue-Linear Flood Fill: A Fast Flood Fill Algorithm
You should be able to use your polygon to create a clipping path. The mini-language for describing polygons for Silverlight is quiet well documented.
Alter the pixels on a copy of your image (all pixels is usually easy to modify than some pixels), then use the clipping path to render only the desired area of the changes back to the original image (probably using an extra buffer bitmap for the result).
Hope this helps. Just throwing the ideas out and see if any stick :)

Find image position inside a larger image

Basically I want to find the pixel location of a small image inside a large image.
I have searched for something similar to this but have had no luck.
It depends on how similar you want the result to match your query image. If you're trying to match corresponding parts of different photorealistic images, take a look at the Feature detection Wikipedia page. What you want to use depends on the transformation you expect one image to undergo to become the other.
That said, if you are looking for an exact pixel-by-pixel match, a brute-force search is probably bad. That can be O(m^2*n^2) for an m*m image used to search within an n*n image. Using better algorithms, it can be improved to O(n^2), linear in the number of pixels. Downsampling both images and doing a hierarchical kind of search might be a good approach.
You could probably use the AForge Framework to do something like this. It offers a variety of image processing tools. Possibly you could use their blob extraction to extracts blobs then compare those blobs to a stored image you have and see if they match.
If the images are pixel-by-pixel equal, you could start by searching for one pixel that has the same color as pixel (0,0) in the small image. Once found, compare each pixel in the area that would be covered by the small image. If there are no differences you found your position. Else start over by searching for the next pixel matching (0,0).
Booyer-Moore search sounds like a solution here if you treat your pixels as characters and are looking for an exact match. Much faster than per pixel searching as well.

How to identify/check blur image?

How can we identify that a given image is blur or how much percent is it blur in C#? Is there any API available for that? Or any algorithm that can be helpful in that?
Thanks!
You could perform a 2D-FFT and search the frequency coefficients for a value over a certain threshold (to elimate false-positives from rounding/edge errors). A blurred image will never have high frequency coefficients (large X/Y values in frequency-space).
If you want to compare with a certain blurring algorithm, run a single pixel through a 2D-FFT and check further images to see if they have frequency components outside the range of the reference FFT. This means you can use the same algorithm regardless of what type of blurring algorithm is used (box blur, gaussian, etc)
For a very specific problem (finding blurred photos shot to an ancient book), I set up this script, based on ImageMagick:
https://gist.github.com/888239
Given a blurred bitmap alone, you probably can't.
Given the original bitmap and the blurred bitmap you could compare the two pixel by pixel and use a simple difference to tell you how much it is blurred.
Given that I'm guessing you don't have the original image, it might be worthing looking at performing some kind of edge detection on the blurred image.
This Paper suggests a method using Harr Wavelet Transform, but as other posters have said, this is a fairly complex subject.
Although, I am posting this answer after 8-9 years after asking the question. At that time, I resolved this problem by applying blur on image and then comparing with the original one.
The idea is, when we apply blur on a non-blurry image and then compare them, the difference in images is very high. But when we apply blur on a blurry image, the difference in images is almost 10%.
In this way, we resolved our problem of identifying blur images and the results were quite good.
Results were published in following conference paper:
Creating digital life stories through activity recognition with image filtering (2010)
Err ... do you have the original image? What you ask is not a simple thing to do, though ... if its even possible
This is just a bit of a random though but you might be able to do it by fourier transforming the "blurred" and the original image and seeing if you can get something that has a very similar frequency profiles by progressively low pass filtering the original image in the frequency domain. Testing for "similarity" would be fairly complex in itself though.

Categories

Resources