Related
I am trying to run the following code to analyze multiple .tif images in several different directories. Upon running the code, the figures that are given are blank, followed by the error on line 49 "M must be provided for packed erosion". I first realized I spelt .tif as .tiff in the code, which I changed. Then I decided that I would just read off one .tif image by creating a Tiff object and wrapping the image path in the tiff object. The console threw an error, saying that the file was unable to be opened.
Code
%% Import Spheroid Directory
Path = 'C:\Users\18606\OneDrive\Documents\Spheroids For Brandon\Spheroids For Brandon\1-8WT';
if ~isfolder(Path)
errorMsg = sprintf('Error: The following folder does not exist:\n%s',Path);
uiwait(warndlg(errorMsg));
return;
end
%% Iterate over each subfolder with .tiff images
Content = fullfile(Path, '*.tif'); % Read Experiment directory with .tiff images
subFold = dir(Content);
imageFiles = []; % Create empty list array
for k = 1:length(subFold)
F = fullfile(Path, subFold(k).name); % For k subfolders, output the full file name and open each subfolder
fileID = fopen(F);
imageFiles{end+1} = fopen(fileID,'%s\n'); % Append fileID to imageFiles list
fclose(fileID);
end
disp(imageFiles(k)) % Display the image files for analysis
%% Image preprocessing
%Divide image "obj" into its respective RGB intensities
red = imageFiles(:,:,1);
green = imageFiles(:,:,1);
blue = imageFiles(:,:,1);
figure(1)
subplot(2,2,1); imshow(imageFiles); title('Original Image')
subplot(2,2,2); imshow(imageFiles); title('Red Plane')
subplot(2,2,3); imshow(imageFiles); title('Green Plane');
subplot(2,2,4); imshow(imageFiles); title('Blue Plane');
%Threshold the blue plane
figure(2)
level = 0.37;
bw2 = imbinarize(blue, level);
subplot(2,2,1); imshow(bw2); title('Blue plane threshold');
%% Image preprocessing continued
fill = imfill(bw2,'holes');
subplot(2,2,2); imshow(fill); title('Holes filled')
%Remove any blobs on border of image
clear = imclearborder(fill);
subplot(2,2,3); imshow(clear); title('Blobs removed');
%Remove blobs smaller than 7 pixels across
se = strel('disk',7);
open = imopen(fill, se);
subplot(2,2,4); imshow(open); title('Removed small blobs');
%% Measure the number of pixels in Image
%numberOfPixels = numel(inputFile);
%[pixelCounts, grayLevels] = imhist(inputFile);
%numberofPixels = sum(pixelCounts);
%% Measure the distance of migration in micromolars
diameter = regionprops(open, 'MajorAxisLength');
%Show result
figure(3)
imshow(imageFiles)
d = imdistline; %Includes a line to physically measure the object
Error Msg
>> RawData
Error using images.internal.morphop>ParseInputs
M must be provided for packed erosion.
Error in images.internal.morphop (line 23)
unpacked_M,mex_method] = ParseInputs(varargin{:});
Error in imerode (line 87)
B = images.internal.morphop(A,se,'erode',mfilename,varargin{:});
Error in imopen (line 73)
outputImage = imdilate(imerode(inputImage,se,'ispacked',M),se,'ispacked',M);
Error in RawData (line 49)
open = imopen(fill, se);
I have a hunch that the file path is being read incorrectly, but the program is reading something, otherwise it would have thrown the error specified in the code. I appreciate any help I can get on this matter.
There are many things in your code that don't make sense.
fileID = fopen(F);
imageFiles{end+1} = fopen(fileID,'%s\n'); % Append fileID to imageFiles list
This opens the file, then puts its file name in imageFiles{end+1}. This is the same as just doing imageFiles{end+1} = F, but more confusing.
Later, you use imageFiles as if it was an image:
red = imageFiles(:,:,1);
But it's not an image, it is a cell array with the names (with path) of a set of files!
imshow(imageFiles) will load the images in that array, and show them to you. But other than that, you never load the images, so all computations you do, you are doing on the names of the files rather than the pixel data.
You want to use imread to load the pixel data. Don't fopen the files, just imread them.
I am trying to get pixel intensity values from regions of interest in RGB images.
I segmented the image and saved the regions of interest (ROI) using regionprops 'PixelList' in MATLAB, as shown below:
In this example I am using "onion.png" image built in MATLAB. (But in reality I have hundreds of images, and each of them have several ROIs hence why I'm saving the ROIs separately.)
%SEGMENTATION PROGRAM:
a=imread('C:\Program Files\MATLAB\MATLAB Production Server\R2015a\toolbox\images\imdata\onion.png');warning('off', 'Images:initSize:adjustingMag');
figure; imshow(a,[]);
nrows = size(a,1);ncols = size(a,2);
zr=ones(nrows,ncols); %matrix of ones
r=a(:,:,1);g=a(:,:,2);b=a(:,:,3); %get RGB values
rr=double(r);gg=double(g);bb=double(b);% convert to double to avoid uint8 sums
bgd=(rr+bb)./(2*gg); %calculation RGB ratio of background
zr1=bgd>1.15; %matrix containing background as 1 and ROI as 0
% remake binary image for holes command which requires white object to fill % (this step is not relevant for this example, but it is for my data)
zr2=zr1<0.5;
zr3=imfill(zr2, 'holes');
figure;imshow(zr3); pause;
roi=regionprops(zr3,'Centroid','PixelList','Area');
ar=[roi.Area];
% find sort order , largest first
[as, ia]=sort(ar(1,:),'descend');
for w=1:length(roi); xy(w,:)=roi(w).Centroid;end
% use sort index to put cenrtoid list in same order
xy1=xy(ia,:);
%and pixel id list
for w=1:length(roi)
roi2(w).PixelList=roi(ia(w)).PixelList;
end
%extract centriod positions as two colums
%SAVE PIXEL LIST FOR EACH ROI IN A SEPARATE FILE
for ww=1:w;
k=roi2(ww).PixelList;
save('onion_PL','k');
end
How do I use this pixel list to get the intensity values in the original image? More specifically, I need to get the ratio of pixels in Green channel over Red ("grr=rdivide(gg,rr);"), but only in the region of interest labeled with PixelList. Here's my code so far:
%PL is the PixelList output we got above.
a=imread('C:\Program Files\MATLAB\MATLAB Production Server\R2015a\toolbox\images\imdata\onion.png');warning('off', 'Images:initSize:adjustingMag');
PL=dir(['*PL.mat']); %load file PixelList files. "dir" is a variable with directory path containing the pixelist files. In this example, we saved "onion_PL.mat"
for m=1:length(PL);
load(PL(m).name);
ex=[]; %empty matrix to hold the extracted values
for mm=1:length(k);
%INSERT ANSWER HERE
end
This next bit is wrong because it's based on the entire image ("a"), but it contains the calculations that I would like to perform in the ROIs
figure; imshow(a,[]);
pause;
nrows = size(a,1);ncols = size(a,2);
zr=ones(nrows,ncols); %matrix of ones
r=a(:,:,1);g=a(:,:,2);b=a(:,:,3); %get RGB values
rr=double(r);gg=double(g);bb=double(b);% convert to double to avoid uint8 sums
grr=rdivide(gg,rr);
I am brand new to MATLAB, so my code is not the greatest... Any suggestions will be greatly appreciated. Thank you in advance!
The loop you are looking for seems simple:
grr = zeros(nrows, ncols); % Initialize grr with zeros.
for mm = 1:length(k)
x = k(mm, 1); % Get the X (column) coordinate.
y = k(mm, 2); % Get the Y (row) coordinate.
grr(y, x) = gg(y, x) / rr(y, x);
end
A more efficient solution is using sub2ind for converting the x,y coordinates to linear indices:
% Convert k to linear indices.
kInd = sub2ind([nrows, ncols], k(:,2), k(:,1));
% Update only the indices in the PixelList.
grr(kInd) = rdivide(gg(kInd), rr(kInd));
In your given code sample there are 5 PixelLists.
I don't know how do you want to "arrange" the result.
In my code sample, I am saving the 5 results to 5 mat files.
Here is an executable code sample:
close all
%SEGMENTATION PROGRAM:
a=imread('onion.png');warning('off', 'Images:initSize:adjustingMag');
figure; imshow(a,[]);
nrows = size(a,1);ncols = size(a,2);
zr=ones(nrows,ncols); %matrix of ones
r=a(:,:,1);g=a(:,:,2);b=a(:,:,3); %get RGB values
rr=double(r);gg=double(g);bb=double(b);% convert to double to avoid uint8 sums
bgd=(rr+bb)./(2*gg); %calculation RGB ratio of background
zr1=bgd>1.15; %matrix containing background as 1 and ROI as 0
% remake binary image for holes command which requires white object to fill % (this step is not relevant for this example, but it is for my data)
zr2=zr1<0.5;
zr3=imfill(zr2, 'holes');
figure;imshow(zr3); %pause;
roi=regionprops(zr3,'Centroid','PixelList','Area');
ar=[roi.Area];
% find sort order , largest first
[as, ia]=sort(ar(1,:),'descend');
for w=1:length(roi); xy(w,:)=roi(w).Centroid;end
% use sort index to put cenrtoid list in same order
xy1=xy(ia,:);
%and pixel id list
for w=1:length(roi)
roi2(w).PixelList=roi(ia(w)).PixelList;
end
%extract centroid positions as two columns
%SAVE PIXEL LIST FOR EACH ROI IN A SEPARATE FILE
for ww=1:w
k=roi2(ww).PixelList;
%save('onion_PL', 'k');
save(['onion', num2str(ww), '_PL'], 'k'); % Store in multiple files - onion1_PL.mat, onion2_PL.mat, ... onion5_PL.mat
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear % Use clear for testing - the variables are going to be read from the mat file.
%PL is the PixelList output we got above.
a=imread('onion.png');warning('off', 'Images:initSize:adjustingMag');
nrows = size(a,1);ncols = size(a,2);
zr=ones(nrows,ncols); %matrix of ones
r=a(:,:,1);g=a(:,:,2);b=a(:,:,3); %get RGB values
rr=double(r);gg=double(g);bb=double(b);% convert to double to avoid uint8 sums
grr=rdivide(gg,rr);
PL=dir('*PL.mat'); %load file PixelList files. "dir" is a variable with directory path containing the pixelist files. In this example, we saved "onion_PL.mat"
for m = 1:length(PL)
load(PL(m).name);
ex=[]; %empty matrix to hold the extracted values
%for mm=1:length(k)
%INSERT ANSWER HERE
grr = zeros(nrows, ncols); % Initialize grr with zeros.
for mm = 1:length(k)
x = k(mm, 1); % Get the X (column) coordinate.
y = k(mm, 2); % Get the Y (row) coordinate.
grr(y, x) = gg(y, x) / rr(y, x);
end
% Instead of using a loop, it's more efficient to use sub2ind
if false
% Convert k to linear indices.
kInd = sub2ind([nrows, ncols], k(:,2), k(:,1));
% Update only the indices in the PixelList.
grr(kInd) = rdivide(gg(kInd), rr(kInd));
end
figure;imshow(grr);title(['grr of m=', num2str(m)]) % Show grr for testing.
save(['grr', num2str(m)], 'grr'); % Save grr for testing.
imwrite(imadjust(grr, stretchlim(grr)), ['grr', num2str(m), '.png']); % Store grr as image for testing
end
First two grr matrices as images (used for testing):
grr1.png:
grr2.png:
i have an image descriptor in a file.modQDH i need to display this image
this is my code
imagefiles = dir('*.modQDH');
nfiles = length(imagefiles); % Number of files found
fprintf('number est ');
fprintf('%d ',nfiles );
fprintf('%n');
A = importdata('obj1__0.modQDH');
disp(A);
when i use disp(a) the result is my vetcor
but me i need the image corresponding to this vector
i have used image(A) and imshow (A) but it doesn't works
disp shows the value of a variable, it does not create an image rendering
see
http://www.mathworks.com/help/matlab/ref/disp.html
try using imagesc which attempts to take care of some of the scaling issues
I have almost 80 dicom images in a folder. Now, I want to convert these series of dicom images to a 3d volume.
Below is the code which loads MRI data, forms counter slices and then generates 3d volume. But, it loads inbuilt MRI images.
How can I change this program to load dicom images from my folder and display 3d volume??
load mri
D = squeeze(D);
%figure
colormap(map)
image_num = 8;
image(D(:,:,image_num))
axis image
x = xlim;
y = ylim;
cm = brighten(jet(length(map)),-.5);
figure
colormap(cm)
contourslice(D,[],[],image_num)
axis ij
xlim(x)
ylim(y)
daspect([1,1,1])
figure
colormap(cm)
contourslice(D,[],[],[1,12,19,27],8);
view(3);
axis tight
figure
colormap(map)
Ds = smooth3(D);
hiso = patch(isosurface(Ds,5),...
'FaceColor',[1,.75,.65],...
'EdgeColor','none');
isonormals(Ds,hiso)
hcap = patch(isocaps(D,5),...
'FaceColor','interp',...
'EdgeColor','none');
view(35,30)
axis tight
daspect([1,1,.4])
lightangle(45,30);
lighting gouraud
hcap.AmbientStrength = 0.6;
hiso.SpecularColorReflectance = 0;
hiso.SpecularExponent = 50;
we can use fullfile which returns a string containing the full path to the file. and dir which returns a list of files and folders that match the string name. When name is a folder, dir lists the contents of the folder. Specify name using absolute or relative path names. name can include wildcards (*).
and rest of the things are well commented in program.
clear all;
close all;
clc;
fileFolder = fullfile('series 9');
files = dir ( fullfile (fileFolder, '*.dcm'));
fileNames = {files.name};
%examine file header (metadata , from dicom stack)
info = dicominfo(fullfile(fileFolder,fileNames{1}));
%extract size info from metadata
voxel_size = [info.PixelSpacing;info.SliceThickness];
%read one file to get size
I = dicomread(fullfile(fileFolder,fileNames{1}));
classI = class(I);
sizeI = size(I);
numImages = length(fileNames);
%read slice images populate 3d matrix
hWaitBar = waitbar(0,'reading dicom files');
%create array
mri= zeros(sizeI(1),sizeI(2), numImages , classI );
for i=length(fileNames):-1:1
fname = fullfile(fileFolder, fileNames{i});
mri(:,:,i) = uint16(dicomread(fname));
waitbar((length(fileNames)-i+1)/length(fileNames))
end
delete(hWaitBar);
I am trying to perform image analysis to get the boundary of an image. The problem is, there is an overlap of more than one point on the data. The problem occurs due to the pixel width of the boundary. ie, my algorithm reads the image, and because the boundary is thick, I get multiple ( sometimes 2 or 3) data points that represent the boundary .As you can see in the image, I have analysed an image and have the scatter plot showing the coordinates. The boundary has more than one element representing it. I need to reduce my vectors (of coordinates) such that a boundary is represented by only one line. I attach the code along with the question for your reference. I am doing this so as to get one single data that can represent the whole image.
clc;close all;
clear all;
folder = 'C:\Users\Adi\Desktop'; % image folder
baseFileName = 'part8.jpg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
rgbImage = imread(fullFileName); % read the image
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows, columns, numberOfColorBands] = size(rgbImage);
figure;
greenChannel = rgbImage(:, :, 2);
binaryImage = greenChannel < 200; % convert image to BW
imshow(binaryImage);
i=1;
j=1;
data=zeros(rows,columns);
n=1;% sample every n rows or col of the image
img2=zeros(rows/n,columns/n);
for col=1:n:columns %reducing the size of the image
for row=1:n:rows
if(binaryImage(row,col)==1)
% data(row,col)=1;
x(i)=row;
y(i)=col; % locate where the image is present
img2(x(i),y(i))=1;
i=i+1;
end
end
end
figure;
scatter(x,y);
figure;
imshow(img2);
blankImage=zeros(length(1:rows),length(1:columns));
m=1; % counter variable
for k=2:rows-1
for l=2:columns-1
if((binaryImage(k+1,l)==0)&&(binaryImage(k,l+1)==0)&&(binaryImage(k-1,l)==0)&&(binaryImage(k,l-1)==0)&&(binaryImage(k,l)==0))
% % if all surrounding pixels are black, ignore them
blankImage(k,l)=0;
elseif((binaryImage(k+1,l)==1)&&(binaryImage(k,l+1)==1)&&(binaryImage(k-1,l)==1)&&(binaryImage(k,l-1)==1)&&(binaryImage(k,l)==1))
%if all surrounding pix are white ,ignore them
blankImage(k,l)=0;
else
blankImage(k,l)=1; % get the boundary elements
x_brep(m)=k;
y_brep(m)=l;
m=m+1;
end
end
end
figure;
imshow(blankImage);
figure;
scatter(x_brep,y_brep);
Sample image and output:
If you have the image processing toolbox, you can take your original image, and use bwmorph - for example, thin or skel, to reduce it to a single pixel line. Note that you may need to invert your image (so that it is a white line on a black background).
Presuming your original image as shown is already binary and is stored in BW (but with line as black on white), it should be as simple as (~BW just inverts the image).
BW2 = bwmorph(~BW,'thin', Inf);
If your image is not already binary you will need to convert it to binary first.