I calculated the distance between an image A1 and different images like image1,image2,image3 and image4 based on its hierarchicalCentroid. dist_1_1{ii} contains 4 values. I want to find the minimum value present in the dist_1_1{ii}.But I shows the value 1 and also i want to show the image which gives minimum value. Please help me. Thanks in advance
%% demo
clc,clear all,close all
plotFlag = 1;
depth = 6;
alef1 = im2bw(imread('C1.bmp')); %% Binary image
vec1 = hierarchicalCentroid(alef1,depth,plotFlag);
% subplot(1,3,1);
A=[];
vec2=[];
dist_1_1=[];
for ii=1:4
A{ii} = imread(['image' num2str(ii) '.bmp']);
% subplot(1,3,2);
vec2{ii} = hierarchicalCentroid(A{ii},depth,plotFlag);
%subplot(1,3,3);
%vec3 = hierarchicalCentroid(tav,depth,plotFlag);
% vec4=hierarchicalCentroid(A,depth,plotFlag);
% vec5=hierarchicalCentroid(A,depth,plotFlag);
dist_1_1{ii} = sum((vec1 - vec2{ii}) .^ 2);
[~,I] = min(dist_1_1{ii});
figure;
subplot(1,2,1);imshow(alef1);
subplot(1,2,2);imshow(A{I});
end
Considering that your images are named such as image1.png, image2.png,...
first, read and store the images in a cell
for ii=1:n
A{ii} = imread(['image' num2str(ii) '.png']);
end
Then compute the similarity between the image A1 and other images:
ind = computeSimilarity(A1,A); % here you compute the similarity and
(of course you would need a for-loop.)
After you have stored the values in the ind vector:
ind = [0.76,1.96,2.96];
Then find the index of a minimum value and choose the image accordingly
[~,I] = min(ind);
figure;
subplot(1,2,1);imshow(A1);
subplot(1,2,2);imshow(A{I});
What should be corrected in your code:
First of all, avoid using cell when it is not necessary and define it correctly when you using it. You cannot define a cell array like A=[]. You should do it like this: A=cell(2,3). For instance, for storing the vector of the descriptors you do not need a cell, just store them as a matrix, as I did.
Second of all when posting your code here, remove the unnecessary parts such as commented plots and commands.
And then, try to modify your code as follows, I might made some mistake about the dimensions, but you can get the main idea.
and also remember that you do not need to check each distance inside the loop. Calculate the vectors first and then find the distances in one step, as I did.
depth = 6;
alef1 = im2bw(imread('C1.bmp'));
vec1 = hierarchicalCentroid(alef1,depth,0);
A=cell(1,4);
vMatrix=zeros(4,length(vec1));
for ii=1:4
A{1,ii} = imread(['image' num2str(ii) '.bmp']);
vecMatrix(ii,:) = hierarchicalCentroid(A{1,ii},depth,0);
end
dist = sum((repmat(vec1,4,1) - vMatrix) .^ 2,2);
[~,I] = min(dist);
Related
I have a matrix named figmat from which I obtain the following pcolor plot (Matlab-Version R 2016b).
Basically I only want to extract the bottom red high intensity line from this plot.
I thought of doing it in some way of extracting the maximum values from the matrix and creating some sort of mask on the main matrix. But I'm not understanding a possible way to achieve this. Can it be accomplished with the help of any edge/image detection algorithms?
I was trying something like this with the following code to create a mask
A=max(figmat);
figmat(figmat~=A)=0;
imagesc(figmat);
But this gives only the boundary of maximum values. I also need the entire red color band.
Okay, I assume that the red line is linear and its values can uniquely be separated from the rest of the picture. Let's generate some test data...
[x,y] = meshgrid(-5:.2:5, -5:.2:5);
n = size(x,1)*size(x,2);
z = -0.2*(y-(0.2*x+1)).^2 + 5 + randn(size(x))*0.1;
figure
surf(x,y,z);
This script generates a surface function. Its set of maximum values (x,y) can be described by a linear function y = 0.2*x+1. I added a bit of noise to it to make it a bit more realistic.
We now select all points where z is smaller than, let's say, 95 % of the maximum value. Therefore find can be used. Later, we want to use one-dimensional data, so we reshape everything.
thresh = min(min(z)) + (max(max(z))-min(min(z)))*0.95;
mask = reshape(z > thresh,1,n);
idx = find(mask>0);
xvec = reshape(x,1,n);
yvec = reshape(y,1,n);
xvec and yvec now contain the coordinates of all values > thresh.
The last step is to do some linear polynomial over all points.
pp = polyfit(xvec(idx),yvec(idx),1)
pp =
0.1946 1.0134
Obviously these are roughly the coefficients of y = 0.2*x+1 as it should be.
I do not know, if this also works with your data, since I made some assumptions. The threshold level must be chosen carefully. Maybe some preprocessing must be done to dynamically detect this level if you really want to process your images automatically. There might also be a simpler way to do it... but for me this one was straight forward without the need of any toolboxes.
By assuming:
There is only one band to extract.
It always has the maximum values.
It is linear.
I can adopt my previous answer to this case as well, with few minor changes:
First, we get the distribution of the values in the matrix and look for a population in the top values, that can be distinguished from the smaller values. This is done by finding the maximum value x(i) on the histogram that:
Is a local maximum (its bin is higher than that of x(i+1) and x(i-1))
Has more values above it than within it (the sum of the height of bins x(i+1) to x(end) < the height of bin x):
This is how it is done:
[h,x] = histcounts(figmat); % get the distribution of intesities
d = diff(fliplr(h)); % The diffrence in bin height from large x to small x
band_min_ind = find(cumsum(d)>size(figmat,2) & d<0, 1); % 1st bin that fit the conditions
flp_val = fliplr(x); % the value of x from large to small
band_min = flp_val(band_min_ind); % the value of x that fit the conditions
Now we continue as before. Mask all the unwanted values, interpolate the linear line:
mA = figmat>band_min; % mask all values below the top value mode
[y1,x1] = find(mA,1); % find the first nonzero row
[y2,x2] = find(mA,1,'last'); % find the last nonzero row
m = (y1-y2)/(x1-x2); % the line slope
n = y1-m*x1; % the intercept
f_line = #(x) m.*x+n; % the line function
And if we plot it we can see the red line where the band for detection was:
Next, we can make this line thicker for a better representation of this line:
thick = max(sum(mA)); % mode thickness of the line
tmp = (1:thick)-ceil(thick/2); % helper vector for expanding
rows = bsxfun(#plus,tmp.',floor(f_line(1:size(A,2)))); % all the rows for each column
rows(rows<1) = 1; % make sure to not get out of range
rows(rows>size(A,1)) = size(A,1); % make sure to not get out of range
inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); % convert to linear indecies
mA(inds) = true; % add the interpolation to the mask
result = figmat.*mA; % apply the mask on figmat
Finally, we can plot that result after masking, excluding the unwanted areas:
imagesc(result(any(result,2),:))
I want to calculate the percentage of hexagonal cells in a binary image, which means the number of the cells that have another 6 neighbours cells. For example, the cell labeled with No. 1,2,3,and 4 all have 6 neighbours cells.
I'm looking for a function that can do that in Matlab. I've tried different Matlab functions such as regionprops, and bwconncomp. However, no one works for me. is there any idea.
A simple image is here:
Hi you can use the bwlabeln function and a succession of morphological function.
The following code does the job:
% load image and post processing
A = imread('LR0gx.png');
I = rgb2gray(A);
I = imcomplement(I);
% labelling of the image
L = bwlabeln(I);
figure; subplot 121;
imagesc(L); title('cells labeling')
% search and count the neighbours using the dilate function
label = unique(L);
for ii = label(2:end)'
I_temp = L == ii;
I_temp = bwmorph(I_temp,'dilate',2) - I_temp;
I_temp2 = L; I_temp2(~I_temp) = 0;
number_of_neighbours(ii) = size(unique(I_temp2), 1)-1;
end
L_2 = zeros(size(L));
for ii = label(2:end)'
L_2(L == ii) = number_of_neighbours(ii);
end
subplot 122;
imagesc(L_2); title('number of neighbours'); colorbar;
The result is the following one:
Ps: you have to remove one to count because the partition of the cell is present in the function unique.
Pss: the imcomplement is needed because bwlabeln label white values.
i want to draw image, do not know how to portray the image output kmeans
my code:
close all; clc; clear;
img = imread('pic7.png');
figure(), imshow(img);
impixelregion;
% nastavenie noveho obrazka
[y x z] = size(img)
for i=1:1:y
for j=1:1:x
imgNew(i, j, :) = 0;
end
end
[X_no_dither, map]= rgb2ind(img,8,'nodither');
figure, imshow(X_no_dither, map);
impixelregion;
m = im2double(X_no_dither)
idx = kmeans(m,4,'emptyaction','singleton');
how i draw image ?
Thanks.
In kmeans, the rows are the things we want to cluster (i.e. pixels by colour), the columns are the variables. Therefore, we cannot just pass in a image straight in, it has to be reshaped first. For example if we look at this MATLAB example., the image is first converted into lab colorspace (and is in lab_he).
First, they take only the a and b elements:
ab = double(lab_he(:,:,2:3));
Then, reshape so that ab is of size n x m where n = total number of pixels and m = 2 - this is because each pixel is being clustered based on both a and b values:
nrows = size(ab,1);
ncols = size(ab,2);
ab = reshape(ab,nrows*ncols,2);
Now, sort those pixels into three colors:
nColors = 3;
% repeat the clustering 3 times to avoid local minima
[cluster_idx cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
'Replicates',3);
The result then has to be reshape'd back into an image to be displayed:
pixel_labels = reshape(cluster_idx,nrows,ncols);
imshow(pixel_labels,[]), title('image labeled by cluster index');
In your case, as you're using a indexed image, try something like this:
idx = kmeans(m(:),4,'emptyaction','singleton');
idx = reshape(idx,size(m));
imshow(idx, []);
m(:) just arranges the pixels as a single column. kmeans then sorts them into four clusters. Afterwards, we reshape the indexes back using the size of our input image, and then display with imshow as normal.
You should read the linked example closely and make sure you understand what they are doing and why.
I have a 5000 *5000 sparse matrix with 4 different values. I want to visualise the nonzero elements with 4 different colors such that I can recognise the ratio of this values and the relationships between them,I use imagesc but I can not recognise very well among different values, especially the values with smaller ratio.I think if I use some symboles for each value , it works but I don't know how is it in Matlab. Any suggestion? The result of Dan code is in figure below.
You could reform the matrix to be a set of [X, Y, F] coordinates (re-using my answer from Resampling Matrix and restoring in one single Matrix):
Assuming your matrix is M
[X, Y] = meshgrid(1:size(M,1), 1:size(M,2));
Mf = M(:); %used again later, hence stored
V = [X(:), Y(:), Mf];
get rid of the zero elements
V(Mf == 0, :) = [];
At this point, if you have access to the statistics toolbox you can just go gscatter(V(:,1), V(:,2), V(:,3)) to get the correct plot otherwise continue with the following if you don't have the toolbox:
Find a list of the unique values in M
Vu = unique(V(:,3));
For each such value, plot the points as an xy scatter plot, note hold all makes sure the colour changes each time a new plot is added i.e. each new iteration of the loop
hold all;
for g = 1:length(Vu)
Vg = V(V(:,3)==Vu(g),:)
plot(Vg(:,1), Vg(:,2), '*');
a{g}=num2str(Vu(g));
end
legend(a);
Example M:
M = zeros(1000);
M(200,30) = 7;
M(100, 900) = 10;
M(150, 901) = 13;
M(600, 600) = 13;
Result:
Now i can answer the first part of the question. I suppose you need to do something like
sum(histc(A, unique(A)),2)
to count the number of unique values in the matrix.
temp = histc(A, unique(A)) "is a matrix of column histogram counts." So you get the counts of all values of unique(A) as they appear in A columns.
I'm doing stat = sum(temp,2) to get counts of all values of unique(A) in the whole matrix.
Then you can use the code proposed from #Dan to visualize the result.
hold all;
u=unique(A);
for i = 1:length(stat)
plot(u(i), stat(i)/max(stat), '*');
end
Please clarify what kind of relationship between the values do you mean?
I am plotting a 7x7 pixel 'image' in MATLAB, using the imagesc command:
imagesc(conf_matrix, [0 1]);
This represents a confusion matrix, between seven different objects. I have a thumbnail picture of each of the seven objects that I would like to use as the axes tick labels. Is there an easy way to do this?
I don't know an easy way. The axes properties XtickLabel which determines the labels, can only be strings.
If you want a not-so-easy way, you could do something in the spirit of the following non-complete (in the sense of a non-complete solution) code, creating one label:
h = imagesc(rand(7,7));
axh = gca;
figh = gcf;
xticks = get(gca,'xtick');
yticks = get(gca,'ytick');
set(gca,'XTickLabel','');
set(gca,'YTickLabel','');
pos = get(axh,'position'); % position of current axes in parent figure
pic = imread('coins.png');
x = pos(1);
y = pos(2);
dlta = (pos(3)-pos(1)) / length(xticks); % square size in units of parant figure
% create image label
lblAx = axes('parent',figh,'position',[x+dlta/4,y-dlta/2,dlta/2,dlta/2]);
imagesc(pic,'parent',lblAx)
axis(lblAx,'off')
One problem is that the label will have the same colormap of the original image.
#Itmar Katz gives a solution very close to what I want to do, which I've marked as 'accepted'. In the meantime, I made this dirty solution using subplots, which I've given here for completeness. It only works up to a certain size input matrix though, and only displays well when the figure is square.
conf_mat = randn(5);
A = imread('peppers.png');
tick_images = {A, A, A, A, A};
n = length(conf_mat) + 1;
% plotting axis labels at left and top
for i = 1:(n-1)
subplot(n, n, i + 1);
imshow(tick_images{i});
subplot(n, n, i * n + 1);
imshow(tick_images{i});
end
% generating logical array for where the confusion matrix should be
idx = 1:(n*n);
idx(1:n) = 0;
idx(mod(idx, n)==1) = 0;
% plotting the confusion matrix
subplot(n, n, find(idx~=0));
imshow(conf_mat);
axis image
colormap(gray)