I have a code that yields a solution similar to the desired output, and I don't know how to perfect this.
The code is as follows.
N = 4; % sampling period
for nB = -30:-1;
if rem(nB,N)==0
xnB(abs(nB)) = -(cos(.1*pi*nB)-(4*sin(.2*pi*nB)));
else
xnB(abs(nB)) = 0;
end
end
for nC = 1:30;
if rem(nC,N)==0
xnC(nC) = cos(.1*pi*nC)-(4*sin(.2*pi*nC));
else
xnC(nC) = 0;
end
end
nB = -30:-1;
nC = 1:30;
nD = 0;
xnD = 0;
plot(nA,xnA,nB,xnB,'r--o',nC,xnC,'r--o',nD,xnD,'r--o')
This produces something that is close, but not close enough for proper data recovery.
I have tried using an index that has the same length but simply starts at 1 but the output was even worse than this, though if that is a viable option please explain thoroughly, how it should be done.
I have tried running this in a single for-loop with one if-statement but there is a problem when the counter passes zero. What is a way around this that would allow me to avoid using two for-loops? (I'm fairly confident that, solving this issue would increase the accuracy of my output enough to successfully recover the signal.)
EDIT/CLARIFICATION/ADD - 1
I do in fact want to evaluate the signal at the index of zero. The if-statement cannot handle an index of zero which is an index that I'd prefer not to skip.
The goal of this code is to be able to sample a signal, and then I will build a code that will put it through a recovery filter.
EDIT/UPDATE - 2
nA = -30:.1:30; % n values for original function
xnA = cos(.1*pi*nA)-(4*sin(.2*pi*nA)); % original function
N = 4; % sampling period
n = -30:30;
xn = zeros(size(n));
xn(rem(n,N)==0) = -(cos(.1*pi*n)-(4*sin(.2*pi*n)));
plot(nA,xnA,n,xn,'r--o')
title('Original seq. x and Sampled seq. xp')
xlabel('n')
ylabel('x(n) and xp(n)')
legend('original','sampled');
This threw an error at the line xn(rem(n,N)==0) = -(cos(.1*pi*n)-(4*sin(.2*pi*n))); which read: In an assignment A(I) = B, the number of elements in B and I must be the same. I have ran into this error before, but my previous encounters were usually the result of faulty looping. Could someone point out why it isn't working this time?
EDIT/Clarification - 3
N = 4; % sampling period
for nB = -30:30;
if rem(nB,N)==0
xnB(abs(nB)) = -(cos(.1*pi*nB)-(4*sin(.2*pi*nB)));
else
xnB(abs(nB)) = 0;
end
end
The error message resulting is as follows: Attempted to access xnB(0); index must be a positive integer or logical.
EDIT/SUCCESS - 4
After taking another look at the answers posted, I realized that the negative sign in front of the cos function wasn't supposed to be in the original coding.
You could do something like the following:
nB = -30:1
nC = 1:30
xnB = zeros(size(nB));
remB = rem(nB,N)==0;
xnB(remB) = -cos(.1*pi*nB(remB))-(4*sin(.2*pi*nB(remB));
xnC = zeros(size(nC));
remC = rem(nC,N)==0;
xnC(remC) = cos(.1*pi*nC(remC))-(4*sin(.2*pi*nC(remC)));
This avoids the issue of having for-loops entirely. However, this would produce the exact same output as you had before, so I'm not sure that it would fix your initial problem...
EDIT for your most recent addition:
nB = -30:30;
xnB = zeros(size(nB));
remB = rem(nB,N)==0;
xnB(remB) = -(cos(.1*pi*nB(remB))-(4*sin(.2*pi*nB(remB)));
In your original post you had the sign dependent on the sign of nB - if you wanted to maintain this functionality, you would do the following:
xnB(remB) = sign(nB(remB).*(cos(.1*pi*nB(remB))-(4*sin(.2*pi*nB(remB)));
From what I understand, you want to iterate over all integer values in [-30, 30] excluding 0 using a single for loop. this can be easily done as:
for ii = [-30:-1,1:30]
%Your code
end
Resolution for edit - 2
As per your updated code, try replacing
xn(rem(n,N)==0) = -(cos(.1*pi*n)-(4*sin(.2*pi*n)));
with
xn(rem(n,N)==0) = -(cos(.1*pi*n(rem(n,N)==0))-(4*sin(.2*pi*n(rem(n,N)==0))));
This should fix the dimension mismatch.
Resolution for edit - 3
Try:
N = 4; % sampling period
for nB = -30:30;
if rem(nB,N)==0
xnB(nB-(-30)+1) = -(cos(.1*pi*nB)-(4*sin(.2*pi*nB)));
else
xnB(nB-(-30)+1) = 0;
end
end
Related
I have following RLSA code in matlab.The jist of this algorithm is that it tries to connect area with specified spacing(threshold) for example in identifying text areas(As text has mostly fixed specific spacing most of the times on images) it tries to join them so that when some morphological operations are performed they do well in identifying those areas.
1.function result=RLSA(image,hor_thresh)
2. zeros_count=0;
3. one_flag=0;
4. hor_image=image;
5. [m,n]=size(image);
6. for i=1:m
7. for j=1:n
8. if(image(i,j)==1)
9. if(one_flag==1)
10. if(zeros_count<=hor_thresh)
11. hor_image(i,j-zeros_count:j-1)=1;
12. else
13. one_flag=0;
14. end
15. zeros_count=0;
16. end
17. one_flag=1;
18. else
19. if(one_flag==1)
20. zeros_count=zeros_count+1;
21. end
22. end
23. end
24. end
25. result= hor_image;
26. end
The above MATLAB code was taken from the following sites
answers.opencv.org
Attempt to implementation Running Length Smoothing Algorithm in C++
More detailed description is here
Working of RLSA
The above code does not work for all threshold values.For example on putting threshold value=20 I got following error
Subscript indices must either be real positive integers or logicals.
Error in RLSA (line 11)
hor_image(i,j-zeros_count:j-1)=1;
Can somebody explain me the working of algorithm on images with text and as to why this code doesn't work for all of the threshold values?
Moreover,Do I need to take two pass(as described in the links given) of this code one for horizontal and one for vertical and logically and them or the mentioned code has already taken care of it?
Well it all depends on the image you pass in along with the Hor_Thresh. I would guess that the problem is that j-zeros_count can be negative. That would be possible if one column of an image has a 1, but within 20 pixels of another column, that has a 1. Then the range that is being set to 1 will span 2 columns.
I don't really know what the algorithm is trying to do, but it appears to be dealing with binary images (but not explicitly). It is setting spans of zeros (book-ended by ones) that count < Hor_Threshold, to all be 1. So if there is "short" runs of zeros, they will be set to 1.
Guessing from the name of the parameter, I would expect to see some reset code between the 2 for loops. The Hor_Threshold implies Horizontal threshold, i.e. it gets reset each and every column.
So between the i and j loop, I think you need to reset your 2 flags:
zeros_count = 0;
one_flag = 0;
It has been a long time since I have used Matlab, I have been using a similar language, Igor Pro for a while, so I tested things out in Igor. This is the translated function:
Function/Wave RLSA(image,hor_thresh)
Wave Image
Variable Hor_Thresh
Variable zeros_count = 0;
Variable one_flag = 0;
Duplicate/FREE Image, hor_image
Variable m = DimSize(Image,0)
Variable n = DimSize(Image,1)
Variable i, J
for (i = 0;i < m;i += 1)
for (j = 0;j < n;j += 1)
if (image[i][j] == 1)
if (one_flag == 1)
if (zeros_count <= hor_thresh)
hor_image[i][j-zeros_count,j-1] = 1;
else
one_flag = 0;
endif
zeros_count = 0;
endif
one_flag = 1;
else
if (one_flag == 1)
zeros_count += 1;
endif
endif
endfor
endfor
return hor_image;
end //RLSA
Igor, like C++ is zero based indexing.
So I could get the same error with an image that I created:
Make/N=(24,24) Image
Image = 0
image[0][22] = 1
image[1][2] = 1
RLSA(image,20)
Throws the same error as you have.
So I have 2 ones in the image, that are separated by 3 zeros (< second argument), but are in different columns.
I am writing a function to create a fractal image in a plot. When I run my code, a plot pops up but it is empty. I think the issues lies somewhere in my if/elseif statements, but I am having a hard time finding it. My code is:
function [] = fractal(x, y, N)
close all
start = [x, y];
X = zeros(N+1,1);
Y = zeros(N+1,1);
X = start;
hold on
for i = 1:N
prob = rand;
if prob >= 0.01
X(i+1,:) = 0;
Y(i+1,:) = 0.16*y(1);
elseif prob == 0.02:0.86
X(i+1,:) = (0.85*x(i))-(0.04*y(i));
Y(i+1,:) = (-0.04*x(i))+(0.85*y(i))+1.6;
elseif prob == 0.87:0.94
X(i+1,:) = (0.2*x(i))-(0.26*y(i));
Y(i+1,:) = (0.23*x(i))+(0.22*y(i))+1.6;
elseif prob == 0.95:1.0
X(i+1,:) = (-0.15*x(i))+(0.28*y(i));
Y(i+1,:) = (0.26*x(i))+(0.24*y(i))+0.44;
plot(X(i,:),Y(i,:),'.','Markersize',1)
axis equal
end
end
end
When I run my code with
>> fractal(1,1,1000)
... a plot comes up but it is empty.
Yup... it's your if statements, but there are more issues with your code though but we will tackle those later. Let's first address your if statements. If you want to compare in a range of values for examples, you need use the AND (&&) statement. In addition, you should place your plot code outside of any if/elseif/else statement. You currently have it inside your last elseif statement so plot will only run if the last condition is satisfied.
To be explicit, if you wish to compare if a value is in between a certain range, do something like:
if (prob >= a && prob < b)
and for elseif:
elseif (prob >= a && prob < b)
a and b are the lower and upper limits of what you want to compare. This includes a but excludes b in the comparison.
I also have a several comments and recommendations with your current code in order to get this to work:
You run your function with a single x and y value, but you are trying to access this x and y in your for loop as if these were arrays. I'm assuming this is recursive in nature so you need to actually use X and Y in your if/else conditions instead of x and y.
Since you are using single values, it is superfluous to use : to access the second dimension. Just leave that out.
You create X and Y but then overwrite X to be the starting location as a 2D array... I think you meant to replace X and Y's first element with the starting location instead.
Your first if statement I think is incorrect. You'd want to access Y(i) not Y(1) no?... given the behaviour of your code thus far.
Your first condition will definitely mess things up for you. This is saying that as long as the value is greater than or equal to 0.01, execute that statement. Otherwise, try and execute the other conditions which may in fact never work because you are looking for values that are greater than 0.01 where the first condition already handles that for you. I assume you meant to check if it was less than 0.01 instead.
Doing value comparecondition array in MATLAB means that this statement is true provided that any one of the values in array matches the condition provided by value. This will have unintended side effects with your current code.
Make sure that your ranges covered for each if statement are continuous (i.e. no gaps or disconnects between ranges). Right now, you are checking for values in 0.01 intervals. rand generates random values between 0 and 1 exclusive. What if you had a value of 0.15? None of your if conditions handle this so you need to use what I talked about above.
You are most likely getting a blank plot because your MarkerSize attribute is very small.... you set it to 1 pixel. Unless you have super human vision, you can't really visualize this. Make the MarkerSize larger.
Use drawnow; after you plot to immediately update the results to screen.
Therefore, with refactoring your code, you should make it look something like this:
function [] = fractal(x, y, N)
close all
start = [x, y];
X = zeros(N+1,1);
Y = zeros(N+1,1);
%// Change - Initialize first elements of X and Y to be the starting positions
X(1) = start(1);
Y(1) = start(2);
hold on
for i = 1:N
prob = rand;
if prob <= 0.01 %// Change
X(i+1) = 0;
Y(i+1) = 0.16*Y(i); %// Change
elseif (prob > 0.01 && prob <= 0.86) %// Change
X(i+1) = (0.85*X(i))-(0.04*Y(i)); %// Change
Y(i+1) = (-0.04*X(i))+(0.85*Y(i))+1.6; %// Change
elseif (prob > 0.86 && prob <= 0.94) %// Change
X(i+1) = (0.2*X(i))-(0.26*Y(i)); %// Change
Y(i+1) = (0.23*X(i))+(0.22*Y(i))+1.6; %// Change
elseif (prob > 0.94 && prob <= 1.0) %// Change
X(i+1) = (-0.15*X(i))+(0.28*Y(i)); %// Change
Y(i+1) = (0.26*X(i))+(0.24*Y(i))+0.44; %// Change
end
%// Change - move outside of if/else blocks
%// Also make marker size larger
plot(X(i),Y(i),'.','Markersize',18); %// Change
axis equal
%// Add just for kicks
drawnow;
end
end
I now get this figure when I do fractal(1,1,1000):
.... cool fractal btw!
I wrote a heap sort function in MATLAB and it works fine, except that when the length of input is greater or equal to 1000, it can take a long time (e.g. the length of 1000 takes half a second). I'm not sure if it's that MATLAB doesn't run very fast on heap sort algorithm or it's just my code needs to be improved.
My code is shown below:
function b = heapsort(a)
[~,n] = size(a);
b = zeros(1,n);
for i = 1:n
a = build_max_heap(a);
b(n+1-i) = a(1);
temp = a(1);
a(1) = a(n+1-i);
a(n+1-i) = temp;
a(n+1-i) = [];
a = heapify(a,1);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function a = build_max_heap(a)
[~,n] = size(a);
m = floor(n/2);
for i = m:-1:1
a = heapify(a,i);
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function a = heapify(a,i)
[~,n] = size(a);
left = 2*i;
right = 2*i + 1;
if left <= n
if a(left) >= a(i)
large = left;
else
large = i;
end
else
return
end
if right <= n
if a(right) >= a(large)
large = right;
end
end
if large ~= i
temp = a(large);
a(large) = a(i);
a(i) = temp;
a = heapify(a,large);
end
end
I'm aware that maybe it's the code a(n+1-i) = []; that may consume a lot of time. But when I changed the [] into -999 (lower than any number of the input vector), it doesn't help but took even more time.
You should use the profiler to check which lines that takes the most time. It's definitely a(n+1-i) = []; that's slowing down your function.
Resizing arrays in loops is very slow, so you should always try to avoid it.
A simple test:
Create a function that takes a large vector as input, and iteratively removes elements until it's empty.
Create a function that takes the same vector as input and iteratively sets each value to 0, Inf, NaN or something else.
Use timeit to check which function is faster. You'll see that the last function is approximately 100 times faster (depending on the size of the vector of course).
The reason why -999 takes more time is most likely because a no longer gets smaller and smaller, thus a = heapify(a,1); won't get faster and faster. I haven't tested it, but if you try the following in your first function you'll probably get a much faster program (you must insert the n+1-i) other places in your code as well, but I'll leave that to you):
a(n+1-ii) = NaN;
a(1:n+1-ii) = heapify(a(1:n+1-ii),1);
Note that I changed i to ii. That's partially because I want to give you a good advice, and partially to avoid being reminded to not use i and j as variables in MATLAB.
I'm attempting to implement Neville's algorithm in MatLab with four given points in this case. However, I'm a little stuck at the moment.
This is my script so far:
% Neville's Method
% Function parameters
x = [7,14,21,28];
fx = [58,50,54,53];
t = 10;
n = length(x);
Q = zeros(n,n);
for i = 1:n
Q(i,1) = fx(i);
end
for j = 2:n
for i = j:n
Q(i,j) = ((t-x(i-j)) * Q(i,j-1)/(x(i)-x(i-j))) + ((x(i)-t) * Q(i-1,j-1)/(x(i)-x(i-j)));
end
end
print(Q);
As for the problem I'm having, I'm getting this output consistently:
Subscript indices must either be real positive integers or logicals.
I've been trying to tweak the loop iterations but to no avail. I know the problem is the primary logic line in the inner loop. Some of the operations result in array indices that are equal to zero initially.
That's where I am, any help would be appreciated!
In your loop at the first time i-j is 0 because you set i = j. In MATLAB indices start at 1. A simple fix to get running code would be to change
for i = j:n
to
for i = j+1:n
This solves
Subscript indices must either be real positive integers or logicals.
However, this may not be ideal and you may need to rethink your logic. The output I get is
>> neville
Q =
58.0000 0 0 0
50.0000 0 0 0
54.0000 50.8571 0 0
53.0000 54.2857 51.3469 0
I would like to compute the maximum of translated images along the direction of a given axis. I know about ordfilt2, however I would like to avoid using the Image Processing Toolbox.
So here is the code I have so far:
imInput = imread('tire.tif');
n = 10;
imMax = imInput(:, n:end);
for i = 1:(n-1)
imMax = max(imMax, imInput(:, i:end-(n-i)));
end
Is it possible to avoid using a for-loop in order to speed the computation up, and, if so, how?
First edit: Using Octave's code for im2col is actually 50% slower.
Second edit: Pre-allocating did not appear to improve the result enough.
sz = [size(imInput,1), size(imInput,2)-n+1];
range_j = 1:size(imInput, 2)-sz(2)+1;
range_i = 1:size(imInput, 1)-sz(1)+1;
B = zeros(prod(sz), length(range_j)*length(range_i));
counter = 0;
for j = range_j % left to right
for i = range_i % up to bottom
counter = counter + 1;
v = imInput(i:i+sz(1)-1, j:j+sz(2)-1);
B(:, counter) = v(:);
end
end
imMax = reshape(max(B, [], 2), sz);
Third edit: I shall show the timings.
For what it's worth, here's a vectorized solution using IM2COL function from the Image Processing Toolbox:
imInput = imread('tire.tif');
n = 10;
sz = [size(imInput,1) size(imInput,2)-n+1];
imMax = reshape(max(im2col(imInput, sz, 'sliding'),[],2), sz);
imshow(imMax)
You could perhaps write your own version of IM2COL as it simply consists of well crafted indexing, or even look at how Octave implements it.
Check out the answer to this question about doing a rolling median in c. I've successfully made it into a mex function and it is way faster than even ordfilt2. It will take some work to do a max, but I'm sure it's possible.
Rolling median in C - Turlach implementation