How to provide input to BagOfFeatures() function in MATLAB in the form of imageSet or imageDataStore? - matlab

I want to use bagOfFeatures() function of MATLAB. But it requires input in the form of imageSet or imageDataStore. The code I want to run is given below:
Dataset = 'D:\dsktop\kinect_leap_dataset\acquisitions';
thresh1 = 0;
thresh2 = 20;
k = dir(fullfile(Dataset,'\P*\G*\*_depth.png'));
kf = {k(~[k.isdir]).folder};
kn = {k(~[k.isdir]).name};
for j=1:length(k)
% Applying thresholding to the original image
full_name = horzcat(kf{j},filesep,kn{j});
image = imread(full_name);
image_bin1 = (image < thresh2);
image_bin2 = (thresh1 < image);
image_bin = abs(image_bin2- image_bin1);
sequence{i} = image_bin;
end
% Bag of Features
bag = bagOfFeatures(sequence);
But the "sequence" is a cell class and so bagOfFeatures() is giving me errors. So I tried this:
Dataset = 'D:\dsktop\kinect_leap_dataset\acquisitions';
imgFolder = fullfile(Dataset);
imgSets = imageSet(imgFolder, 'recursive');
imgSets.Description
But now the problem is how to do the processing (thresholding) on images saved in imgSets. Also, after processing how to save all the "image_bin" images in imageSet class so that I can give them as input to the BagOfFeatures() function.

I solved this problem myself. To give input as an imageSet or imageStrore to BagOfFeatures(), we have to store all the "image_bin" images in a folder in PC.
For that, we have to create that folder in the desired location as
mkdir D:\.............\cropped
Then, we have to save the "image_bin" in that folder in a loop as
file_name = sprintf('D:/............/cropped/image_bin_%d.png',j);
imwrite(image_bin, file_name);
Then, the data from above folder is read in MATLAB memory as
imds = imageDatastore('D:/.............../cropped', 'Labels', label);
% label is an array of labels made by the user
[trainingSet, validationSet] = splitEachLabel(imds, 0.3, 'randomize');
% Bag of Features
bag = bagOfFeatures(trainingSet);
And It's done.

Related

How to save a single .mat file of features for many images (loop for)?

I trained two-class-classification (svmtrain) with 15 features for 18 images and I have many objects in a single image. I want to save single .mat file of features of these images. My problem is when I run this code, I have just the variables of last image.
This is my code:
NbIm = size(names1,1);
n1 = 1;
n2 = NbIm;
for n = n1:n2
%1- Read the original image
%2- Processing : Segmentation
%3- characterization :
[B3,L3,N3] = bwboundaries(ICellules); (see picture)
CC = bwconncomp(L3);
BW = bwlabel(L3);
stats1 = regionprops(CC,'Area','Centroid','Eccentricity','Perimeter','ConvexArea','ConvexHull','ConvexImage','MajorAxisLength','MinorAxisLength','Orientation','Solidity','BoundingBox');
for k = 1:length(B3),
V = []; glcm = [];
V = Im_originale(BW==k);
glcm = graycomatrix(V,'Offset',[2 0],'Symmetric', true);
stats= graycoprops(glcm);
Contrast_Cellule = stats.Contrast;
Correlation_Cellule = stats.Correlation;
Energy_Cellule = stats.Energy;
Homogeneity_Cellule = stats.Homogeneity;
Area_cellule = stats1(k).Area;
Perimeter_cellule = stats1(k).Perimeter;
Circularity_cellule = (4*pi*Area_cellule)/Perimeter_cellule^2;
Centroid_cellule = stats1(k).Centroid;
Compactness_cellule = Perimeter_cellule^2/(4*pi*Area_cellule);
MajorAxis_cellule = stats1(k). MajorAxisLength;
MinorAxis_cellule = stats1(k). MinorAxisLength;
Orientation_cellule = stats1(k).Orientation;
Eccentricity_cellule = stats1(k).Eccentricity;
Solidity_cellule = stats1(k).Solidity;
boundary3 = B3{k};
[cc] = chaincode(boundary3);
ai = cc.code;
ai = ai.';
output = calc_harmonic_coefficients(ai,30);
Ampl = 0.5*sqrt((output(1)^2)+(output(2)^2)+(output(3)^2)+(output(4)^2));
Feat(k,:) = [Area_cellule,Perimeter_cellule,Circularity_cellule,Compactness_cellule, Solidity_cellule,Eccentricity_cellule,MajorAxis_cellule,MinorAxis_cellule, Centroid_cellule,Ampl,Contrast_Cellule,Correlation_Cellule,Energy_Cellule,Homogeneity_Cellule];
end
end
save('FeatTrain.mat', 'Feat');
Every time you run the inner loop (k=...) you overwrite Feat, without ever saving it.
If you want to have a single variable for Feat, instead of saving multiple .mat files there are 2 ways to it:
If every time you run the inner loop the size of Feat is the same, you can make it a 3D matrix, by changing you line to Feat(n-n1+1,k,:)=[.... This will make a 3D matrix where each Feat(n,:,:) will be the features of each image.
If instead every time you run the inner loop Feat can change size, then use a cell array, as in Feat{n-n1+1}(k,:)=[....

Creating a geoTIFF from an image in Matlab

I'm trying to create a geoTIFF file in Matlab from the attached png.
example image
I'm following the example provided in:
https://uk.mathworks.com/help/map/examples/exporting-images-and-raster-grids-to-geotiff.html
but need to create georeferencing information from scratch, so using makerefmat and worldfilewrite to acheive this. The code below does not cause a crash, but generates a TIFF that image readers seem to struggle with, so I assume I'm doing something wrong. There may also be some redundancy as I haven't worked with TIFF tags before. Any help appreciated!
% Load image without georeferencing
RGB = imread('uk_dT.png');
% Create worldfile for image. At present this is done by first creating a
% reference matrix, then using these values to generate a worldfile.
% Longitude spans -17:10 (west to east), latitude 63:47 (north to south)
lonmin = -17; lonmax = 10; latmin = 47; latmax = 63;
DX = (lonmax-lonmin)/(length(RGB(1,:,1))); DY = (latmin-latmax)/(length(RGB(:,1,1)));
R = makerefmat(lonmin, latmax, DX, DY);
worldfilewrite(R,'uk_dT.tfw');
% Read worldfile, create geotiff
REF = worldfileread('uk_dT.tfw','geographic',size(RGB));
geotiffwrite('uk_dT.tif',RGB,REF)
Out of interest, this code was improved for me on another forum. The result still doesn't open in some image viewers, but I think that's to do with the class of the data. As I'm writing for GIS software this solution works for me.
file = 'uk_dT.png' ;
[path,name,ext] = fileparts(file) ;
I = imread(file) ;
lonmin = -17; lonmax = 10; latmin = 47; latmax = 63;
% Write to geotiff
R = georasterref('RasterSize',size(I),'LatitudeLimits', [latmin,latmax],'LongitudeLimits',[lonmin,lonmax]);
tiffile = strcat(name,'.tif') ;
geotiffwrite(tiffile,I,R)

Error on Extract hog Features from image sets of different dimensions in Matlab. ''Subscripted assignment dimension mismatch''

How could I perform hog feature extraction from image set of different dimensions? I am getting this error on last section.
''Subscripted assignment dimension mismatch.''
%% Change Directory
cd('C:\Users\inquisitive\Documents\MATLAB\hog_test');
%% Root Folder
rootFolder = fullfile('D:\HGDatabase');
%% Load Imagesets Database Directory
imgSets = imageSet(rootFolder,'recursive');
%%
{ imgSets.Description } % display all labels on one line
[imgSets.Count] % show the corresponding count of images
%% determine the smallest amount of images in a category
minSetCount = min([imgSets.Count]);
imgSets = partition(imgSets, minSetCount, 'randomize');
[imgSets.Count]
%% partioning into training and testing sets
[trainingSet, testSet] = partition(imgSets, 0.2, 'randomize');
*%%CAN'T I SKIP THIS SECTION AND DEFINE hog_16x16 ON LOOP ITSELF WHY I NEED TO PERFORM THIS AT FIRST WITH ONE IMAGE*
img = read(trainingSet(3), 4);
[hog_16x16, vis16x16] = extractHOGFeatures(img,'CellSize',[16 16]);
cellSize = [16 16];
hogFeatureSize = length(hog_16x16);
%%Extracting Hog Features
trainingFeatures = [];
trainingLabels = [];
for hand = 1:numel(trainingSet)
numImages = trainingSet(hand).Count;
features = zeros(numImages, hogFeatureSize, 'single');
for i = 1:numImages
img = read(trainingSet(hand), i);
% Apply pre-processing steps
lvl = graythresh(img);
img = im2bw(img, lvl);
features(i, :) = extractHOGFeatures(img, 'CellSize', cellSize);
end
labels = repmat(trainingSet(hand).Description, numImages, 1);
trainingFeatures = [trainingFeatures; features];
trainingLabels = [trainingLabels; labels ];
end
Other Query:
Which image format work best .jpg or .png? I thought .png would be better? Am i right?
I took some pictures and resize them by thinking that it may train in better way? Am i thinking right or wrong? Or is there nothing to do with different size of input. What would you suggest either to perform in same size or image sets with different dimensions.
CAN'T I SKIP FOLLOWING SECTION AND DEFINE hog_16x16 ON LOOP ITSELF WHY I NEED TO PERFORM THIS AT FIRST WITH ONE IMAGE? If i can skip how to deal with that case
img = read(trainingSet(3), 4);
[hog_16x16, vis16x16] = extractHOGFeatures(img,'CellSize',[16 16]);
cellSize = [16 16];
hogFeatureSize = length(hog_16x16);
You should ensure the dimensions of the image are the same as all images, then your extracted hog_16x16 features will have the same dimensions.

how do i mask labeled object based on some specified threshold value for each objects area,majoraxis and minoraxis?

i am currently using bwconnomp to label each connected object and regionpropsto find area, majoraxis, minoraxis of each labeled object respectively. i am also displaying each labeled object its area,majoraxis and minoraxis. now i want to set some threshold for area,majoraxis and minoraxis and if the value of area,majoraxis and minoraxis is above specified threshold then that object has to be masked.how this can be done??
here is my code
clc
clear all
close all
Index = 1;
scrsz = get(0,'ScreenSize');
%read an image
while Index ~= 0
% Open a dialog and select an image file
[FileName,FilePath,Index] = uigetfile('*.png', 'Open Imagefile ');
if Index == 0
disp('Procedure Done')
break;
end
inimage = imread([num2str(FilePath) FileName]);
D=inimage;
A=inimage;
subplot(2,3,1);
imshow(inimage);
title('original image');
%labeling algorithm
B=im2bw(inimage);
C=imfill(B,'holes');
label=bwlabel(C);
max(max(label))
CC = bwconncomp(B);
data = regionprops(CC,'all');
for j=1:max(max(label))
[row, col] = find(label==j);
len=max(row)-min(row)+2;
breadth=max(col)-min(col)+2;
target=uint8(zeros([len breadth] ));
sy=min(col)-1;
sx=min(row)-1;
for i=1:size(row,1)
x=row(i,1)-sx;
y=col(i,1)-sy;
target(x,y)=A(row(i,1),col(i,1));
end
mytitle=strcat('Object Number:' ,num2str(j),'area:', num2str(data(j).Area),'MajorAxis: ',num2str(data(j).MajorAxisLength),'MinorAxis: ',num2str(data(j).MinorAxisLength));
figure,imshow(target);title(mytitle);
a=size(target);
ax=a(1);
ay=a(2);
pos=[1,1,ay,ax];
rectangle('Position',pos,'EdgeColo','r')
end
next = input('next image? press Enter: ');
if next == 0
channelactivity = 0;
break
else
close all
disp('==================================')
pause(0.2)
continue
end
end
Here is a way to do it. The code is commented so easy to follow; the important line is the following:
AboveAreaIndices = find(vertcat(data.Area) > SomeValue)
In which you store the indices of the objects whose area is larger than SomeValue. In the example I color them red but you can do whatever you want with them or remove them altogether from the data structure.
You can also use logical operators to combine multiple conditions for example using the MinorAxis and MajorAxis properties. Note that I used AllArea as anew variable to store the concatenated areas to make things clearer, but you can keep them as vertcat(data.Area).
AboveIndices = find(vertcat(data.Area) > SomeValue & vertcat(data. MinorAxis) > SomeValue & Bla bla bla...);
Whole code:
clear
clc
close all
%// Read and clean up sample image
A = imread('rice.png');
A = im2bw(A,.5);
A = bwareaopen(A,50);
CC = bwconncomp(A);
%// Same as you.
data = regionprops(CC,'all');
%// Concatenate all the areas into an array.
AllArea = vertcat(data.Area);
%//========================================
%//==== Apply threshold on area here \\====
AboveAreaIndices = find(AllArea > 150);
%// If you wish to remove the entries from the data structure
% data(AllArea>150) = [];
%//========================================
%// Same for centroids...for display purposes
AllCentroids = vertcat(data.Centroid);
%// Display original and thresholded objects. Use the indices calculated
%// above to "mask" large areas if you want
imshow(A);
hold on
scatter(AllCentroids(:,1),AllCentroids(:,2),40,'b','filled')
scatter(AllCentroids(AboveAreaIndices,1),AllCentroids(AboveAreaIndices,2),40,'r','filled')
And sample output:

N-th largest component of bwconncomp including the background

My question has two parts. First one is:
How can I include the background as a component in the bwconncomp function, because it's default behavior doesn't include it.
Also, and this is my other question is, how can I select the n-th largest component based on what I get by using bwconncomp.
Currently I was thinking about something like this, but that doesn't work :P
function out = getComponent(im,n)
CC = bwconncomp(im,4);
%image is an binary image here
numPixels = cellfun(#numel,CC.PixelIdxList);
sortedPixels = sort(numPixels,'descend');
w = sortedPixels(n);
[largest, index] = find(numPixels==w);
im(CC.PixelIdxList{index}) = 0;
out = im;
But that doesn't work at all. But im not too sure what the CC.PixelIdxList{index} does, is it just changing elements in the array. I also find it kinda vague what exactly PixelIdxList is.
To find the background, you can use 'not' operation on the image
'PixelIdxList' is not what you need. You need the 'Area' property.
function FindBackgroundAndLargestBlob
x = imread('peppers.png');
I = x(:,:,2);
level = graythresh(I);
bw = im2bw(I,level);
b = bwlabel(bw,8);
rp = regionprops(b,'Area','PixelIdxList');
areas = [rp.Area];
[unused,indexOfMax] = max(areas);
disp(indexOfMax);
end
Update:
You can do it with bwconncomp as well:
function FindBackgroundAndLargestBlob
x = imread('peppers.png');
I = x(:,:,2);
level = graythresh(I);
bw = im2bw(I,level);
c = bwconncomp(bw,4);
numOfPixels = cellfun(#numel,c.PixelIdxList);
[unused,indexOfMax] = max(numOfPixels);
figure;imshow(bw);
bw( c.PixelIdxList{indexOfMax} ) = 0;
figure;imshow(bw);
end
Which will give the following results: