I am trying to develop an application for image processing.
Here is my complete code in DotNetFiddle.
I have tested my application with different images from the Internet:
Cameraman is GIF.
Baboon is PNG.
Butterfly is PNG.
Pheasant is JPG.
Butterfly and Pheasant are re-sized to 300x300.
The following two images show correct Fourier and Inverse Fourier spectrum:
The following two images do not show the expected outcome:
What could be the reason?
Are there any problem with the later two images?
Do we need to use images of specific quality to test Image-processing applications?
The code you linked to is a radix-2 FFT implementation which would work for any image with sizes that are exact powers of 2.
Incidentally, the Cameraman image is 256 x 256 (powers of 2) and the Baboon image is 512 x 512 (again powers of 2). The other two images, being resized to 300 x 300 are not powers of 2. After resizing those images to an exact power of 2 (for example 256 or 512), the output of FrequencyPlot for the brightness component of the last two images should look somewhat like the following:
butterfly
pheasant
A common workaround for images of other sizes is to pad the image to sizes that are exact powers of 2. Otherwise, if you must process arbitrary sized images, you should consider other 2D discrete Fourier transform (DFT) algorithms or libraries which will often support sizes that are the product of small primes.
Note that for the purpose of validating your output, you also have option to use the direct DFT formula (though you should not expect the same performance).
I got not time to dig through your code. Like I said in my comments you should focus on the difference between those images.
There is no reason why you should not be able to calculate the FFT of one image and fail for another. Unless you have some problem in your code that can't handle some difference between those images. If you can display them you should be able to process them.
So the first thing that catches my eye is that both images you succeed with have even dimensions while the images your algorithm produces garbage for have at least one odd dimension. I won't look into it any further as from experience I'm pretty confident that this causes your issue.
So befor you do anything else:
Take one of those images that work fine, remove one line or row and see if you get a good result. Then fix your code.
Related
I have a data source that provides many (4096) double values in an array. These are measured with high resolution and are the result of a FFT. For visualisation purposes, they need to be reduced. (Reapplying the FFT on the raw signal is not possible here.) I could simply average each n samples and have a resulting array of length / n values. To allow more flexible selection of the number of resulting values, I need interpolation, though.
I've looked up some basic information about this on Wikipedia. I am already familiar with 2D downsampling/interpolation from a user prespective in raster image editors. Now I need this in 1D in C# code. Think of it as changing (reducing) the raster image size of a 1D barcode image, or resampling an audio wave file.
One library I've found recommended is Math.NET Numerics. This is already used for other tasks in my application, so I could easily use that. There's the CubicSpline class in there but I have no idea how to use it.
Q: What would be an approach to reduce the number of samples in a double[] to an arbitrary number using interpolation?
I'm not interested in finding a single double value between two others. I need to combine multiple source values into each a single output value, while not losing any information (single frequency bins with an extreme level) at the boundaries of the groups, and without aliasing effects or rounding because of different group sizes if the numbers aren't divisible.
Maybe the use of bitmap image functions and a 1*n bitmap size is a good solution instead of dealing with the math directly? This would involve a lot of data conversion, though, which reduces performance and probably also precision. Or some library from the autio processing field?
I have a very long PDF file (58x500 inches). The goal is to divide one large vector pdf file to a certain percentage. For example %25 = 125 inches in height while the width stay the same. So one large pdf will be divided into 4 pages.
ImageMagick was able to do this but it crashes if I changed the dpi to 300. Is it possible to do this with Ghostscript? I am currenlty using Ghostscipt.net and C#.
Can someone point me to the right direction?
I mentioned netvips in a comment -- it will do progressive PDF rendering (it uses poppler rather than ghostscript), so you can load the whole page at 300 DPI and write it out as four huge raster files.
I don't actually have C# on this laptop, but here's what you'd do in Python. The C# code would be almost the same.
import sys
import pyvips
image = pyvips.Image.image_new_from_file(sys.argv[1], dpi=300, access="sequential")
n_pages = 4
for n in range(n_pages):
filename = f"page-{n}.tif"
print(f"rendering {filename} ...")
y = int(n * image.height / n_pages)
page_height = int(min(image.height / n_pages, image.height - y))
page = image.crop(0, y, image.width, page_height)
page.write_to_file(filename)
The access="sequential" puts libvips into sequential mode -- pixels will only be computed on demand from the final write operation. You should be able to render your 200,000 pixel high image using only a modest amount of memory.
You don't need to use tif of course, jpg might be more sensible, and if this is for printing, few people will notice.
As everyone said, it would be better to keep as a vector format for as long as you can.
See this previous answer of mine. It demonstrates how to render a portion of the original input file to a bitmap. I'd suggest you use the exact same technique, but use the pdfwrite device instead of the png16m device, so that you get a PDF file as the output, thus maintaining the vector nature of the input.
So to paraphrase the answer there, this:
gs -sDEVICEWIDTHPOINTS=72 -dDEVICEHEIGHTPOINTS=144 -dFIXEDMEDIA -r300 -sDEVICE=pdfwrite -o out.pdf -c "<</PageOffset [-180 -108]>> setpagedevice" -f input.pdf
Will create a 'window' 1 inch wide by 2 inches high, starting 2.5 inches from the left of the original and 1.5 inches up from the bottom. It then runs the input and every position of it which lies within that window is preserved, everything which lies outside it is dropped.
You'd need to do that multiple times, once for each section you want.
I should mention that Ghostscript itself is perfectly capable of rendering the entire PDF file to a document. It uses the same kind of display list approach to very large output files where it creates a (simplified) representation of the original input, and runs that description multiple times. Each time it renders one horizontal band of the final output, then moves down to the next band and so on.
In my opinion, it's likely that the limiting factor of 300 dpi in your original experience is ImageMagick rather than Ghostscript, I know that Ghostscript is able to render input which is several metres in each dimension at 1200 dpi or more, though it does, of course, take a long time to produce the gigabytes of data.
I saw a lot a topic about this, I understood the theory but I'm not able to code this.
I have some pictures and I want to determine if they are blurred or not. I found a library (aforge.dll) and I used it to compte a FFT for an image.
As an example, there is two images i'm working on :
My code is in c# :
public Bitmap PerformFFT(Bitmap Picture)
{
//Loade Image
ComplexImage output = ComplexImage.FromBitmap(Picture);
// Perform FFT
output.ForwardFourierTransform();
// return image
return = output.ToBitmap();
}
How can I determine if the image is blurred ? I am not very comfortable with the theory, I need concret example. I saw this post, but I have no idea how to do that.
EDIT:
I'll clarify my question. When I have a 2D array of complex ComplexImage output (image FFT), what is the C# code (or pseudo code) I can use to determine if image is blurred ?
The concept of "blurred" is subjective. How much power at high frequencies indicates it's not blurry? Note that a blurry image of a complex scene has more power at high frequencies than a sharp image of a very simple scene. For example a sharp picture of a completely uniform scene has no high frequencies whatsoever. Thus it is impossible to define a unique blurriness measure.
What is possible is to compare two images of the same scene, and determine which one is more blurry (or identically, which one is sharper). This is what is used in automatic focussing. I don't know how exactly what process commercial cameras use, but in microscopy, images are taken at a series of focal depths, and compared.
One of the classical comparison methods doesn't involve Fourier transforms at all. One computes the local variance (for each pixel, take a small window around it and compute the variance for those values), and averages it across the image. The image with the highest variance has the best focus.
Comparing high vs low frequencies as in MBo's answer would be comparable to computing the Laplace filtered image, and averaging its absolute values (because it can return negative values). The Laplace filter is a high-pass filter, meaning that low frequencies are removed. Since the power in the high frequencies gives a relative measure of sharpness, this statistic does too (again relative, it is to be compared only to images of the same scene, taken under identical circumstances).
Blurred image has FFT result with smaller magnitude in high-frequency regions. Array elements with low indexes (near Result[0][0]) represent low-frequency region.
So divide resulting array by some criteria, sum magnitudes in both regions and compare them. For example, select a quarter of result array (of size M) with index<M/2 and indexy<M/2
For series of more and more blurred image (for the same initial image) you should see higher and higher ratio Sum(Low)/Sum(High)
Result is square array NxN. It has central symmetry (F(x,y)=F(-x,-y) because source is pure real), so it is enough to treat top half of array with y<N/2.
Low-frequency components are located near top-left and top-right corners of array (smallest values of y, smallest and highest values of x). So sum magnitudes of array elements in ranges
for y in range 0..N/2
for x in range 0..N
amp = magnitude(y,x)
if (y<N/4) and ((x<N/4)or (x>=3*N/4))
low = low + amp
else
high = high + amp
Note that your picture shows jumbled array pieces - this is standard practice to show zero component in the center.
I'm working on a scientific imaging software for my university, and I've encountered a major problem. Scientific camera (Apogee Alta U57) at my lab provides images as 16bpp array - it's 0-65535 values per pixel! We want to keep this range, but in fact we can't display them on monitor (0-255 grayscale range). So I found a way to resolve this problem - simply to make use of colors, and to display whole image as a heatmap (from black, blue, through green and red, to pure white).
I mean something like this - Example heatmap image I want to achieve
My only question is: How to efficiently convert 16bpp array of pixel values to complete heatmap bitmap in c#? Are there any libraries for doing that? If not, how do I achieve that using .NET resources?
My idea was to create function that maps 65536 values into (255 R, 255G, 255B), but it's a tough job - especially without using HSV model.
I would be much obliged for any help provided!
Your question consist of several parts:
reading in the 16 bit pixel data values
mapping them to 24 bit rgb colors
writing them out to an image file
I'll skip part one and three and give you a few ideas about part 2.
It is in fact harder than it seems. A unique mapping that doesn't lose any information is simple, in fact trivial, just a little bit shifting will do.
But you also want the result to work visually, meaning not so much is should be visually appealing but should make sense to a human eye. so we need a mapping that has a credible yet large enough gradient.
For this you should experiment a little. I suggest to make use of the LinearGradientBrush, as I show here. Have a look at the interpolateColors function! It uses only 6 colors in the example, way to few for your case!
You should pick many more; you may need to go through the color space in a spiral..
The trick for you will be to choose both nice and enough stop colors to create a 64k large set of unique colors, best going from blueish to reddish..
You will need to test the result for uniqueness; in fact you may want to create a pair of Dictionary and Dictionary for the mappings..
How can I compare two images and determine if they are 100% similar, or only altered in color, or cropping?
Well, abstractly speaking, you need to define a similarity function, that compares two images. To determine if the images are "100% similar" (equal) you can do the following:
compare the sizes of the images
if the image sizes are the same simply subtract the pixels from each other
if ( sum( abs( pixel_1_i - pixel_2_j ) ) / num_pixels < threshold ) return true
For the case that images are differently colored, or cropped
apply an edge detector to both images
compute the cross-correlation (in the frequency domain, FFT)
find the highest peak
place the (smaller) edge map in the determined position
calculate the absolute error
if (error < threshold) return true
BTW: This approach will not work if your images are scaled or rotated.
Further Research:
cross-correlation: FFT (fast fourier transformation, link1, link2, FFT in C#), zero-padding (needed for the FFT if the input signals have different sizes)
edge detection: Sobel, Canny (these are very common image processing filters, they should be available in a C# library, just like the FFT)
The following is a fairly simplistic approach to the problem and won't work well with two different photographs of the same subject taken from slightly different angles, but would work if you had two copies of the same image that you wanted to verify.
The case of two identical images is straightforward - just loop through the pixel arrays subtracting on RGB value from the other. If the difference is less than a small tolerance then the pixel is identical. Thus as soon as you find a pixel difference greater than the tolerance you know that the images are different.
You could allow for a certain number or percentage of differences to allow for differences causes by compression artefacts.
To check for alterations in colour you could look at the HLS (Hue, Lightness and Saturation) values instead. If the pixels have the same L & S values but a different H value then it's just the colour that's different (I think).
Cropping is more difficult as you have to try to find the location of the smaller image in the larger one.
You can use object descriptors such as:
SIFT - http://en.wikipedia.org/wiki/Scale-invariant_feature_transform
SURF - http://en.wikipedia.org/wiki/SURF
Then compare images by using calculated descriptors. Those descriptors will enable you to deal with rotated, scaled and slightly changed images.
Also the descriptors consist of oriented gradients meaning that those descriptors are robust to illumination and color changes as well.
You can use Accord.NET (SURF implementation).