Calculate pixel from coordinates - coordinates

Hello I have this image:
This image has 16 pixels. White is 0, pink 1... like in image. My problem is that I need to calculate number of pixel from coordinates. If I have coordinates x = 3 and y = 3, I need to get black pixel with number 15.
How can I do that?

If you know how many pixels per row you have, you can simply use the next formula :
(y * numberPerRow) + x
Example using a 16 pixels images (4x4)
x
y
calcul
value
3
3
3 * 4 + 3
15
0
0
0 * 4 + 0
0
1
2
2 * 4 + 1
9

Related

Nonlinear Filter for image processing - looking for minimum inside a mask

I have an idea about a filter for images but I do not know how I can realize this without using a double-for-loop in MATLAB.
I have an image, and I want to use a linear filter mask on it, let's say:
[1,1,1,1,1]
This filter mask is moving over the image, pixel by pixel. For each neighbourhood, the pixel I is set to the minimum of the surrounding neighbourhood.
Here is an example:
[ … image data …]
[ … …]
[ … …]
[ … 23 68 155 20 53 …]
[ … …]
For my example, I want to filter the centering pixel with the value 155. The result would be:
[ … image data …]
[ … …]
[ … …]
[ … 23 68 20 20 53 …]
[ … …]
The pixel 155 gets replaced with the minimum value in his neighbourhood.
I can do this with a double-for-loop, but it is really slow, too slow to use it for my application.
Would be happy for a good idea how to increase the speed! Thank you
Your filter idea is called erosion. It is implemented in the Image Processing Toolbox in the function imerode. In your case, you'd apply:
result = imerode(image_data, [1,1,1,1,1]);
The neighborhood can have any shape. Set elements to 0 to exclude them from the neighborhood. For example, for a roundish neighborhood you can use
[0,1,1,1,0
1,1,1,1,1
1,1,1,1,1
1,1,1,1,1
0,1,1,1,0]
If I understand your question correctly, what you want is finding a moving minimum value with a specified window width along a specific row. This can be done with movmin function which was introduced in version 2016a.
Knowing that movmin processes columns by default (as dim = 1). So in your case, you may want to set the dim argument to 2 (move along the rows) and discard the endpoints for the value outside of the window. A sample code may look like:
k = randi(20,20,11); % make some samples
ci = 6; % sample at the center row
wd = 5; % filter window width
k(:,ci) = movmin(k(:,(ci-2:ci+2)),wd,2,'Endpoints','discard') % replace the center row samples
Take a look at the movmin documentation to learn more.
I was working on an own solution, when the answer of Y. Chang came up... I wanted to post it nevertheless. At least, the result is the same, so it seems to work.
% Test input.
A = round(rand(5) * 10)
% Dimensions.
nRows = size(A, 1);
nCols = size(A, 2);
% Kernel.
b = [1, 1, 1, 1, 1]
% Step size.
step = floor(numel(b) / 2);
% Output.
B = zeros(nRows, nCols);
for k = 1:nRows
temp = repmat(A(k, :), nCols + 2 * step, 1);
idx = double(triu(ones(size(temp)), -numel(b) + 1) & tril(ones(size(temp)), 0));
idx(idx == 0) = NaN;
temp = temp .* idx;
temp = min(temp, [], 2).';
B(k, :) = temp(step+1:end-step);
end
B
% Compare with movmin function.
BB = movmin(A, numel(b), 2)
Output:
A =
9 2 1 6 7
2 5 9 1 7
2 8 5 10 4
2 0 6 5 8
8 3 10 7 6
b =
1 1 1 1 1
B =
1 1 1 1 1
2 1 1 1 1
2 2 2 4 4
0 0 0 0 5
3 3 3 3 6
BB =
1 1 1 1 1
2 1 1 1 1
2 2 2 4 4
0 0 0 0 5
3 3 3 3 6

Assigning values in neighborhood of local maxima’s to the value of local maxima based on varying window width (non symmetric window width)

This question is an extension of my previous question with some new issues so I thought to make a new query. I hope it is ok.
https://stackoverflow.com/questions/46054811/changing-the-values-in-the-neighbourhood-of-local-maxima-to-the-local-maxima/46055833#46055833
Query:
Where I find local maxima. I want to make a window and assign the values depending upon window size to the neighbors the value of local maxima.
Problem: (I want my window size to change as in my original signal I have different behavior around local maxima’s.) For example in 8th window local maxima is at 34th location but I have assigned the values on the left of 34th location the value of local maxima.
In short I want to have varying and controllable window width.
Please have a look at the attached picture to get an idea of output what I want.
I hope it will give some good idea.
I want to have varying and non symmetric means not same at every local maxima window width .
I have also attached a code for nlfilter which is doing exactly what I want to do means it makes window and assign values to local maximas within that window width but I need to have flexible and changeable window width.
Is it possible to have varying window width or is there some other way possible to do that.
enter image description here
Code:
t = 1:35 ;
Y = [1 3 13 6 2 7 5 4 2 4 1 0 1 2 3 5 0 0 1 0 0 2 3 6 7 0 0 8 0 1 1 2 3 4 2];
n = 2;
[p l] = findpeaks(Y);
locations = zeros(size(Y));
locations(l) = true;
locations = conv(locations, ones(1, 2*n+1), 'same') > 0;
X = -inf(size(Y)); % create temporary
X(l) = Y(l); % copy the local maxima
X = nlfilter(X, [1 2*n+1 ], #(x) max(x)); %replace all values with it local maxima
X(l) = Y(l); % ensure local maxima are not changed
Y(locations) = X(locations); % copy filtered temporary to output
figure(1)
hold on
plot(t,Y,'r')
t = 1:35 ;
Y = [1 3 13 6 2 7 5 4 2 4 1 0 1 2 3 5 0 0 1 0 0 2 3 6 7 0 0 8 0 1 1 2 3 4 2];
plot(t,Y,'b')
hold off
I shall be grateful to you for your valuable replies.
Further Explanation:
Please have a look at the pictures attached.
2nd picture is a part of original signal with local maximas mentioned as green dots.
In 1st pictures the red lines shows the region which I want to assign the value of local maxima. Green Dot is local maxima . So you will see that if I apply window with fixed width it will not work because the points before local maxima are less than after local maxima.
The reason for placing 1 outside in example is same that there are few points before local maxima which I want to flat as compared to after local maxima.
The same is the case with other windows like last window 8 I have local maxima on 34th location but why I have chosen large values before it is only due to the values I want to assign the values of local maxima .
You can define a criterion that starting form a peak and going to the both sides we compute variance of neighbors of the peak and we increase the radius of the neighborhood until variance of neighboring elements becomes greater than a predefined threshold.
Here idx_peaks is position of peaks and peaks is value of peaks. After applying the threshold you can get number of elements before and after position of each peak n_before and n_after. Then you can find indices of neighborhood and assign values to them.
Y = [1 3 13 6 2 7 5 4 2 4 1 0 1 2 3 5 0 0 1 0 0 2 3 6 7 0 0 8 0 1 1 2 3 4 2];
idx_peaks = [3 6 10 16 19 25 28 34];
peaks = [13 7 4 5 1 7 8 4];
threshold = 2;
cumvar = #(a)cumsum(a(:).^2)./(1:numel(a)).'-(cumsum(a(:))./(1:numel(a)).').^2;
categ = zeros(numel(Y),1);
categ(idx_peaks)=1;
forward_categ = cumsum(categ(idx_peaks(1):end));
n_after = accumarray(forward_categ,Y(idx_peaks(1):end),[],#(x)sum(cumvar(x)<threshold)-1).';
backward_categ = cumsum(flipud(categ(1:idx_peaks(end))));
n_before = flipud(accumarray(backward_categ,fliplr(Y(1:idx_peaks(end))),[],#(x)sum(cumvar(x)<threshold)-1)).';
lo = idx_peaks-n_before;
up = idx_peaks+n_after;
val = repelem(peaks,up-lo+1);
index=cumsum(accumarray(cumsum([1;up(:)-lo(:)+1]),[lo(:);0]-[0;up(:)]-1)+1);
index= index(1:end-1);
Y(index) = val
Here is the result when setting the threshold to 2 :
Y=
[1 3 13 6 2 7 4 4 4 4 4 4 1 5 5 5 1 1 1 1 1 1 1 7 7 0 0 8 4 4 4 4 4 4 4]

MATLAB: building gradient between two columns in greyscale image

I have two images, one of which is a greyscale image (orig), the other is a binary image of the same size with vertical lines (mask). Where the binary value is 1 I would like on the grey scale to create a gradient from the two columns of values on either side of the binary line. For example:
binary: old greyscale: new greyscale:
0 0 1 1 1 0 0 x 10 x x x 6 x x 10 9 8 7 6 x
0 0 1 1 1 0 0 x 1 x x x 5 x x 1 2 3 4 5 x
0 0 1 1 1 0 0 x 5 x x x 13 x x 5 7 9 11 13 x
0 0 1 1 1 0 0 x 10 x x x 2 x x 10 8 6 4 2 x
I have the following code so far...not sure if its of any value...it runs through and finds the x location of the start of a vertical streak in vectempa, width in vectempb, and then the value from the greyscale on either side in vectemp1 and vectemp2. Current plan is to take the absolute value of difference of each column in vectemp1 and vectemp2, divide by that column in vectempb (width), and then use that to increment the gradient...somehow accounting for direction of the gradient. Does this make sense or is there a much better/easier way to do this?
vectempa=[];
vectempb=[];
vectemp1=[];
vectemp2=[];
q=1;
r=1;
for i=1:x
if mask(1,i)==0 && mask(1,(i+1))==1
vectempa(end+1)=i;
vectemp1(1:z,q)=orig((1:z),i);
q=q+1;
elseif mask(1,i)==1 && mask(1,(i+1))==0
vectempb(end+1)=i-vectempa(end);
vectemp2(1:z,r)=orig((1:z),i);
r=r+1;
end
end
Thanks!
Is it possible you are looking for roifill?
new = roifill( old, mask );

Matlab random number range

I am struggling generating a random number within the range of x.
So say x is 4 the range would be -2 to 2 and if it was 6 then -3 to 3.
I know it is
rand() * something + somethingelse
You have to take out the mean of rand*x, that is x/2:
x = [1 2 3 4 5 6 7]
rand(1,numel(x)).*x-x/2
ans =
0.4172 -0.4283 0.7716 1.0149 -0.5978 0.4069 -2.9690
From where you left it is not hard to find the solution:
rand() * something + somethingelse
From left to right:
rand() : From 0 to 1
We want to make the range 4 times as wide, so we do:
rand()*4 : From 0 to 4
Now the width is correct, we just need to give it the correct location:
rand()*4-2: From -2 to 2

Find Value at a given Orientation in Matrix

In Matlab I've matrix where, in a previous stage of my code, an specific element was chosen. From this point of the matrix I would like to find a maximum, not just the maximum value between all its surounding neighbours for a given radius, but the maximum value at a given angle of orientation. Let me explain this with an example:
This is matrix A:
A =
0 1 1 1 0 0 9 1 0
0 2 2 4 3 2 8 1 0
0 2 2 3 3 2 2 1 0
0 1 1 3 2 2 2 1 0
0 8 2 3 3 2 7 2 1
0 1 1 2 3 2 3 2 1
The element chosen in the first stage is the 4 in A(2,4), and the next element should be the maximum value with, for example, a 315 degrees angle of orientation, that is the 7 in A(5,7).
What I've done is, depending on the angle, subdivide matrix A in different quadrants and make a new matrix (an A's submatrix) with only the values of that quadrant.
So, for this example, the submatrix will be A's 4th quadrant:
q_A =
4 3 2 8 1 0
3 3 2 2 1 0
3 2 2 2 1 0
3 3 2 7 2 1
2 3 2 3 2 1
And now, here is my question, how can I extract the 7?
The only thing I've been able to do (and it works) is to find all the values over a threshold value and then calculate how those points are orientated. Then, saving all the values that have a similar orientation to the given one (315 degrees in this example) and finally finding the maximum among them. It works but I guess there could be a much faster and "cleaner" solution.
This is my theory, but I don't have the image processing toolbox to test it. Maybe someone who does can comment?
%make (r,c) the center by padding with zeros
if r > size(A,1)/2
At = padarray(A, [size(A,1) - r], 0, 'pre');
else
At = padarray(A, [r-1], 0 'post');
if c > size(A,2)/2
At = padarray(At, [size(A,2) - c], 0, 'pre');
else
At = padarray(At, [c-1], 0 'post');
%rotate by your angle (maybe this should be -angle or else 360-angle or 2*pi-angle, I'm not sure
Ar = imrotate(At,angle, 'nearest', 'loose'); %though I think nearest and loose are defaults
%find the max
max(Ar(size(Ar,1)/2, size(Ar,2)/2:end); %Obviously you must adjust this to handle the case of odd dimension sizes.
Also depending on your array requirements, padding with -inf might be better than 0
The following is a relatively inexpensive solution to the problem, although I found wrapping my head around the matrix coordinate system a real pain, and there is probably room to tidy it up somewhat. It simply traces all matrix entries along a line around the starting point at the supplied angle (all coordinates and angles are of course based on matrix index units):
A = [ 0 1 1 1 0 0 9 1 0
0 2 2 4 3 2 8 1 0
0 2 2 3 3 2 2 1 0
0 1 1 3 2 2 2 1 0
0 8 2 3 3 2 7 2 1
0 1 1 2 3 2 3 2 1 ];
alph = 315;
r = 2;
c = 4;
% generate a line through point (r,c) with angle alph
[nr nc] = size(A);
x = [1:0.1:nc]; % overkill
m = tan(alph);
b = r-m*c;
y = m*x + b;
crd = unique(round([y(:) x(:)]),'rows');
iok = find((crd(:,1)>0) & (crd(:,1)<=nr) & (crd(:,2)>0) & (crd(:,2)<=nc));
crd = crd(iok,:);
indx=sub2ind([nr,nc],crd(:,1),crd(:,2));
% find max and position of max
[val iv]=max(A(indx)); % <-- val is the value of the max
crd(iv,:) % <-- matrix coordinates (row, column) of max value
Result:
val =
7
iv =
8
ans =
5 7