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.
Related
I have a folder which contains 200 BMP images, I am reading all the images, converting each image into a vector and then trying to store these image vectors into a matrix. Following is the code which is self-explanatory, though it looks quite right however when i run the script it gives me the following error.
Error in Readallimages (line 16)
immat(437580,k)=imtovector
Subscripted assignment dimension mismatch.`
myFolder = 'C:\Users\Sana\Desktop\DermoscopyImages';
if ~isdir(myFolder)
errorMessage = sprintf('Error: The following folder does not exist:\n%s',
myFolder);
uiwait(warndlg(errorMessage));
return;
end
filePattern = fullfile(myFolder, '*.bmp');
bmpFiles = dir(filePattern);
immat=zeros(437580,200);
for k = 1:length(bmpFiles)
baseFileName = bmpFiles(k).name;
fullFileName = fullfile(myFolder, baseFileName);
fprintf(1, 'Now reading %s\n', fullFileName);
imageArray = rgb2gray(imread(fullFileName)); %Read images
imtovector=double(imageArray(:)); %Convert 2D image to 1D vector
immat(437580,k)=imtovector %Store image vector to matrix
imshow(imageArray); % Display image.
drawnow; % Force display to update immediately.
end`
Any type of help in this regard would highly be appreciated.
Thanks inadvance
I have the following code:
a = imaqhwinfo;
%[camera_name, camera_id, format] = getCameraInfo(a);
% Capture the video frames using the videoinput function
% You have to replace the resolution & your installed adaptor name.
% vid = videoinput('winvideo', 1);
vid = VideoReader('C:\VHDL Project\VHDL Course\Logtel\Image processing\Sacramento Kings vs Golden State Warriors.mp4')
% Set the properties of the video object
set(vid, 'FramesPerTrigger', Inf);
set(vid, 'ReturnedColorspace', 'rgb')
vid.FrameGrabInterval = 5;
%start the video aquisition here
start(vid)
% Set a loop that stop after 100 frames of aquisition
while(vid.FramesAcquired<=200)
% Get the snapshot of the current frame
data = getsnapshot(vid);
% Now to track red objects in real time
% we have to subtract the red component
% from the grayscale image to extract the red components in the image.
diff_im = imsubtract(data(:,:,1), rgb2gray(data));
%Use a median filter to filter out noise
diff_im = medfilt2(diff_im, [3 3]);
% Convert the resulting grayscale image into a binary image.
diff_im = im2bw(diff_im,0.18);
% Remove all those pixels less than 300px
diff_im = bwareaopen(diff_im,300);
% Label all the connected components in the image.
bw = bwlabel(diff_im, 8);
% Here we do the image blob analysis.
% We get a set of properties for each labeled region.
stats = regionprops(bw, 'BoundingBox', 'Centroid');
% Display the image
imshow(data)
hold on
%This is a loop to bound the red objects in a rectangular box.
for object = 1:length(stats)
bb = stats(object).BoundingBox;
bc = stats(object).Centroid;
rectangle('Position',bb,'EdgeColor','r','LineWidth',2)
plot(bc(1),bc(2), '-m+')
a=text(bc(1)+15,bc(2), strcat('X: ', num2str(round(bc(1))), ' Y: ', num2str(round(bc(2)))));
set(a, 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');
end
hold off
end
% Both the loops end here.
% Stop the video aquisition.
stop(vid);
% Flush all the image data stored in the memory buffer.
flushdata(vid);
% Clear all variables
clear all
sprintf('%s','That was all about Image tracking, Guess that was pretty easy :) ')
I try to read a MP4 file, run it and find reds objects.
Unfortunately the tool pop up me the following error:
Error using VideoReader/set
The name 'FramesPerTrigger' is not an accessible property for an instance of class 'VideoReader'.
Error in RedObjectTracking (line 11)
set(vid, 'FramesPerTrigger', Inf);
I would be happy if someone can tell me where my mistake
Thanks for the help.
If you look at the documentation for VideoReader you will see that (as your error says) FramesPerTrigger is not listed as a valid property. Based on more of the documentation for FramesPerTrigger, it is a property that is only used for video devices in the image acquisition toolbox (similar to the videoinput that you have commented out on the line before. So the line where you attempt to set the FramesPerTrigger value shouldn't be there when you're only using a video file input via VideoReader.
This also makes sense, as your image acquisition system will have triggers and it is important for MATLAB to know how many frames to grab for each trigger. A video file, on the other hand (which VideoReader is intended to handle) has no triggers and the frame information is readily available from the file itself.
It looks, based on your code, that you're trying to simply substitute VideoReader in for videoinput but this will not work so there are many points throughout your code which will result in errors.
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 draw several x-marks on a binary image to some co-ordinates.
My output should look like this
To do this i have written some codes below
clear all;
% Here four co-ordinates are provided as an example. In my main code the co- ordinates will be hundred or thousands
position{1}.x = 10;
position{1}.y = 10;
position{2}.x = 20;
position{2}.y = 20;
position{3}.x = 30;
position{3}.y = 30;
position{4}.x = 40;
position{4}.y = 40;
% Read image as binary
image = imread('test34.jpg');
figure('name','Main Image'),imshow(image);
gray_image=rgb2gray(image);
level = graythresh(gray_image);
binary_image = im2bw(image,level);
% Define color of the x-marker and initializing shapes which i want to draw
red = uint8([255 0 0]);
markerInserter = vision.MarkerInserter('Shape','X-mark','BorderColor','Custom','CustomBorderColor',red);
i = 1;
% The loop will continue to the number of co-ordinates which will never be predefined in my main code
while i<=numel(position)
% Converting binary to RGB for only once.
if i == 1
rgb = repmat(binary_image, [1, 1, 3]);
else
rgb = repmat(binary_image, [1, 1, 1]);
end
% Position where x-marks will be drawn
Pts = int32([position{i}.x position{i}.y]);
% Draw x-marks
binary_image = step(markerInserter, rgb, Pts);
i = i+1;
end
figure('name','binary_image'),imshow(binary_image);
But i am getting these errors
Error using images.internal.imageDisplayValidateParams>validateCData
(line 119)
If input is logical (binary), it must be two-dimensional.
Error in images.internal.imageDisplayValidateParams (line 27)
common_args.CData = validateCData(common_args.CData,image_type);
Error in images.internal.imageDisplayParseInputs (line 78)
common_args = images.internal.imageDisplayValidateParams(common_args);
Error in imshow (line 227)
[common_args,specific_args] = ...
Error in test2 (line 39)
figure('name','binary_image'),imshow(binary_image);
I have tried some examples but they are experimented on RGB image while i need it on binary image and that's where i am getting errors.
Why i am getting these errors and what will be the solution?
Please provide explanation with proper code.
You code seems a bit complicated (to me) for what it is intended. Here is a simple example demonstrating how to draw red crosses using scatter on a binary image. As you see, the image in itself is binary and the markers are in color, so the 'net' image is no longer binary... Also, there is no need to convert your RGB image to graylevels before applying im2bw.
And don't forget to use hold on to avoid discarding the image when adding the markers!
Here is the code with comments:
clear
clc
close all
%// Read image
MyImage = imread('peppers.png');
%// Convert to binary. No need to use rgb2gray.
MyBWImage = im2bw(MyImage(:,:,2));
%// Define some x- and y positions for markers
xpositions = linspace(10,300,40);
ypositions = linspace(20,500,40);
imshow(MyBWImage)
%// IMPORTANT!!
hold on
%// Draw markers
scatter(xpositions.',ypositions.',80,'r','x')
With output:
Is this what you meant?
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.