This question already has answers here:
Matlab -- random walk with boundaries, vectorized
(2 answers)
Closed 8 years ago.
I have a array of 10 vectors 'x' with as below (for simulating 1D random walk):
r=rand(10,1000);
r(r>.5)=1;
r(r<=.5)=-1;
x=cumsum(r);
The image of the one vector will be like:
If I consider 2 values in the sequence , say +10 and -10, then I would like to reflect the sequence 'x' when it reaches those values. How to achieve this?
Before answering your question, a should point that your code is broken. By default cumsum accumulate data across first dimension, to change this behavior you should specify dim parameter:
x = cumsum(r,2);
And, answering your question, you could simply invert all data above threshold:
threshold = 10;
nsteps = ceil( max(abs(x(:))) / (2*threshold) - 0.5 );
for ii = 1:nsteps
ind = abs(x) > 10;
x(ind) = 20 * sign(x(ind)) - x(ind);
end
Related
This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 3 years ago.
I got a problem about checking if two matrices are equal in MATLAB.
Specifically, I want to verify if, for a matrix W, all elements are equal to each other and all row sums are equal to 1 we would have W = W^2.
Therefore I wrote the following code which aims to check if every element of these two matrices are equivalent, to conclude whether the matrices are equal to each other. But it turns out that this does not work since the W8 matrix should be equal to its square.
for i = 1 :60
for j = 1 :60
if(W8(i,j) - W8_square(i,j) ~= 0)
disp('the matrix are not equal');
break;
end
end
end
There is a matlab function for it:
eq = isequal(W8,W8_square) should work
Here you find the reference
https://www.mathworks.com/help/matlab/ref/isequal.html
Be careful that if this checks for EXACT identity, so computation errors, of the order of eps, may affect the result.
To solve this, I would subtract the two matrixes and check the norm of the result: below a certain threshold (low) they are equal.
Here you have an example code for your problem:
n = 10; %matrix size
W8 = ones(n)/n; %Generating W8
W8_square = W8^2;
eq = isequal(W8,W8_square) %checking EXACT identity
M_difference = W8-W8_square; %Difference matrix
eq2 = isequal(M_difference<=eps,ones(n)) %%comparing every value with eps
This question already has answers here:
rgb to ycbcr conversion in matlab
(2 answers)
Closed 4 years ago.
I'm learning about image processing, and currently translating between RGB and YCbCr.
Basically, I have a nxmx3 matrix, which represents the brightness of each colour (RGB), and the operation to change this to Y,Cb, and Cr would be something like this:
for each row, index, in RGBMatrix:
y[index] = row[0] + row[1] + row[2]
So each row of y has one value, and that value is based on the values in the same in RGBMatrix.
I've tried the following in MATLAB:
function [y,Cb, Cr] = rgbToYCbCr(r,g,b)
signalSize = size(r);
y = zeros(signalSize);
for i = 1:signalSize(1)
for j = 1:signalSize(2)
y(i,j,1) = (0.299 * r(i,j,1)) + (0.587 * g(i,j,2)) + (0.114 * b(i,j,3));
end
end
end
However, this does not give me the results that I want as y now has the same dimensions as the RGBMatrix, when instead it should be 1 column.
How can I do this efficiently in MATLAB?
I know there is an inbuilt function for RGB to YCbCr, but for the sake of learning I'd like to implement it myself.
Example:
RGB Matrix:
R G B
[[0.5,0.5,0.5],
[0.2,0.1,0.6],
[0.1,0.4,0.7]]
Y Matrix:
[[0.5+0.5+0.5],
[-0.2-0.1+0.6],
[0.1+0.4-0.7]]
or
[[1.5],
[0.3],
[-0.2]]
Ignore the fact that values aren't realistic, what I'm more concerned about is carrying out an operation per row like I've described in Matlab without using the (typically) slower iterative way (with a for loop).
In reality I have a 1080x768x3 array. Each element in the 1080x768 dimension has a value for each colour (R,G,B) and I want to convert this to (Y,Cb,Cr) eventually.
If you have an RGB image, Imgrgb that is NxMx3 in size, do:
Imgrgb= imread('peppers.png'); % A sample RGB image
% make sure you have a double image range [0-1], you may not need this.
Imgrgb=im2double(Imgrgb);
r=Imgrgb(:,:,1);
g=Imgrgb(:,:,2);
b=Imgrgb(:,:,3);
y = (0.299 * r) + (0.587 * g) + (0.114 * b);
Cb=
Cr=
% concatenate result:
ImgYCbCr=cat(3,y,Cb,Cr);
And y shoudl be NxM, the same as r,g, and b. Do the same for the other 2 values with their corresponding equation.
If your matrix is like:
A =
1 3 5
2 4 6
then you may "flatten" it to a vector like:
>>Av = A(:)
Av =
1
2
3
4
5
6
I.e. it takes the values from the matrix in a row order and converts to a vector.
To convert it back to a matrix you may use the reshape function
>> reshape(Av,[2 3])
ans =
1 3 5
2 4 6
The A(:) method is equivalent to reshape(A,[numel(A) 1])
This question already has an answer here:
MatLab function that shifts points to the left or right from a max or minimum point
(1 answer)
Closed 6 years ago.
I have written a script that does the function:
eval(['VCathodicOh3(2,i) =' 'min(' 'data_' varnames{1} '(49000:51000,9));'])
In this, 'VCathodicOh3' is made by taking data from column 9 in different variables that are organized in arrays (they are 1:100000 rows by 10 columns).
I want to, instead of just finding the min, also add something to this function so that it takes the min, finds the point at which that min is at, and then move 4 points to the left of that point.
Ex:
min(data_var(49000:51000,9)) = -3.190
then lets say (50250, -3.190) is the point at which you find the min. I would like the script to move that point -4 (50246, y) and give me the new corresponding value.
You can use the second output of min to tell you the index of the minimum value. You could then decrement this value by 4 to shift it to the left.
a = [5 3 2 1 0]
[~, ind] = min(a);
newval = a(ind-4)
If you have a 2D matrix, you can convert the linear index ind to rows / columns and decrement that:
a = magic(10);
[~, ind] = min(a);
[row,col] = ind2sub(size(a), ind);
newval = a(row, col-4)
As a side note, I would really discourage using dynamic variable names like you are and use a more appropriate data structure such as a cell array or struct. The usage of eval can get out of hand very quickly as I'm sure you've noticed.
This question already has answers here:
Generate a random number with max, min and mean (average) in Matlab
(6 answers)
Closed 9 years ago.
I want to generate a N dimensional column vector in matlab, with mean 0.5 ( variance is ok to adjust ) , but I want all numbers to be positive, does anyone know how to do it?
You can try this:
E.g. create a vector of 1000 random values drawn from a normal distribution with a mean of 0.5 and a standard deviation of 5.
a = 5;
b = 0.5;
y = a.*randn(1000,1) + b;
To make it positive, then you can delete all the numbers that are negative or zero and generate some more until you got n positive numbers.
Check out here for more info.
It depends on the distribution that you want. The rand(v) function generates a uniform random distribution (range [0,1] I believe although I'm not sure if either 0 or 1 are theoretically possible values) in an array with dimensions v.
So if you want a 3x4x5x6 array, you would do
myRandArray = rand([3 4 5 6]);
If you want the upper value to be larger, you could do
myRandArray = maxVal * rand([3 4 5 6]);
Where maxVal is the largest value. And if you want a range minVal to maxVal, then do
myRandArray = minVal + (maxVal - minVal) * rand([3 4 5 6]);
For other distributions (like randn for normal distribution) you can make adjustments to the above, obviously. If you want a "truncated normal distribution" - you may need to start with too many values:
dims = [3 4 5 6];
n = prod( dims );
tooMany = 0.5 + randn(2 * n); % since you want mean = 0.5
tooMany(tooMany < 0) = [];
if numel( tooMany ) > n
myRandArray = reshape(tooMany(1:n), dims);
end
You can obviously improve on this, but it's a general idea.
For example, you could generate only n values, see how many fail (say m), then generate another m * n / (n - m), and repeat as needed until you have exactly n.
Note that the mean of the final distribution is no longer 0.5 since we cut off the tail. A 'normal distribution' cannot remain 'normal' if you exclude certain values. But then you didn't specify what distribution you wanted...
This question already has answers here:
Matlab, matrix containing random numbers within specified range
(3 answers)
Closed 8 years ago.
I want to generate random values between 0.001 and 0.0015 such that each time I run a for loop, i get a new value.
e.g
value = random number between 0.001 and 0.0015;
for i = 1:10,
for value,
Calculate something...
end
end
Can any one tell me how to do that?
It's all written in the documentation of rand() function: http://www.mathworks.com/help/matlab/ref/rand.html
Example 1 Generate values from the uniform distribution on the
interval [a, b]:
r = a + (b-a).*rand(100,1);
So in your case a = 0.001 and b = 0.0015 and you can also change rand(100,1) to just rand(10,1) to give you 10 random values on the interval [a,b].
It's simple, you just do:
0.001+(rand()*(0.0015-0.001))
Here is how you should be doing it in my opinion:
myNumbers = rand(10,1)*0.0005+0.001;
for value = myNumbers;
%Calculate something
value
end
Note that the main improvement here is that you precalculate all random values at once.
Furthermore you can loop over them directly.