Repairing pixels. Median function help please - matlab

I need help debugging my median function under the if statement. I am getting an input error. Also if there is a simpler way to write the median function it will be greatly appreciated. I am writing this code to clean up the above image for a project. Thanks. Also, I am pretty new with MATLAB.
``clear
clc
format compact
filenameIN = uigetfile('.bmp','Picture');
noisyRGBarray = imread(filenameIN);
%figure(1)
%imshow(noisyRGBarray)
y = noisyRGBarray;
[m,n]=size(y)
cleanRGBarray = y;
for i = 2:m-1
for j = 2:n-1
if y(i,j) == 0 | y(i,j) == 255 % clean add new
cleanRGBarray(i,j) = median( ( y ( (i-1),(j-1) ) ) , ( y ( (i-1),(j) ) ) , ( y ( (i-1),(j+1) ) ) ; ( y ( (i),(j-1) ) ), ( y ( (i),(j) ) ) ; ( y ( (i),(j+1) ) ) ; ( y ( (i+1),(j-1) ) ), ( y ( (i+1),(j) ) ), ( y ( (i+1),(j+1) ) ) ) ;
end
end
end

You are making this very hard on yourself! The simplest way to re formulate the innermost loop is
block = y((-1:1)+i, (-1:1)+j);
cleanRGBarray(i,j) = median(block(:));
A couple of things to note:
You attempted to create a vector of arguments for median but didn't surround it with []
I used the fact that when indexing over more than one dimension, Matlab does "nested loops" to get all the numbers (so my block variable ends up being 3x3)
I feed a column vector block(:) with dimensions 9x1 into median - if you give it an N dimensional matrix, it will operate on the first non-singleton dimension only (so give it 3x3 and it returns 1x3 medians)
There are techniques for doing this much more efficiently - built in median filters, and things like blockproc - but you need the Image Processing Toolbox for those.
I hope this helps a bit.

matlab has a built-in median filter medfilt2 you can also try ordfilt2

Related

MATLAB : Calculating contrast

I'm trying to calculate the contrast of the image 'tire.tif' in Matlab using this formula Contrast formula
I did this little program in Matlab with two methods. The problem is that I don't get the same result. Can someone check my code and tell me what did I do wrong.
[M,N]=size(I);
Lumi=1/(M*N)*sum(I(:)); % which gives 53.66
Cont_method1=sqrt(1/(N*M)*sum(I(:)-Lumi)^2); % gives 5.478+03
Cont_method2=sqrt(1/prod(size(I))*sum(power((I(:)-Lumi),2))); % gives 9.0292
Your first method,
Cont_method1 = sqrt(
1/(N*M) * sum(
I(:)-Lumi
)^2
);
computes the sum of I(:)-Lumi, then squares the sum. The equation you link takes the sum of squares:
Cont_method1 = sqrt(
1/(N*M) * sum(
( I(:)-Lumi )^2
)
);
This is equivalent to your second method:
Cont_method2 = sqrt(
1/prod(size(I)) * sum(
power( ( I(:)-Lumi ), 2 )
)
);
Note that N*M and prod(size(I)) are the same thing, and both equivalent to the more efficient numel(I). And note that dividing the sum by the number of elements is the same as computing the mean using mean. So you can simplify:
Cont_method3 = sqrt( mean( ( I(:)-Lumi )^2 ));
But note that all you're doing here is computing a scaled norm:
Cont_method4 = norm(I(:)-Lumi) / sqrt(numel(I));

Plotting in maple

I'm having trouble plotting a set of complex numbers in maple.
I know what it should look like from a drawing I produced but I'd like to plot it in maple. My code is as follows;
z := x + I*y;
plots:-implicitplot([abs(z) <= 2, abs(z) >= 1, abs(arg(z)) >= Pi/4,
abs(arg(z)) <= Pi/2], x = -3...3, y = -3...3, filled = true);
The issue is that the inequalities are being plotted independently of each other rather than all together, so even the first pair of inequalities together fill the entire plane. Is there any way I can have the $4$ conditions imposed in $S$ be taken into account at the same time, rather than separately?
Didn't you mean for the second inequality to be reversed? Otherwise the first is redundant.
The command that you need is inequal, not implicitplot. Your args should be arguments. Your z expressions should be wrapped in evalc. (I don't why that's necessary, but it seems to be.) There's no need for filled= true. So, the command is
plots:-inequal(
[evalc(abs(z)) <= 2, evalc(abs(z)) >= 1,
evalc(abs(argument(z))) >= Pi/4, evalc(abs(argument(z))) <= Pi/2
], x = -3...3, y = -3...3
);
Sometimes using plots:-inequal takes a long time, in those cases I just use plots:-implicitplot with filledregions = true option. But I don't use a list of inequalities as its argument. For one plot only, implicitplot needs one equation/inequality, so what function can you use that gives you the intersection of regions for your inequalities? Very simple, just define a binary piecewise function with piecewise command. Here is how I do your plot.
f := piecewise( And( abs( x + y*I ) <= 2, abs( x + y*I ) >= 1, abs( argument( x + y*I ) ) >= Pi/4, abs( argument( x + y*I ) ) <= Pi/2 ), 1, 0 );
plots:-implicitplot( f > 1/2, x = -3..3, y = -3..3, filledregions = true, coloring = [yellow, white], view = [-3..3, -3..3] );
The output plot is the following.
Note that plots:-inequal gives a more accurate output, but plots:-implicitplot takes less time, so you should consider the trade-off between them and see which is better on your specific example.

Expand a summation with matlab as a function and write it to a text file

I have a function and I want to fit with a data set (x,y):
E = exp(-a*R)*sum(c(i)*R^i) , i= 1,2 ,3 ...
a and c are variables. I want to fit with different i.
How can I expand this equation and use as a function in the following command? lsqcurvefit(EQ,var,R,E)
Also I want to write the expanded equation to a text file like the following example:
fprintf(fitting_text,' EQ E(R)= exp(-a*R)*c1 *R; \n');
Thanks.
A vectorized way of calculating the sum is to use bsxfun to build a Vandermonde-like matrix with R and then perform a matrix-vector multiply:
sum = bsxfun(#power,R,1:k)*c(1:k);
It's not a computationally efficient as a loop, but it is nice and compact.
As for the function to pass to the fitting function, you can go one of two routes.
You can have EQ be a function of three arguments with the last one being the maximum power of R (Note that I have turned a into the last element of the parameter vector c and assumed everything is a column vector):
EQ = #(c,R,k) exp(-c(k+1)*R) .* ( bsxfun(#power,R,1:k)*c(1:k) );
c = lsqcurvefit(#(c,R) EQ(c,R,3),var,R,E); % cubic fit
You can also have EQ be a function of k only and return a function handle of arguments c and R:
EQ = #(k) #(c,R) exp(-c(k+1)*R) .* ( bsxfun(#power,R,1:k)*c(1:k) );
c = lsqcurvefit(EQ(3),var,R,E); % cubic fit
(I find this option more aesthetically pleasing).
An adaptive string can also be made using a function handle:
>> startOfLine = 'EQ E(R) = exp(-a*R) * ';
>> str = #(k) [startOfLine,'(',strjoin(strcat({'c'},num2str((1:k)'),'*R^',num2str((1:k)')),' + '),')'];
>> str(3)
ans =
EQ E(R)exp(-a*R) * (c1*R^1 + c2*R^2 + c3*R^3)

matlab: sum values of different sized subarrays without loop

I wonder if it is possible to get min/max values of different sized subarrays
without using a loop in matlab.
% create a 1D vector with arbitory floating point values
A = rand(100,1,'double');
% get start indexes of sections of A (eg. A>0.9)
pos01 = A>0.9;
posIdx= [1;find(pos01);size(A,1)];
% if 1 or size(A,1) where not required, remove them
posIdx = unique(posIdx);
% min/max all sections:
for ix=1:size(posIdx,1)-1
Amin(ix) = min(A(posIdx(ix):posIdx(ix+1)));
Amax(ix) = max(A(posIdx(ix):posIdx(ix+1)));
end
This last row can be very slow if you have a very large vector A and lots of sections.
I wonder how to vectorize this loop in matlab.
I tried to come up with a solution using arrayfun, remap, bsxfun and others.
But all the solutions I can think of, require the sections to have equal size - which is not the case :(
Any ideas ?
best,
Jens Henrik
Use cumsum and accumarray
A = rand(100,1,'double');
pos01 = A > 0.9;
subs = ( pos01(1) == 0 ) + cumsum( pos01(:) ); % convert posIdx to subs. note the special treatment of the first entry.
Amin = accumarray( subs, A, [], #min );
Amax = accumarray( subs, A, [], #max );
bsxfun approach to replace your for-loop part -
t1 = bsxfun(#le,1:size(A,1),posIdx(2:end)) & bsxfun(#ge,1:size(A,1),posIdx(1:end-1));
t1 = t1';
t2 = A(:,ones(1,size(t1,2))).*t1;
t2(~t1)=nan;
Amin = nanmin(t2);
Amax = nanmax(t2);

Matlab: conv(u,v) but that sums 'u' and 'v'?

Is there any function in Matlab like conv(u,v) but that sums up 'u(x)' and 'v(x)' instead of multiplying them?
Imagine:
u(x) = 66*(x-6)
v(x) = 6*(x-9)
Applying this "wanted function"...
sum = wantedfunction(u,v)
So,
sum(x) = 66*(x-6) + 6*(x-9)
Any ideas?
I believe you can do what you are asking for using anonymous functions:
u = #( x ) ( 66 * (x - 6) );
v = #( x ) ( 6 * (x - 9) );
w = #( x ) ( u(x) + v(x) );
This makes w the "sum" function you wanted - if I understood your question correctly.
Example: after I keyed in the above, I found
w(1:5)
Gave
-378 -306 -234 -162 -90
It's possible I completely missed the point of your question - if so, please leave a comment.
If by "conv" function you mean convolution then the equivalent of that for your case is simply adding two functions you want and then multiply them by delta(your desired spacing on x axis) and then sum over that, gives your function. Still you need to iterate this process by a "for" loop for different delays.