diff --git a/src/albina nirupa/classificationcode.m b/src/albina nirupa/classificationcode.m new file mode 100644 index 0000000..cf87765 --- /dev/null +++ b/src/albina nirupa/classificationcode.m @@ -0,0 +1,27 @@ +%% +mkdir('E:\Experiments\odroid\A2\A2a\cells\rbc'); +mkdir('E:\Experiments\odroid\A2\A2a\cells\cluster'); +mkdir('E:\Experiments\odroid\A2\A2a\cells\wbc'); +mkdir('E:\Experiments\odroid\A2\A2a\cells\parasite'); +%% +%Classifier Function obtained after training the classifier with the +%generated training data set and the feature table +% There are 4 different catergories of classification +X = table2array(varfun(@double, CellFeature_table_A(:,trainedClassifiercells.PredictorNames))); +cellclass = predict(trainedClassifiercells, X); + +for i = 1:length(cellclass) + image = imread(strcat('E:\Experiments\odroid\A2\A2a\cells\A1 (',num2str(i),').jpg')); + if(cellclass(i)== 'rbc') + imwrite(image,strcat('E:\Experiments\odroid\A2\A2a\cells\rbc\',num2str(i),'.jpg'),'jpeg'); + else if (cellclass(i)== 'wbc') + imwrite(image,strcat('E:\Experiments\odroid\A2\A2a\cells\wbc\',num2str(i),'.jpg'),'jpeg'); + else if (cellclass(i)== 'cluster') + imwrite(image,strcat('E:\Experiments\odroid\A2\A2a\cells\cluster\',num2str(i),'.jpg'),'jpeg'); + else if (cellclass(i)== 'parasite') + imwrite(image,strcat('E:\Experiments\odroid\A2\A2a\cells\parasite\',num2str(i),'.jpg'),'jpeg'); + end + end + end + end +end \ No newline at end of file diff --git a/src/albina nirupa/createMask.m b/src/albina nirupa/createMask.m new file mode 100644 index 0000000..c6116f4 --- /dev/null +++ b/src/albina nirupa/createMask.m @@ -0,0 +1,37 @@ +function [BW,maskedRGBImage] = createMask(RGB,Imax,Imin) +%createMask Threshold RGB image using auto-generated code from colorThresholder app. +% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using +% auto-generated code from the colorThresholder App. The colorspace and +% minimum/maximum values for each channel of the colorspace were set in the +% App and result in a binary mask BW and a composite image maskedRGBImage, +% which shows the original RGB image values under the mask BW. + +% Auto-generated by colorThresholder app on 12-Dec-2015 +%------------------------------------------------------ + + +% Convert RGB image to chosen color space +I = RGB; + +% Define thresholds for channel 1 based on histogram settings +channel1Min = Imin;%132.000; +channel1Max = Imax;%182.000; + +% Define thresholds for channel 2 based on histogram settings +channel2Min = channel1Min;%131.000; +channel2Max = channel1Max;%177.000; + +% Define thresholds for channel 3 based on histogram settings +channel3Min = channel1Min;%130.000; +channel3Max = channel1Max;%180.000; + +% Create mask based on chosen histogram thresholds +BW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ... + (I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ... + (I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max); + +% Initialize output masked image based on input image. +maskedRGBImage = RGB; + +% Set background pixels where BW is false to zero. +maskedRGBImage(repmat(~BW,[1 1 3])) = 0; diff --git a/src/albina nirupa/whole_blood_segment_odroid.m b/src/albina nirupa/whole_blood_segment_odroid.m new file mode 100644 index 0000000..3e7a396 --- /dev/null +++ b/src/albina nirupa/whole_blood_segment_odroid.m @@ -0,0 +1,223 @@ +%% +%The code creates a feature table for the different types of cells and +%is used to create a initial training dataset for the classifier + +%% +clc ; +close all; +clear all; +%% +mkdir('E:\Experiments\odroid\S\S1\gate1'); +mkdir('E:\Experiments\odroid\S\S1\gate2'); +mkdir('E:\Experiments\odroid\S\S1\gate3'); +mkdir('E:\Experiments\odroid\S\S1\gate4'); +mkdir('E:\Experiments\odroid\S\S1\P'); +%% +% To create a circular mask to eliminate the spokes channels and perform +% processing of cells in the central imaging region +% Create a logical image of a circle with specified +% diameter, center, and image size. +% First create the image. +imageSizeX = 640; %X pixel size of the image +imageSizeY = 480; %Y pixel size of the image +[columnsInImage rowsInImage] = meshgrid(1:imageSizeX, 1:imageSizeY); +% Next create the circle in the image. +centerX = 300; %center X pixel of the circle +centerY = 240; %center y pixel of the circle +radius = 220; %Radius of the circle +circlePixels = (rowsInImage - centerY).^2 ... + + (columnsInImage - centerX).^2 <= radius.^2; % creates the circular mask + +%% Generate Background +%a = rgb2gray(imread(strcat('E:\Experiments\odroid\step1\1 (',num2str(V),').jpg'))); +%imshow(a); +%%% average ten frames to generate background. +bg = 0; V=1; +count = 500 ;% set number of frame to be averaged +N = 1; % start frame number +for i = N:N+count + bg = bg +double(rgb2gray((imread(strcat('E:\Experiments\odroid\S\S1\1 (',num2str(V+i),').jpg'))))); +end +bg = uint8(bg /count); % Final Background generated. +imshow(uint8(circlePixels).*bg); +%% +tic +r =0;b=0; +count = 0; +maxglcm = 0; +Cont =0;Corr=0;Homo=0;I_mean=0;I_std=0;I_cir=0;I_area =0;stain=0; + ccount = 0; + C_Percentstained =0;StainMaxlength=0;StainMinlength=0;StainSolid=0; StainNumobj=0; + Features_table = [];F=[]; +CellFeature_table = [];cell=[]; +% Feature_table = table('VariableNames',{'Area', 'ConvexArea', 'Eccentricity', 'EquivDiameter', 'EulerNumber', 'Extent', 'FilledArea', 'MajorAxisLength', 'MinorAxisLength', 'Orientation', 'Perimeter', 'Solidity'}); + for V =1:29999 + disp(V); +Shape_Features =[]; Texture_Features1 = []; +% The if condition is used to refresh the background for every 2000 frames +% This helps eliminate any debris/ struck cells in the ROI +if mod(V,2000) == 0 + %if V <19999-30 +% bg1 = bg; +bg =0; +count = 300 ;% set number of frame to be averaged +N = 1; % start frame number +for i = N:N+count + bg = bg +double(rgb2gray((imread(strcat('E:\Experiments\odroid\S\S1\1 (',num2str(V+i),').jpg'))))); +end +bg = uint8(bg /count); % Final Background generated. +% bg = (bg+bg1)/2.0 +end + % The following section performs the segmentation based on histogram values + CurrFrame = (rgb2gray((imread(strcat('E:\Experiments\odroid\S\S1\1 (',num2str(V),').jpg'))))); + Sub =double(double(CurrFrame.*uint8(circlePixels))-double(bg.*uint8(circlePixels))); + %imshow(Sub); + Submin = min(Sub(:)); + Submax = max(Sub(:)); + AdjBGSub = uint8( (Sub - Submin)/(Submax-Submin) * 255); + Ia = AdjBGSub; + [A, B]=size(Ia); + I = medfilt2(Ia); % To smoothen the image + I = adapthisteq(I); +I1 = medfilt2(I); +Irgb = cat(3, I1, I1, I1); +meanIntensityValue(V) = mean2(I1); % Finds the mean of the intensities of the image pixels +stdIntensityValue = std2(I1); % Finds the standard deviation of the intensities of the image pixels +% Selection of max and minimum of intensities for the thresholding +%This multipication factor can be varied when you are optimizing the +%thresholding +Imax = meanIntensityValue(V)+stdIntensityValue*4; % mean+ 4*standard deviation +Imin = meanIntensityValue(V)-stdIntensityValue*4; % mean- 4*standard deviation +% Further processing of the thresholded image +Mask = createMask(Irgb,Imax,Imin);%figure;imshow(Mask); +MaskInv = ~Mask; +Maskopen =bwareaopen(MaskInv,150);%figure;imshow(Maskfinal); +% Maskdil = imdilate(Maskopen, [se90 se0]);%figure;imshow(Maskdil); +Maskdil = imclose(Maskopen, strel('disk',5)); +Maskfill = imfill(Maskdil, 'holes');%figure;imshow(Maskfill); +Maskclose = Maskfill; +% Maskclose = imclose(Maskfill, strel('disk',5)); +Maskclear = imclearborder(Maskclose, 4);%figure;imshow(Maskclear); +Maskfinal = Maskclear; +% Filter image based on image properties. +Maskfinal = bwpropfilt(Maskfinal, 'Area', [350 + eps(350), Inf]); % Area greater than 350 pixels +Maskfinal = bwpropfilt(Maskfinal, 'Solidity', [0.6 + eps(0.6), Inf]); % 1 is completely solid region +Maskfinal = bwpropfilt(Maskfinal, 'EulerNumber', [4.94065646e-324 + eps(4.94065646e-324), Inf]); +%Extract properties of all the cells in the thresholded image +Maskproperties = regionprops(Maskfinal, {'Area', 'ConvexArea', 'Eccentricity', 'EquivDiameter', 'EulerNumber', 'Extent', 'FilledArea', 'MajorAxisLength', 'MinorAxisLength', 'Orientation', 'Perimeter', 'Solidity'}); +% Creates a feature table of all the above listed properties for all the +% segmented cells/regions in the image +Shape_Features = struct2table(Maskproperties); +%Plotting of 200 images to see the performance of segmetation operations +if V<200 +h= figure; +subplot(2,3,1); +subimage(Mask); +title('Mask'); + +subplot(2,3,2); +subimage(Maskfill); +title('Maskfill'); + +subplot(2,3,3); +subimage(Maskdil); +title('Maskdil'); + +subplot(2,3,4); +subimage(uint8(MaskInv).*I1); +title('Maskclose'); +% subplot(1,2,1); +subplot(2,3,5); +subimage(I1); +title('I1'); +% subplot(1,2,2); +subplot(2,3,6); +subimage(uint8(Maskfinal).*I1); +title(' Maskfinal'); +%saveas(h,strcat('E:\Experiments\odroid\S\S1\gate4\FrameNumber','-',num2str(V)),'jpg'); + close(h); +% figure;imshow(uint8(Maskfinal).*I); +% figure;imshow(I); +end +% Generation of the traning images for the classification program +CComp = bwconncomp(Maskfinal); +Areas = regionprops(CComp,'Area'); +Centroids1=regionprops(CComp,'Centroid'); +Perimeters=regionprops(CComp,'Perimeter'); +Texture_Features=[]; +for i = 1:CComp.NumObjects + Cent = Centroids1(i).Centroid; + HighX = round(Cent(1))+20; + if HighX>B + HighX =B; + end + HighY = round(Cent(2))+20; + if HighY>A + HighY =A; + end + LowX = round(Cent(1))-19; + if LowX<=0 + LowX =1; + end + + LowY = round(Cent(2))-19; + if LowY<=0 + LowY =1; + end + + ccount = ccount +1;%,num2str(V),'.avi' + Icrop=Ia(LowY:HighY,LowX:HighX); + Icrop1=I(LowY:HighY,LowX:HighX); + Maskcrop=Maskfinal(LowY:HighY,LowX:HighX); + imwrite(Icrop,strcat('E:\Experiments\odroid\S\S1\gate3\FrameNumber','-',num2str(V),'_',num2str(ccount),'.jpg')); + % Additional texture features for the feature table + glcm = graycomatrix(Icrop1);%gray level covariance matrix + maxglcm(ccount)=max(max(glcm)); %Feature 1 + stats(ccount) = graycoprops(glcm,{'Contrast','Correlation','homogeneity'}); + Texture_Features = struct2table(stats(ccount)); +% Cont(ccount)= stats(ccount).Contrast; %Feature 2 +% Corr(ccount) = stats(ccount).Correlation; %Feature 3 +% Homo(ccount)= stats(ccount).Homogeneity;%Feature 4 +% Ent(ccount)= stats(ccount).Entropy; + I_mean(ccount) = mean2(Icrop1); %Feature 5 + I_std(ccount)=std2(Icrop1); %Feature 6 + I_cir(ccount) = ((Shape_Features.Perimeter(i))^ 2)/ (4 * pi * Shape_Features.Area(i)); %Feature 7 + + % Percentage of stained area + BWthresh = im2bw(Icrop,0.15); + BWthreshtemp =~(BWthresh).*Maskcrop; + CC1 =bwconncomp(imcomplement(BWthresh).*Maskcrop); + MaxLength = regionprops(CC1,'MajorAxisLength'); + MinLength = regionprops(CC1,'MinorAxisLength'); + Solid = regionprops(CC1,'Solidity'); +% imwrite(~BWthresh,strcat('E:\Experiments\odroid\A2\A2a\gate2\FrameNumber','-',num2str(V),'_',num2str(ccount),'.jpg')); + Areas_stained = regionprops(CC1,'Area'); + StainNumobj(ccount) = CC1.NumObjects; + if CC1.NumObjects ==0 + C_Percentstained(ccount) = 0; + StainMaxlength(ccount) = 0;StainMinlength(ccount) = 0; + StainSolid(ccount) = 0; StainSolid(ccount) = 0; + else + if (max(struct2array(MaxLength))/max(struct2array(MinLength)))<2 + F = [F; max(struct2array(MaxLength))/max(struct2array(MinLength))]; +% imwrite(Icrop,strcat('E:\Experiments\odroid\A2\A2a\P\FrameNumber','-',num2str(V),'_',num2str(ccount),'.jpg')); + end + C_Percentstained(ccount) = sum(struct2array(Areas_stained))/max((Shape_Features.Area(i)))*100; + StainMaxlength(ccount) = max(struct2array(MaxLength)); + StainMinlength(ccount) = max(struct2array(MinLength)); + StainSolid(ccount) = max(struct2array(Solid)); + % Stainproperties = regionprops(BWthreshtemp, {'Area', 'ConvexArea', 'Eccentricity', 'EquivDiameter', 'EulerNumber', 'Extent', 'FilledArea', 'MajorAxisLength', 'MinorAxisLength', 'Orientation', 'Perimeter', 'Solidity'}); +% Parasite_Features = struct2table(Stainproperties); + end + Texture_Features1 = [Texture_Features; Texture_Features1]; +end +if CComp.NumObjects>0 + Features = [Shape_Features Texture_Features1]; %Variable Addition + +Features_table = [Features_table; Features]; % Table update + end + cell = table(I_mean', I_std', I_cir', maxglcm', C_Percentstained',StainMaxlength',StainMinlength',StainSolid', StainNumobj'); + cell.Properties.VariableNames = {'Mean' 'Std' 'Circularity' 'MaxGLCM' 'Percentage_Stain' 'StainMaxlength' 'StainMinlength' 'StainSolid' 'StainNumobj'}; + CellFeature_table = [Features_table cell]; % Table update + end + toc \ No newline at end of file