I used connected component labeling algorithm (bwconncomp) to label the different parts of a binary image (MATLAB). Now i need to calculate the area of different labels and remove the labels with smaller area. Can i use the default area finding command or is there any specific commands for that in matlab...Help..
From the documentation:
CC = bwconncomp(BW) returns the connected components CC found in BW.
The binary image BW can have any dimension. CC is a structure with
four fields...
The final field in CC is PixelIdxList, which is:
[a] 1-by-NumObjects cell array where the kth element in the cell array is
a vector containing the linear indices of the pixels in the kth object.
You can find the area of each label by looking at the length of the corresponding entry in the cell array. Something like:
areas_in_pixels = cellfun(#length, CC.PixelIdxList);
The PixelIdxList is a cell array, each member of which contains the linear indexes of the pixels present in that connected component. The line of code above finds the length of each cell in the cell array - i.e. the number of pixels in each connected component.
I've used cellfun to keep the code short and efficient. A different way of writing the same thing would be something like:
areas_in_pixels = nan(1, length(CC.PixelIdxList);
for i = 1:length(CC.PixelIdxList)
areas_in_pixels(i) = length(CC.PixelIdxList{i});
end
For each connected component, you can then find the size of that component in pixels by accessing an element in areas_in_pixels:
areas_in_pixels(34) %# area of connected component number 34
If you don't want to write lots of code like above just use built-in functions of MATLAB to detect the area. Label your components and from the properties of the component you can find out the area of that component. Suppose Bw is the binary image:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
for k = 1:length(B)
area(k)=stats.Area;
end
You can make this better still by avoiding the for loop with the following:
[B,L] = bwboundaries(Bw,'noholes');
stats = regionprops(L,'Area','perimeter');
area = [stats.Area];
Best,
-Will
Related
I have a row that contains the names and photos of people in Oracle, how do I make face recognition that can recognize names only by taking pictures from the camera ??
what techniques can I use?
Firstly, do not store the raw images in the blob column. You should store the vector representation of raw images. The following python code block will find the vector representation of a face image.
#!pip install deepface
from deepface.basemodels import VGGFace, Facenet
model = VGGFace.loadModel() #you can use google facenet instead of vgg
target_size = model.layers[0].input_shape
#preprocess detects facial area and aligns it
img = functions.preprocess_face(img="img.jpg", target_size=target_size)
representation = model.predict(img)[0,:]
Here, you can either pass exact image path like img.jpg or the 3D array to img argument of preprocess_face. In this way, you will store the vector representations in the blob column of oracle database.
When you have a new face image, and want to find its identity in the database find its representation again.
#preprocess detects facial area and aligns it
target_img = functions.preprocess_face(img="target.jpg", target_size=target_size)
target_representation = model.predict(target_img )[0,:]
Now, you have the vector representation of the target image and vector representations of the database images. You need to find the similarity score of target image representation and each instance of database representations.
Euclidean distance is the easiest way to compare vectors.
def findEuclideanDistance(source_representation, test_representation):
euclidean_distance = source_representation - test_representation
euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
euclidean_distance = np.sqrt(euclidean_distance)
return euclidean_distance
We will compare each data base instance to target. Suppose that representations of data base instances are stored in representations object.
distances = []
for i in range(0, len(representations)):
source_representation = representations[i]
#find the distance between target_representation and source_representation
distance = findEuclideanDistance(source_representation, target_representation )
distances.append(distance)
Distances list stores the distance of each item in the data base to target. We need to find the lowest distance.
import numpy as np
idx = np.argmax(distances)
Idx is the id of the target image in the database.
So I have the code to import a stack of images, but I am getting an error: Subscripted assignment dimension mismatch.
myPath = 'E:\folder name\'; %'
fileNames = dir(fullfile(myPath, '*.tif'));
width = 1400;
height = 1050;
nbImages = length(fileNames);
C=uint8(zeros(width, height, nbImages));
for i=1:length(fileNames)
C(:,:,i)=imread(cat(2,'E:\folder name\',fileNames(i).name));
i
end
I understand that the error is originating from the for loop, but I don't know of any other way to fill in an empty matrix with images.
Your images must not be all the same size. You can handle this by using explicit assignment for the first two dimensions. This will zero-pad any images which are smaller than the rest.
im = imread(...);
C(1:size(im, 1), 1:size(im, 2), i) = im;
Also, there is a good chance that your images have multiple color channels (the third dimension), so you'll likely want to concatenate along the fourth dimension rather than the third.
C(:,:,:,i) = imread(...)
Obviously it all depends what you want to do with the images, but in general, if you want a "stack" of images (or a "stack" of anything, really), then it sounds like you should be collecting them as a cell array instead.
Also, the correct way to create safe filenames is using the fullfile command
e.g.
C = cell(1, length(nbImages));
for i = 1 : length (fileNames)
C{i} = imread (fullfile ('E:','folder name', fileNames(i).name));
end
If you really want to concatenate to a 3D matrix from your cell array, assuming you have checked this is possible, you can do this very easily using comma-separated-list generator syntax:
My3DMatrix = cat(3, C{:});
In my image I have 5 Objects in black-white form. Some are respectively small, some are bigger.
So what i am trying to do is drawing a BoundingBox or tag the objects which has less area than others (ex. under 10pixels/area) .
I couldn't make this happen, can anyone help?
That's two separate problems. The first is to select only objects above a certain area. So simply remove all objects below it:
clean = bwareaopen (im, 10); # remove all objects with area below 10
Then for the second problem there are many possibilities. You can get their borders:
borders = bwperim (clean);
imshow (borders);
You can label them:
labeled = bwlabel (clean);
imshow (labeled);
Or you can get their bounding box (which depending on the shape of your objects may overlap):
props = regionprops (clean, 'BoundingBox');
all_bb = props.BoundingBox;
boxes = false (size (clean));
for i = 1:numel (all_bb)
bb = all_bb{i};
bb(round (bb(2):bb(2)+bb(4), bb(1):bb(1)+bb(3))) = true;
end
imshow (boxes);
Note: this was written out of my head, no testing. There may be small oversights, but nothing major.
I have obtained blood vessels of an eye in an image variable ves. I found the number of connected components(8-connectivity) as blobs. For each blob I need to calculate the Area, Major axis length and Centroid and store these values in a matrix testfv (each row corresponding to each property).For a single blob, Area returns a 1x1 struct, Centroid returns a 1x2 struct, and MajorAxisLength returns a 1x1 struct. So ,I guess depending on the number of blobs the number of cells required to store the values of Areas, Centroids and MajorAxisLength's vary, so using just one testfv to store these values as I have done would be wrong.
Is it possible? This is the code I tried(i assumed that testfv has 25 columns which allows me to store upto 8 blobs info)
[labeledImage numberOfBlobs] = bwlabel(ves, 8);
col=numberOfBlobs*2;
testfv = zeros(3,col);
for i=1:col
blobMeasurements = regionprops(labeledImage, 'Area');
testfv(1,col) = [blobMeasurements.Area];
blobMeasurements = regionprops(labeledImage, 'MajorAxisLength');
testfv(2,col)= [blobMeasurements.MajorAxisLength];
blobMeasurements = regionprops(labeledImage, 'Centroid');
testfv(3,col) = [blobMeasurements.Centroid];
end
I am getting the following error....
??? Subscripted assignment dimension mismatch.
Error in ==> alpha1 at 191 <br/>
testfv(1,col) = [blobMeasurements.Area];
Also, I need to write the data of the testfv matrix to an excel sheet file. How do I that ?
Would really appreciate the help as I am new to Matlab.
I have a list of values each with latitude and longitude. I'm looking to create a translucent heatmap image to overlay on Google Maps. I know there are server side and flash based solutions already, but I want to build this in javascript using the canvas tag.
However, I can't seem to find a concise description of the algorithm used to turn coordinates and values into a heatmap. Can anyone provide or link to one?
Thanks.
The basic idea would be to create a grid and project every lat,lng coord to that grid. I would use a 2D array of ints.
The psuedo-code would be:
for each coord
cell = coord projected to grid
increment cell value
end
for 0 to # of passes
for each row
for each col
if grid[row,col] > 0 then
grid[row,col] += 1
increment_adjacent_cells(row, col)
end
end
end
end
So, the idea is that the higher the int value, the hotter that cell is. increment_adjacent_cells should increment the values in all 8 adjacent cells.
I have tried to solve this in javascript using the canvas element, here is my current result:
http://gist.github.com/346165
I have to fix the gaussian filter and the color mapping, because it doesn't give good results currently.
A faster way of building a heatmap could be to use a queue:
Pseudocode:
Add an element to queue (first in heatmap(x,y, val))
While (!queue.isEmpty())
{
elem = queue.pop()
queue.push(elem.x + 1, elem.y, val-1)
queue.push(elem.x - 1, elem.y, val-1)
queue.push(elem.x, elem.y + 1, val-1)
queue.push(elem.x, elem.y - 1, val-1)
}
This saves on tons of iterations!
Look at this project if you are looking for something that looks more like 'tv weather maps':
https://github.com/optimisme/javascript-temperatureMap