I have a complex matrix cdata, that is 2144x2048. I am getting elements from cdata that are greater than a specified threshold by doing the following:
[row, col] = find(abs(cdata) > threshold);
row and col can have multiple values. Then, I take the row and col values, I perform a calculation to get N samples of the real x-data, and 33 samples of the y-data as follows:
xdata = real(cdata(row(i),col(i)-bw:col(i)+bw))
ydata = real(cdata(row(i)-bw:row(i)+bw,col(i)-bw:col(i)+bw))
where bw is a constant value that determines the number of samples I need to get. During this calculation, specifically the column portion of cdata for the xdata and the row portion of cdata for the ydata, I exceed the bounds of the matrix and MATLAB throws the following error:
??? Subscript indices must either be real positive integers or logicals
How can I ensure that I don't exceed the bounds? I'm ok with having to skip a row/col pair if it is going to exceed the bounds.
The reason you're having problems is because you're not restricting your search to closer then bw from the edge of the matrix. This means its possible to find values above the threshold near the edges of the matrix. When you add or subtract bw from these indices you end up out of bounds. You can restrict your search like this.
[row, col] = find(abs(cdata(bw+1:end-bw,bw+1:end-bw)) > threshold);
row = row + bw;
col = col + bw;
This guarantees your row and column indices are within the bounds so when you grab a region surrounding them you won't go out of bounds.
On a side note. The ydata variable in your code is indexing an entire square region of the matrix and the xdata is only indexing a section of a row. Should your ydata actually be ydata = real(cdata(row(i)-bw:row(i)+bw, col(i)))?
Related
How can I get a maximum of a three-dimensional matrix (which was previously two-dimensional and converted to a three-dimensional matrix by reshape) in MATLAB so that I can then get the position of that maximum value in the matrix?
I wrote the following code, but unfortunately the dimensions obtained for the maximum values are larger than the dimensions of the matrix.
mxshirin=max(max(frvrdin))
[X,Y,Z]=size(frvrdin)
[o,i]=find(frvrdin==mxshirin)
xo=size(o)
xi=size(i)
If frvrdin is 3D, max(max(frvrdin)) will be a 1x1x3 vector:
frvrdin = rand(3,3,3);
max(max(frvrdin))
ans(:,:,1) =
0.8235
ans(:,:,2) =
0.9502
ans(:,:,3) =
0.7547
Don't nest max() functions, simply use the 'all' switch to take the max of the entire matrix at once.
max(frvrdin,[],'all')
ans =
0.9340
If you're on an older MATLAB, use column flattening: max(frvrdin(:)).
You can't use the automated location output of max [val,idx]=max() on more than two dimensions, so use find and ind2sub:
frvrdin = rand(3,3,3);
val = max(frvrdin,[],'all'); % Find maximum over all dims
idx = find(abs(frvrdin-val)<1e-10); % Compare within tolerance
[row,col,page] = ind2sub(size(frvrdin),idx); % Get subscript indices
where row is the index into your first dimension, col into the second and finally page into the third.
I want to scramble the image using matlab using the algorithm:
Converting the image to gray scale of W X H pixels.
Computing the sum of every row and every column.
Generating the random variables Kc and Kr of range (2^bit depeth-1) of h&w elements respectively.
Finding the modulo2 of the sum.
Rotate the ith row by Kr(i) amount right if modulo2 of sum of rows is zero else rotate it left by kr(i) amount. Similarly for the columns.
Show the image
Problem is in using the circshift command in matlab to rotate the ith row by Kr(i) amount. This function is not using the indexing of the particular row or column.
%%Encryption till scrambled image
rgb = imread('image.jpg');
I=rgb2gray(rgb);
[w,h]=size(I);
imshow(I);
title('Original grayscale');
info = imfinfo('image.jpg');
bit=info.BitDepth;
range=(2^bit)-1;
Kc=randi(range,[1,h]); %generating a random array Kc of h
Kr=randi(range,[1,w]); %generating random array Kr
alpha=sum(I); %sum of all column element creating an linear array of h columns
alpha1=sum(I,2); %sum of all row element creating an linear array of w rows
M=mod(alpha,2); %linear array of h column
M1=mod(alpha1,2); %linear array of w rows
for i=1:h
if M(1:i)==0
I1=circshift(I(:,i),-Kc(i)); %shifts up
else
I1=circshift(I(:,i),Kc(i)); %shifts down
end
end
for j=1:w
if M1(j:1)==0
I2=circshift(I1(j,:),Kr(j)); %shifts right
else
I2=circshift(I1(j,:),-Kr(j)); %shifts left
end
end
figure
imshow(I2);
title('Scrambled Image');`
I have a problem with MATLAB bar3 plots: Here is what I have:
m x n Array Values containing values of a measurement.
Another m x n Array Angles Represents the angle at which a value was measured (e.g. the 3rd value was measured at an angle of 90°). The angular values for each measurement value are stored in another variable.
I need a range for my x-axis from -180° to +180°. This alone is no problem. But how do I hand over my measurement values? I have to somehow link them to the angular values. So that each value in Values is somehow linked to it's angular value in Angles. For my y-axis, I can simply count from 0 to the amount of rows of my Values Array.
EXAMPLE:
Valueslooks like:
3 5 6
2 1 7
5 8 2
Angles looks like:
37° 38° 39°
36° 37° 38°
34° 35° 36°
Values(1,1) = 3 was measured at Angles(1,1) = 37° for example.
At each angle, the number of bars varies depending on how many measurements exist for that angle. bar3 needs a matrix input. In order to build a matrix, missing values are filled with NaN.
Warning: NaNs are usually ignored by plotting commands, but bar3 apparently breaks this convention. It seems to replace NaNs by zeros! So at missing values you'll get a zero-height bar (instead of no bar at all).
[uAngles, ~, uAngleLabels] = unique(Angles); %// get unique values and
%// corresponding labels
valuesPerAngle = accumarray(uAngleLabels(:), Values(:), [], #(v) {v});
%// cell array where each cell contains all values corresponding to an angle
N = max(cellfun(#numel, valuesPerAngle));
valuesPerAngle = cellfun(#(c) {[c; NaN(N-numel(c),1)]}, valuesPerAngle);
%// fill with NaNs to make all cells of equal lenght, so that they can be
%// concatenated into a matrix
valuesPerAngle = cat(2, valuesPerAngle{:}); %// matrix of values for each angle,
%// filled with NaNs where needed
bar3(uAngles, valuesPerAngle.'); %'// finally, the matrix can be plotted
ylabel('Angles')
xlabel('Measurement')
With your example Values and Angles this gives:
Say we have a matrix m x n where the number of rows of the matrix is very big. If we assume each row is a vector, then how could one find the maximum/minimum distance between vectors in this matrix?
My suggestion would be to use pdist. This computes pairs of Euclidean distances between unique combinations of observations like #seb has suggested, but this is already built into MATLAB. Your matrix is already formatted nicely for pdist where each row is an observation and each column is a variable.
Once you do apply pdist, apply squareform so that you can display the distance between pairwise entries in a more pleasant matrix form. The (i,j) entry for each value in this matrix tells you the distance between the ith and jth row. Also note that this matrix will be symmetric and the distances along the diagonal will inevitably equal to 0, as any vector's distance to itself must be zero. If your minimum distance between two different vectors were zero, if we were to search this matrix, then it may possibly report a self-distance instead of the actual distance between two different vectors. As such, in this matrix, you should set the diagonals of this matrix to NaN to avoid outputting these.
As such, assuming your matrix is A, all you have to do is this:
distValues = pdist(A); %// Compute pairwise distances
minDist = min(distValues); %// Find minimum distance
maxDist = max(distValues); %// Find maximum distance
distMatrix = squareform(distValues); %// Prettify
distMatrix(logical(eye(size(distMatrix)))) = NaN; %// Ignore self-distances
[minI,minJ] = find(distMatrix == minDist, 1); %// Find the two vectors with min. distance
[maxI,maxJ] = find(distMatrix == maxDist, 1); %// Find the two vectors with max. distance
minI, minJ, maxI, maxJ will return the two rows of A that produced the smallest distance and the largest distance respectively. Note that with the find statement, I have made the second parameter 1 so that it only returns one pair of vectors that have this minimum / maximum distance between each other. However, if you omit this parameter, then it will return all possible pairs of rows that share this same distance, but you will get duplicate entries as the squareform is symmetric. If you want to escape the duplication, set either the upper triangular half, or lower triangular half of your squareform matrix to NaN to tell MATLAB to skip searching in these duplicated areas. You can use MATLAB's tril or triu commands to do that. Take note that either of these methods by default will include the diagonal of the matrix and so there won't be any extra work here. As such, try something like:
distValues = pdist(A); %// Compute pairwise distances
minDist = min(distValues); %// Find minimum distance
maxDist = max(distValues); %// Find maximum distance
distMatrix = squareform(distValues); %// Prettify
distMatrix(triu(true(size(distMatrix)))) = NaN; %// To avoid searching for duplicates
[minI,minJ] = find(distMatrix == minDist); %// Find pairs of vectors with min. distance
[maxI,maxJ] = find(distMatrix == maxDist); %// Find pairs of vectors with max. distance
Judging from your application, you just want to find one such occurrence only, so let's leave it at that, but I'll put that here for you in case you need it.
You mean the max/min distance between any 2 rows? If so, you can try that:
numRows = 6;
A = randn(numRows, 100); %// Example of input matrix
%// Compute distances between each combination of 2 rows
T = nchoosek(1:numRows,2); %// pairs of indexes for all combinations of 2 rows
for k=1:length(T)
d(k) = norm(A(T(k,1),:)-A(T(k,2),:));
end
%// Find min/max distance
[~, minIndex] = min(d);
[~, maxIndex] = max(d);
T(minIndex,:) %// Displays indexes of the 2 rows with minimum distance
T(maxIndex,:) %// Displays indexes of the 2 rows with maximum distance
I would like to write a program which plots the points on top of a semicircle on a certain interval and a straight line everywhere else. Something like this: __n__.
I defined a time domain, which was stored as a vector (t = 0:0.01:5). I assumed that I could define the points on the top of the semicircle using elements of the time vector:
if t>=2|t<=2.3
y = sqrt(.15^2-(t-2.15)^2);
but MATLAB produced an error message saying only square matrices can be squared.
I tried to utilize indices to show that I wanted to square an element of the t vector and not the whole vector:
i = [200:230];
for t(200:230)
y = sqrt(.15^2-(t(i)-2.15)^2);
After these failures, I noticed that squaring a square matrix with one column of non-zero elements would produce a new square matrix with a column of the first matrix's elements squared. If there is some way to eliminate the extra columns of zeros after squaring the matrix, I could use that property of matrices to square the values of the t vector.
What is the simplest and most effective way to address this problem?
It sounds like you want to draw a horizontal line with a semicircular "bump" on it. Here's how you can do this:
t = 0:0.01:5; % Create the time vector
y = zeros(size(t)); % Create a zero vector the same size as t
index = find((t >= 2) & (t <= 2.3)); % Find a set of indices into t
y(index) = sqrt(.15^2-(t(index)-2.15).^2); % Add the "bump" to y
y(1:index(1)) = y(index(1)); % Add the line before the "bump"
y(index(end):end) = y(index(end)); % Add the line after the "bump"
In the above solution, the lines before and after the "bump" could be slightly higher or lower than one another (depending on where your samples in t fall). If you want to make sure they are at the same height, you can instead do the following:
index = (t >= 2) & (t <= 2.3); % Find a set of logical indices
y(index) = sqrt(.15^2-(t(index)-2.15).^2); % Add the "bump" to y
% OPTION #1:
y(~index) = y(find(index,1,'first')); % Use the first circle point as the height
% OPTION #2:
y(~index) = y(find(index,1,'last')); % Use the last circle point as the height
Finally, you can plot the line:
plot(t,y);
Hold on, so your question is, you want to square each element of a vector? All you have to do is:
t.^2
The . represents an element-wise operation in MATLAB on a vector or an array.
And secondly, if I understood your problem currently, you want to create a vector y, which contains a function of elements of t such that t>=2 | t <=2.3?
If so, all you have to do is this:
y = sqrt(0.15^2-(t( (t>=2|t<=2.3) )-2.15).^2));
Essentially, I created a logical index (t>=2 | t<=2.3) and used to access only those elements (which I wanted) in t.
Also, I didn't fully understand what you wanted to achieve. Do you want to plot the topmost point (maxima) of a semicircular curve?