Matlab - euclidean distance of specific elements between two vectors - matlab

I'm trying to find the coordinates/index that has the minimum distance of an element in a 2d array to another same element 2d array. I have a binary image from my edge detection problem and a ground truth image. For example, I have A as my binary image and B as the ground truth image:
A = [0 255 255 255;255 255 255 255;255 255 255 255;255 255 255 255 ]
B = [255 255 255 255;255 255 255 255; 255 255 0 255; 255 255 0 0]
0 is black and 255 is white. My algorithm goes like this:
for n=1:maxindex
if(A(n)==0&&B(n)==0)
distance(n) = 0;
elseif(A(n)==0&&B(n)==255)
for m=1: maxindex
if(B(m)==0&&m~=n)
translate index to subscripts
compute euclidean distance
store value in temporary vector
end
end
find minimum in temporary vector
distance(n) = minimum found
end
end
The algorithm really takes a long time for large images, since it's exhaustive when there's a mismatch. Is there a function in Matlab that would make this faster?

Related

Histogram function plots different colours from those requested

I"m trying to color-code each of 4 histograms using a predefined color scheme. Here's a minimal working example:
colours = [0 32 96;
192 0 0;
71 207 255;
255 143 143;
] / 255;
for i=1:4
x = randn(1,100);
subplot(1,4, i)
values = histogram(x, 'FaceColor', colours (i, :));
end
However, in the image I'm getting, the colors are actually (slightly) different, for instance for the first histogram I get (102,121,160) instead of (0,32,96):
The default histogram FaceAlpha is 0.6 (ref.). Setting it to 1 should do the trick.
histogram(x,'FaceColor',[0 1 0],'FaceAlpha',1);
Very cumbersome and unexpected.

Initialization of population for genetic algorithm in matlab

I randomly generated initial 10 population(let each of size n) of genetic algorithm as follows
for i = 1:10
for j=1:n
population(i,j)=randi([MinIntensity,MaxIntensity]);
end
end
Assume that I have the values of one population.For example let the first population of size 10 is [100 110 120 130 140 150 160 170 180 190].Is it possible to generate the remaining 9 population such that the values are near to the first population?(It is for the quick convergence of genetic algorithm).Also each population is a grayscale image with intensity values represented in row major order.Hence the intensity values should be in the range of 0 - 255.
Please help.Thanks in advance
You can do one thing. Use the first string as it is for the rest of the 9 strings except randomly generate an index (between 1 to n) and assign a random integer only to that positions with that random index.
population(1,:) = [100 110 120 130 140 150 160 170 180 190];
for i = 2:10
idx = randi([1 10]);
population(i,:) = population(1,:);
population(i,idx) = randi([0 255]);
end
With this you will get ten strings differing in only one position.
Edit: Image.
Assuming you have a MXN image. Create a mask for example
randi([-10 10], M , N)
Now add this to your original image. Now you get a new image whose all the pixels are modified but only within the range of -10 to 10. Some of the pixel values might go out of range in that case just modify as below
x(find(x < 0)) = 0 %Here X is your new image.
x(find(x > 255)) = 255

Matlab subtract without rounding off negative number to zero

I have two arrays,
X = uint8 ([ 255 0 75; 44 225 100]);
Y = uint8 ([ 50 50 50; 50 50 50]);
When I perform X-Y, I get the result as
205 0 25
0 175 50
What I expect is
205 -50 25
-6 175 50
How to achieve this. Kindly help.
uint8 is can only contain values between 0 and 255 - it can't contain negative values. Use a signed data type (one without a u as its first letter).
Incidentally, do you have a good reason to specify the data type at all?

Error while trying to use polyval

I have the following vector
vec = [ 255 0 255 0 255 0 255 0 255 0 255 0 255 0 255 0]
vec 1x16 double
and using the following command
polyval(vec', 256);
I get
ans = 3.3896e+038
but when I try to get back my original vector
vec2 = decimal2base(ans, 256)
I get
vec2 = 255 0 255 0 255 1 0 0 0 0 0 0 0 0 0 0
and this is clearly not my original vector.
Whats more if again I run polyval in this vector
polyval(vec2', 256);
I get
ans=
3.3896e+038
I am not entirely sure what sort of mistake I am making as I know that my conversion functions are ok, so it must be a number precision thing.
Ah, large numbers. The value 3.3896e+038 is higher than the maximum integer that can be represented by a double without loss of accuracy.
That maximum number is 2^53 or
>> flintmax('double')
ans =
9.0072e+15
So you are losing accuracy and you cannot reverse the computation.
Doing the computations with uint64 values only:
>> pows = uint64(fliplr(0:numel(vec)-1));
>> sum(uint64(vec).*(uint64(256).^pows),'native')
ans =
18446744073709551615
That's about 1.84e+19. Just a little different from what you get if you use doubles. But wait... that number looks familiar:
>> intmax('uint64')
ans =
18446744073709551615
So, you've maxed out unsigned 64-bit integers too:
>> uint64(256).^pows
ans =
Columns 1 through 5
18446744073709551615 18446744073709551615 18446744073709551615 18446744073709551615 18446744073709551615
Columns 6 through 10
18446744073709551615 18446744073709551615 18446744073709551615 72057594037927936 281474976710656
Columns 11 through 15
1099511627776 4294967296 16777216 65536 256
Column 16
When you get above 255^8 or so, you're passing intmax('uint64') and you can't manage numbers this large, at least not with MATLAB's built-in data types.
see if this returns '1':
polyval(vec(6:end),256)==polyval(vec2(6:end),256);
If so, then it's just a property of '255+1' for that special 'vec'.

Checking Pixels in Matlab

I have an image with 3 colors in matlab which value 0, 128, and 255. for example:
255 255 255 255 128 255 0 255 255 128 0 255
255 0 255 255 128 255 255 0 255 128 255 255
255 0 255 0 128 255 255 255 255 128 255 0
255 255 0 255 128 255 255 0 255 128 255 255
255 0 0 255 128 0 255 255 0 128 255 0
First, I want to check the pixels of the index (1,1) to (1,5).
If there is pixel value 0 (black), then the pixels of the index (1,1) to (1,5) is changed to 128 (gray), if none, then the pixels are changed to 0 (white).
Second, I want to do these steps again, checking of the index (2,1) to (2,5), (3,1) to (3,5), through to the bottom, then continue to the next, to the index (1,6) to (1,10), (2,6) to (2,10), through to the bottom, then went to the index (1,11) to (1,end), (2,11) to (2,end).
Do you absolutely need to do this sequentially? It sounds like you need to do this for each group of the form (n, (5*m : 5*m +1)). If so, you can do all of the tests simultaneously by reshaping the matrix into a 3d matrix of blocks which are 5 elements wide. Also I am assuming that you meant "if none, then the pixels are changed to 255 (white)", not 0.
Suppose your image is called myImage, then
numBlocks = numel(myImage)/(5*size(myImage,1));
% Generate a 3D matrix each of which is 5 elements long in dimension 2. Note reshape will throw an error if numblocks is fractional
foo = reshape(myImage,size(myImage,1),5,numBlocks);
blackTest = any(foo==0,2);
result = blackTest * 128 + ~blackTest*255; % result for each block
output = reshape(repmat(result,[1 5 1]),size(myImage));
This reorganises your image into a 3d matrix, where each submatrix corresponding to each "layer" of the 3d matrix is 5 elements wide. For the whole 3d matrix it checks whether any of the elements in dimension 2 are zero, leaving a logical matrix foo of length 1 in dimension 2. foo consists of logical ones and zeros, which in MATLAB can also be treated as numerical ones and zeros. So it multiplies foo by 128 (for grey output value) and adds the logical inverse of foo multiplied by 255, to get your white output values. Finally it repeats the matrix back to 5-element-wide blocks and restores it to its original dimensions.
Edit: Note that as mentioned in the code comment, this code won't work if your original image isn't a multiple of 5 pixels wide. To fix this you'd have to create a special case, or use a loop to step through each 5-element-wide block. In fact that might be a better approach all round:
index = 1;
output = zeros(size(myImage));
while index < size(myImage,2)
blockEnd = min(index+4,size(myImage,2));
blackTest = any(myImage(:,index:blockEnd)==0,2);
blackTest = blackTest(:,ones(1,5));
output(1:end,index:blockEnd) = blackTest * 128 + ~blackTest*255;
index = index+5;
end
% generate matrix
rand_data = randi(10,10);
I = zeros(10);
I(rand_data < 6 & rand_data > 3) = 128;
I(rand_data >= 6) = 255;
% here's the code
I = reshape(I',5,[])';
mask = repmat(any(I == 0,2),5,1);
I(mask) = 128;
I(~mask) = 255;
I = reshape(I',10,[])';