create bmp image of sine wave - matlab

I would like to create bitmap for any sine grating. How could I accomplish this.
I am doing that:
n = 64;
[X,Y] = meshgrid(linspace(-2*pi,2*pi,n));
sinewave2D=sin(5*X);
plot(sinewave2D(1,:))
imagesc(sinewave2D)
imwrite(sinewave2D,'sine.bmp')
imshow('sine.bmp')
But "sinewave2D" has negative values and bmp accepts values between 0-255 so how can I accomplish that and have my gratings that I need.

It sounds as though the problem is how to deal with negative numbers.
As the programmer, this is your choice!
One method would be to normalize your sine wave to fit in the output range, as follows:
% shift digital counts so the minimum is at zero
sinewave2D = sinewave2D - min(sinewave2D(:);
% scale digital counts so the maximum is at 255
sinewave2D = sinewave2D / max(sinewave2D(:) * 255;
% then, write the image
imwrite(uint8(sindwave2D), 'sine.bmp');
The problem with this method, of course, is if the dynamic range of the sine wave changes, these changes will not be reflected in the output image! It also centers zero at a nonzero digital count, so zero will appear gray in the bitmap.

Related

Sampling an image

I have a 2D image G(m,n).
G is constructed by first acquiring k-space values and then inverse Fourier transforming.
The k-space consist m*n number of complex values.
What is meant by acquiring only 1/q of this amount (from m*n)? (q is a positive number)
In a scheme I will keep only 1/q th of the original k-space values.
Other elements 0f the original k space will make to zero/one.
Thank you.
Discarding a Fraction of Least Significant Frequency Components
One method is to use the fft2() function to convert the image to the frequency domain and delete the least significant frequency components based on their magnitudes. To find the least significant values the sort() function is used and the corresponding indices are returned. We can set the specific indices corresponding to the lowest frequency components to zero using matrix-indexing. You've pretty much described what has to be done above, but to provide more context:
• 1/q frequency components must remain.
• 1 - (1/q) frequency components must be set to zero/deleted.
%Grabbing a built-in test image%
Image = imread("peppers.png");
%Converting to grayscale if colour%
if size(Image,3) == 3
Image = rgb2gray(Image);
end
%Converting to frequency domain%
Frequency_Domain = fft2(Image);
%Sorting the the frequency domain values from greatest to least magnitude%
[Sorted_Coefficients,Sort_Indices] = sort(reshape(abs(Frequency_Domain),[numel(Frequency_Domain) 1]),'descend');
%Evaluating the number of coefficients to delete%
Number_Of_Coefficients = length(Sort_Indices);
q = 40;
Preserved_Fraction = 1/q;
Number_Of_Coefficients_To_Keep = round(Preserved_Fraction*Number_Of_Coefficients);
%Finding out which values to deleted based on the indices corresponding to the sorted array%
Delete_Indices = Sort_Indices(Number_Of_Coefficients_To_Keep+1:end);
Frequency_Domain(Delete_Indices) = 0;
%Evaluating how many frequency components were deleted%
Number_Of_Deleted_Frequency_Components = numel(Delete_Indices);
fprintf("Deleted %d frequency coefficients\n",Number_Of_Deleted_Frequency_Components);
%Converting the image back to the spatial domain%
G = uint8(ifft2(Frequency_Domain));
subplot(1,2,1); imshow(Image);
title("Original Image");
subplot(1,2,2); imshow(G);
title("Frequency Sampled Image");
disp(1 - (numel(Delete_Indices)/numel(Frequency_Domain)));

How to squeeze a time domain signal (to increase its frequency) in MATLAB?

I have a 1D signal of length 1x48 as follows:
h = [-0.00265429202364732 0.00114381559623147 0.00908984174155875 0.0183092424104111 0.0211504546133937 0.00770487019300306 -0.0267214048940936 -0.0720838840492711 -0.0997128821116885 -0.0725675276244839 0.0291024753407948 0.179241574214812 0.298171242995671 0.284570146378536 0.0817474628244779 -0.259613052052673 -0.574126734090367 -0.656991438427717 -0.392367536944054 0.145508194624853 0.699248579096810 0.960789439152323 0.757486942825664 0.170755448210657 -0.498796897953831 -0.904761150789826 -0.856496441492131 -0.419554007897496 0.143113035135791 0.539681841427904 0.612572904069275 0.398909459502485 0.0701631492551362 -0.189524355981899 -0.282109382620421 -0.220926595018094 -0.0887181885881753 0.0277116422165095 0.0824062595946282 0.0772777428539982 0.0415608034306098 0.00566535573566328 -0.0142417524165823 -0.0174044104259903 -0.0112752491506654 -0.00370981479490947 0.00105712046376533 0.00248943884050455];
I need to somehow squeeze this signal to increase its frequency.
Thanks to "rayryeng", please see the following plot. The green one (squeezed one) is obviously a kind of downsampled version of the blue one. Let's say we have the blue signal saved as an image. Open that image in paint or photoshop etc. Now grab the side and squeeze it by mouse (horizontally). You can see that the nature and shape of the squeezed one is as like as the original one. I want to have that kind of squeezed signal. Here in the picture below, amplitude is changed. It shouldn't. If you squeeze the blue one in paint or photoshop the amplitude never changes.
Thank you.
If you squeeze the signal maintaining the sample period you lose accuracy. That's why the amplitude changes. The squeezing works by averaging neighbouring samples. Consider for example the original peak sample. Since it is averaged with some lower-value samples, the squeezed signal has smaller peaks.
It would be better to do the opposite, i.e "enlarge" the signal horizontally by a factor r, and consider that your new sample period is r times smaller (finer) than before. So the original signal is now sampled more finely, and the squeezed signal has the same accuracy as the original one.
For that you can use resample:
h2 = resample(h,5,2); %// resample factor in this example: 5/2
plot(h, 'b');
hold on
plot(h2, 'r');
I'm going to interpret "squeezing" as representing the signal with fewer points, but maintaining the same pitch.
As such, you could use some sort of interpolation to do so. What you can do is specify values from 1 up to the length of your signal as control points and the values of h as the output values. Next, you can specify a reduced number of points but still maintaining a linearly increasing range from 1 up to 48 but have exactly this many points that span this range. We can use linspace to help us do this. For the interpolation, we can use interp1. Let's choose 'spline' interpolation to have some smoothing in between each keypoint that is produced in the final result.
In other words, try something like this:
num_points_reduced = 20;
h = [-0.00265429202364732 0.00114381559623147 0.00908984174155875 0.0183092424104111 0.0211504546133937 0.00770487019300306 -0.0267214048940936 -0.0720838840492711 -0.0997128821116885 -0.0725675276244839 0.0291024753407948 0.179241574214812 0.298171242995671 0.284570146378536 0.0817474628244779 -0.259613052052673 -0.574126734090367 -0.656991438427717 -0.392367536944054 0.145508194624853 0.699248579096810 0.960789439152323 0.757486942825664 0.170755448210657 -0.498796897953831 -0.904761150789826 -0.856496441492131 -0.419554007897496 0.143113035135791 0.539681841427904 0.612572904069275 0.398909459502485 0.0701631492551362 -0.189524355981899 -0.282109382620421 -0.220926595018094 -0.0887181885881753 0.0277116422165095 0.0824062595946282 0.0772777428539982 0.0415608034306098 0.00566535573566328 -0.0142417524165823 -0.0174044104259903 -0.0112752491506654 -0.00370981479490947 0.00105712046376533 0.00248943884050455];
x = 1:numel(h);
y = linspace(1,numel(h),num_points_reduced);
h_reduced = interp1(x, h, y, 'spline');
If we plot the original signal as well as the result, this is what it would look like:
plot(1:numel(x), h, 1:num_points_reduced, h_reduced);
grid;

Find the height and length of waves in noisy data

My goal is to find the maximum values of wave heights and wave lengths.
dwcL01 though dwcL10 is arrays of <3001x2 double> with output from a numerical wave model.
Part of my script:
%% Plotting results from SWASH
% Examination of phase velocity on deep water with different number of layers
% Wave height 3 meters, wave peroid 8 sec on a depth of 30 meters
clear all; close all; clc;
T=8;
L0=1.56*T^2;
%% Loading results tabels.
load dwcL01.tbl; load dwcL02.tbl; load dwcL03.tbl; load dwcL04.tbl;
load dwcL05.tbl; load dwcL06.tbl; load dwcL07.tbl; load dwcL08.tbl;
load dwcL09.tbl; load dwcL10.tbl;
M(:,:,1) = dwcL01; M(:,:,2) = dwcL02; M(:,:,3) = dwcL03; M(:,:,4) = dwcL04;
M(:,:,5) = dwcL05; M(:,:,6) = dwcL06; M(:,:,7) = dwcL07; M(:,:,8) = dwcL08;
M(:,:,9) = dwcL09; M(:,:,10) = dwcL10;
%% Finding position of wave crest using diff and sign.
for i=1:10
Tp(:,1,i) = diff(sign(diff([M(1,2,i);M(:,2,i)]))) < 0;
Wc(:,:,i) = M(Tp,:,i);
L(:,i) = diff(Wc(:,1,i))
end
This works fine for finding the maximum values, if the data is "smooth". The following image shows a section of my data. I get all peaks, when I only need the one around x = 40. How do I filter so I only get the "real" wave crests. The solution needs to be general so that it still works if I change the domain size, wave height or wave period.
If you're basically trying to fit this curve of data to a sine wave, have you considered performing Fourier analysis (FFT in Matlab), then checking the magnitude of that fundamental frequency? The frequency will tell you the wave spacing, and the magnitude the height, and when used over multiple periods will find an average.
See the Matlab help page for an example of the usage
but the basic gist is:
y = [...] %vector of wave data points
N=length(y); %Make sure this is an even number
Y = fft(y); %Convert into frequency domain
figure;
plot(y(1:N)); %Plot original wave data
figure;
plot(abs(Y(1:N/2))./N); %Plot only the lower half of frequencies to hide aliasing
I have one more solution that might work for you. It involves computing the 2nd-order derivative using a 5-point central difference instead of the 2-point finite differences. When using diff twice you are performing two first-order derivatives consecutively (finite 2-point differences) which are very susceptible to noise/oscillations. The advantage of using a higher-order approximation is that the neighboring points help filter out the small oscillations, and this may work for your case.
Let f(:) = squeeze(M(:,2,i)) be the array of data points, and h is the uniform spacing distance between the points:
%Better approximation of the 2nd derivative using neighboring points:
for j=3:length(f)-2
Tp(j,i) = (-f(j-2) + 16*f(j-1) - 30*f(j) + 16*f(j+1) - f(j+2))/(12*h^2);
end
Note that since this 2nd-order derivative requires the 2 neighboring points to the left and right, that the range of the loop must start at the 3rd index and end 2 short of the array length.

how to apply Fourier Transform on image using matlab

I have a problem, which is how it is applied Fourier Transform (ftt) on the image (or how enhance image used Fourier Transform)
when i run my program
the input was fingerprint image
the output was white image
the problem is the output should be fingerprint image after enhance used Fourier Transform not white image
F=fft2( I );
factor=abs(F).^F;
block =ifft2(factor);
R= fftshift(block);
I hope finding some help
The exponentiation of F.^F seems to be a big number, so it is above the upper value and matlab slice it to be the upper value.
% Calculating fft2
fft2im = fft2(double(im));
% Taking the spectrum with log scaling
fft2im = log(1+(abs(fft2im)));
% Putting DC in the middle:
spectrum = fftshift(fft2im);
% finding maximum in spectrum:
maximum = max(max(spectrum));
% scaling maximum to 255 and minimum to 0:
spectrum = 255*spectrum/maximum;
% Casting to uint8 to be able to display:
spectrum = uint8(spectrum);
imshow(spectrum);

Matlab - Signal Noise Removal

I have a vector of data, which contains integers in the range -20 20.
Bellow is a plot with the values:
This is a sample of 96 elements from the vector data. The majority of the elements are situated in the interval -2, 2, as can be seen from the above plot.
I want to eliminate the noise from the data. I want to eliminate the low amplitude peaks, and keep the high amplitude peak, namely, peaks like the one at index 74.
Basically, I just want to increase the contrast between the high amplitude peaks and low amplitude peaks, and if it would be possible to eliminate the low amplitude peaks.
Could you please suggest me a way of doing this?
I have tried mapstd function, but the problem is that it also normalizes that high amplitude peak.
I was thinking at using the wavelet transform toolbox, but I don't know exact how to reconstruct the data from the wavelet decomposition coefficients.
Can you recommend me a way of doing this?
One approach to detect outliers is to use the three standard deviation rule. An example:
%# some random data resembling yours
x = randn(100,1);
x(75) = -14;
subplot(211), plot(x)
%# tone down the noisy points
mu = mean(x); sd = std(x); Z = 3;
idx = ( abs(x-mu) > Z*sd ); %# outliers
x(idx) = Z*sd .* sign(x(idx)); %# cap values at 3*STD(X)
subplot(212), plot(x)
EDIT:
It seems I misunderstood the goal here. If you want to do the opposite, maybe something like this instead:
%# some random data resembling yours
x = randn(100,1);
x(75) = -14; x(25) = 20;
subplot(211), plot(x)
%# zero out everything but the high peaks
mu = mean(x); sd = std(x); Z = 3;
x( abs(x-mu) < Z*sd ) = 0;
subplot(212), plot(x)
If it's for demonstrative purposes only, and you're not actually going to be using these scaled values for anything, I sometimes like to increase contrast in the following way:
% your data is in variable 'a'
plot(a.*abs(a)/max(abs(a)))
edit: since we're posting images, here's mine (before/after):
You might try a split window filter. If x is your current sample, the filter would look something like:
k = [L L L L L L 0 0 0 x 0 0 0 R R R R R R]
For each sample x, you average a band of surrounding samples on the left (L) and a band of surrounding samples on the right. If your samples are positive and negative (as yours are) you should take the abs. value first. You then divide the sample x by the average value of these surrounding samples.
y[n] = x[n] / mean(abs(x([L R])))
Each time you do this the peaks are accentuated and the noise is flattened. You can do more than one pass to increase the effect. It is somewhat sensitive to the selection of the widths of these bands, but can work. For example:
Two passes:
What you actually need is some kind of compression to scale your data, that is: values between -2 and 2 are scale by a certain factor and everything else is scaled by another factor. A crude way to accomplish such a thing, is by putting all small values to zero, i.e.
x = randn(1,100)/2; x(50) = 20; x(25) = -15; % just generating some data
threshold = 2;
smallValues = (abs(x) <= threshold);
y = x;
y(smallValues) = 0;
figure;
plot(x,'DisplayName','x'); hold on;
plot(y,'r','DisplayName','y');
legend show;
Please do not that this is a very nonlinear operation (e.g. when you have wanted peaks valued at 2.1 and 1.9, they will produce very different behavior: one will be removed, the other will be kept). So for displaying, this might be all you need, for further processing it might depend on what you are trying to do.
To eliminate the low amplitude peaks, you're going to equate all the low amplitude signal to noise and ignore.
If you have any apriori knowledge, just use it.
if your signal is a, then
a(abs(a)<X) = 0
where X is the max expected size of your noise.
If you want to get fancy, and find this "on the fly" then, use kmeans of 3. It's in the statistics toolbox, here:
http://www.mathworks.com/help/toolbox/stats/kmeans.html
Alternatively, you can use Otsu's method on the absolute values of the data, and use the sign back.
Note, these and every other technique I've seen on this thread is assuming you are doing post processing. If you are doing this processing in real time, things will have to change.