Batch Processing Image Files in MATLAB - matlab

I'm a beginner in MATLAB and image processing.
I encountered a problem while trying to use the batch processing and hope someone would be able to enlighten me. Thanks.
Following the example from MATLAB, I did these:
p = which('Picture1.tif');
filelist = dir([fileparts(p) filesep 'Picture*.tif']);
fileNames = {filelist.name}'
I = imread(fileNames{1});
imshow(I)
Because I wanted to select the region of interest,
BW = roipoly(I);
BW1 = not(BW);
N = roifill(I,BW1);
After I selected the ROI, I created a function in the editor:
function Segout = DetectLines(N)
[junk threshold] = edge(N, 'sobel');
fudgeFactor = .5;
BWs = edge(N, 'sobel', threshold*fudgeFactor);
se90 = strel('line', 3, 90);
se0 = strel('line', 3, 0);
BWsdil = imdilate(BWs, [se90 se0]);
BWdfill = imfill(BWsdil, 'holes');
BWnobord = imclearborder(BWdfill, 4);
seD = strel('diamond', 1);
BWfinal = imerode(BWnobord, seD);
BWfinal = imerode(BWfinal, seD);
BWoutline = bwperim(BWfinal);
Segout = N;
Segout(BWoutline) = 255;
end
Back to the command window, I typed;
Segout = DetectLines(N);
figure, imshow(Segout)
The figure that came out was what I expected.
The problem comes now when I try to loop over images. I'm not sure if I've done it
correctly.
Following the example, I created another function in the editor;
function SegoutSequence = BatchProcessFiles(fileNames, fcn)
N = imread(fileNames{1});
[mrows, ncols] = size(N);
nImages = length(fileNames);
SegoutSequence = zeros(mrows, ncols, nImages, class(N));
parfor (k = 1:nImages)
N = imread(fileNames{k});
SegoutSequence(:,:,k) = fcn(N);
end
end
At the command window, I typed:
SegoutSequence = BatchProcessFiles(fileNames, #DetectLines);
implay(SegoutSequence)
However, the result was not what I wanted it to be. It was not the ROI that I wanted. Can anyone help me with this? Thank you very much.
Picture1:
Picture1 after selecting ROI:

Lookin at your code, you only selected the ROI once for the image you tested individually.
However, when you call the BatchProcessFiles function, you dont select a region of interest, and the DetectLines function is applied to the raw images... Therefore you need to pass the mask you created with roipoly to your BatchProcessFiles function to do the same on all the images.
As a side note, you might get better results if you try Hough transformation to detect the lines.
Also your code breaks if the images are not grayscale (you can add a call to rgb2gray() to be on the safe side)
Sample solution:
MATLAB
I = imread(fileNames{1});
BW = not( roipoly(I) );
SegoutSequence = BatchProcessFiles(fileNames, BW, #DetectLines);
implay(SegoutSequence)
BatchProcessFiles.m
function SegoutSequence = BatchProcessFiles(fileNames, Mask, fcn)
% ...
parfor (k = 1:nImages)
N = imread(fileNames{k});
if ndims(N)==3, N=rgb2gray(N); end
if ~isempty(Mask), N = roifill(N, Mask); end
SegoutSequence(:,:,k) = fcn(N);
end
end
or call it as: BatchProcessFiles(fileNames, [], #DetectLines) if you don't need to apply the mask

Related

Extract Freeman chain code of an object - Matlab

I am trying this code to generate a freeman chain code based on the code in https://www.crisluengo.net/archives/324 but it uses the DIPimage. Therefore, does someone has an idea how to by pass the dip_array function?
Code:
clc;
clear all;
Image = rgb2gray(imread('https://upload-icon.s3.us-east-2.amazonaws.com/uploads/icons/png/1606078271536061993-512.png'));
BW = imbinarize(Image);
BW = imfill(BW,'holes');
BW = bwareaopen(BW, 100);
BW = padarray(BW,60,60,'both')
BW = imcomplement(BW);
imshow(BW)
[B,L] = bwboundaries(BW,'noholes');
%%%%%%%https://www.crisluengo.net/archives/324%%%%%
directions = [ 1, 0
1,-1
0,-1
-1,-1
-1, 0
-1, 1
0, 1
1, 1];
indx = find(dip_array(img),1)-1;
sz = imsize(img);
start = [floor(indx/sz(2)),0];
start(2) = indx-(start(1)*sz(2));
cc = []; % The chain code
coord = start; % Coordinates of the current pixel
dir = 1; % The starting direction
while 1
newcoord = coord + directions(dir+1,:);
if all(newcoord>=0) && all(newcoord<sz) ...
&& img(newcoord(1),newcoord(2))
cc = [cc,dir];
coord = newcoord;
dir = mod(dir+2,8);
else
dir = mod(dir-1,8);
end
if all(coord==start) && dir==1 % back to starting situation
break;
end
end
I don't want to translate the whole code, I don't have time right now, but I can give a few pointers:
dip_array(img) extracts the MATLAB array with the pixel values that is inside the dip_image object img. If you use BW as input image here, you can simply remove the call to dip_array: indx = find(BW,1)-1.
imsize(img) returns the sizes of the image img. The MATLAB function size is equivalent (in this particular case).
Dimensions for the dip_image object are different from those for MATLAB arrays: they are indexed as img(x,y), whereas MATLAB arrays are indexed as BW(y,x).
Indices for dip_image objects start at 0, not at 1 as MATLAB arrays do.
These last two points change how you'd compute start. I think it'd be something like this:
indx = find(BW,1);
sz = size(BW);
start = [1,floor((indx-1)/sz(2))+1];
start(1) = indx-((start(2)-1)*sz(1));
But it's easier to use ind2sub (not sure why I did the explicit calculation in the blog post):
indx = find(BW,1);
sz = size(BW);
start = ind2sub(sz,indx);
You also probably want to swap the two columns of directions for the same reason, and change all(newcoord>=0) && all(newcoord<sz) into all(newcoord>0) && all(newcoord<=sz).

How to process image before applying bwlabel?

I = imread('Sub1.png');
figure, imshow(I);
I = imcomplement(I);
I = double(I)/255;
I = adapthisteq(I,'clipLimit',0.0003,'Distribution','exponential');
k = 12;
beta = 2;
maxIter = 100;
for i=1:length(beta)
[seg,prob,mu,sigma,it(i)] = ICM(I, k, beta(i), maxIter,5);
pr(i) = prob(end);
hold on;
end
figure, imshow(seg,[]);
and ICM function is defined as
function [segmented_image,prob,mu,sigma,iter] = ICM(image, k, beta, max_iterations, neigh)
[width, height, bands] = size(image);
image = imstack2vectors(image);
segmented_image = init(image,k,1);
clear c;
iter = 0;
seg_old = segmented_image;
while(iter < max_iterations)
[mu, sigma] = stats(image, segmented_image, k);
E1 = energy1(image,mu,sigma,k);
E2 = energy2(segmented_image, beta, width, height, k);
E = E1 + E2;
[p2,~] = min(E2,[],2);
[p1,~] = min(E1,[],2);
[p,segmented_image] = min(E,[],2);
prob(iter+1) = sum(p);
%find mismatch with previous step
[c,~] = find(seg_old~=segmented_image);
mismatch = (numel(c)/numel(segmented_image))*100;
if mismatch<0.1
iter
break;
end
iter = iter + 1;
seg_old = segmented_image;
end
segmented_image = reshape(segmented_image,[width height]);
end
Output of my algorithm is a logical matrix (seg) of size 305-by-305. When I use
imshow(seg,[]);
I am able to display the image. It shows different component with varying gray value. But bwlabel returns 1. I want to display the connected components. I think bwlabel thresholds the image to 1. unique(seg) returns values 1 to 10 since number of classes used in k-means is 10. I used
[label n] = bwlabel(seg);
RGB = label2rgb(label);
figure, imshow(RGB);
I need all the ellipse-like structures which are in between the two squares close to the middle of the image. I don't know the number of classes present in it.
Input image:
Ground truth:
My output:
If you want to explode the label image to different connected components you need to use a loop to extract labels for each class and sum label images to get the out label image.
u = unique(seg(:));
out = zeros(size(seg));
num_objs = 0;
for k = 1: numel(u)
mask = seg==u(k);
[L,N] = bwlabel(mask);
L(mask) = L(mask) + num_objs;
out = out + L;
num_objs = num_objs + N ;
end
mp = jet(num_objs);
figure,imshow(out,mp)
Something like this is produced:
I have tried to do everything out of scratch. I wish it is of some help.
I have a treatment chain that get at first contours with parameters tuned on a trial-and-error basis, I confess. The last "image" is given at the bottom ; with it, you can easily select the connected components and do for example a reconstruction by markers using "imreconstruct" operator.
clear all;close all;
I = imread('C:\Users\jean-marie.becker\Desktop\imagesJPG10\spinalchord.jpg');
figure,imshow(I);
J = I(:,:,1);% select the blue channel because jpg image
J=double(J<50);% I haven't inverted the image
figure, imshow(J);
se = strel('disk',5);
J=J-imopen(J,se);
figure, imshow(J);
J=imopen(J,ones(1,15));% privilegizes long horizontal strokes
figure, imshow(J);
K=imdilate(J,ones(20,1),'same');
% connects verticaly not-to-far horizontal "segments"
figure, imshow(K);

Matlab - Image Filtering with a 5X5 Filter without imfilter function

I tried to modify the code (Implementing IMFILTER in matlab) to filter an image with an 5X5 gaussian filter. Something is wrong but I don't find it.
gauss_kernel = fspecial('gaussian',5,2);
function [result] = evc_filter(input, kernel)
rsize = size(input);
r = zeros(rsize);
original=padarray(input,[2,2]);
for i = 3:rsize(1)+2
for j = 3:rsize(2)+2
temp = original(i-2:i+2,j-2:j+2) .* kernel;
r(i-2,j-2) = sum(temp(:));
end
end
result=r;
end
If I display the picture with imshow it looks different if I use the imfilter function. Can anyone help?
first, convert your image to double then do the remaining procedure. see example code below:
function imfilt()
img = imread('one.jpg');
img = double(img);
[r,c,z] = size(img);
pad = 4;
nimg = zeros(r+pad,c+pad,z);
nimg(pad/2+1: r+pad/2, pad/2+1: c+pad/2,:) = img;
h = fspecial('gaussian',5,2);
res = zeros(r,c,z);
for i = pad/2+1 : r+pad/2
for j = pad/2+1 : c+pad/2
tmp = nimg(i-pad/2:i+pad/2,j-pad/2:j+pad/2,1).*h;
res(i-pad/2,j-pad/2,1) = sum(tmp(:));
tmp = nimg(i-pad/2:i+pad/2,j-pad/2:j+pad/2,2).*h;
res(i-pad/2,j-pad/2,2) = sum(tmp(:));
tmp = nimg(i-pad/2:i+pad/2,j-pad/2:j+pad/2,3).*h;
res(i-pad/2,j-pad/2,3) = sum(tmp(:));
end
end
imshow(uint8(res),[]);
end

How to use reshape on a 4D matrix after using fread on a RGB RAW file?

The following code correctly loads an mp4 file and stores it in a 3D matrix.
r = 1;
fileName = testDummyMP4;
readerobj = VideoReader(fileName, 'tag', 'myreader1');
F = get(readerobj, 'numberOfFrames');
tampon = single(read(readerobj,1));
tampon = imresize(tampon(:,:,1),r);
I = zeros(size(tampon,1),size(tampon,2),F,'uint8');
for k = 1:F
disp(['Open: ' num2str(round(100*k/F)) '%'])
vidFrames = single(read(readerobj,k));
I(:,:,k) = imresize(vidFrames(:,:,2),r);
end;
imagesc((I(:,:,1)));
This is the output
I'm trying to reverse engineer this code so that it produces the same sort of result for but for a .raw 8bit rbg file. Following the answers from this question I tried the following:
You can download the 'M1302000245_1436389857.982603.raw' rbg file here
Or Google Drive version here
Ix = 256;
Iy = 256;
SF = 30; % Sample frequency
RecordingTime = 30;
Iz = SF*RecordingTime
testDummy = 'M1302000245_1436389857.982603.raw'
fin = fopen(testDummy, 'r');
I = fread(fin, Ix*Iy*3*Iz, 'uint8');
fclose(fin);
I = reshape(I, [Ix Iy 3 Iz]); % The rbg should be 256x256x3x900
% I've tried each of the following manipulations before calling imagesc to no avail
% I = flipdim(imrotate(I, -90),2);
% I=impixel(I)
% I=I'
imagesc((I(:,:,1))); % view first slice
This gives:
What am I doing wrong?
Additional info:
Recordings are taken using raspberry pi cameras with the following python code
class BrainCamera:
def __init__(self):
self.video_format = "rgb"
#self.video_quality = 5
# Set up the settings of the camera so that
# Exposure and gains are constant.
self.camera = picamera.PiCamera()
self.camera.resolution = (256,256)
self.camera.framerate = 30
sleep(2.0)
self.camera.shutter_speed = self.camera.exposure_speed
self.camera.exposure_mode = 'off'
g = self.camera.awb_gains
self.camera.awb_mode = 'off'
self.camera.awb_gains = g
self.camera.shutter_speed = 30000
self.camera.awb_gains = (1,1)
def start_recording(self, video_name_path):
self.camera.start_recording(video_name_path, format=self.video_format)
self.camera.start_preview()
def stop_recording(self):
self.camera.stop_recording()
self.camera.stop_preview()
# Destructor
def __del__(self):
print ("Closed Camera")
self.camera.close()
I don't get the output you have, but I get some reasonable image:
%your vode from above, ending with I=fread(...)
I=uint8(I)
I2=reshape(I, 3, Ix ,Iy, []);
I2=permute(I2,[3,2,1,4]);
imagesc(I2(:,:,:,1));
implay(I2);
With Daniel's help I got the following working. Additionally a co-worker found out how to get the number of frames of a .raw rbg video. This we needed since it turns out assuming noFrame = SF*RecordingTime was a bad idea.
testDummy = 'M1302000245_1436389857.982603.raw'
testDummyInfo = dir(testDummy);
noFrames = testDummyInfo.bytes/(256*256*3); % In my question Iz = noFrames
fin = fopen(testDummy, 'r');
I = fread(fin, testDummyInfo.bytes, 'uint8');
fclose(fin);
I=uint8(I);
I2=reshape(I, 3, Ix ,Iy, noFrames);
I2=permute(I2,[3,2,1,4]);
imagesc(I2(:,:,2,1)); % Throw out unnecessarry channels r and b. Only want GFP signal
to produce:

Running matlab code through a folder

I have the following code for which instead of loading one image at a time, I'd like to run through every image in a folder (the defective folder in this code). I'd like the output to be an array containing the values of 'G' for each of the input images. I'm not too sure how to go about this - so any points appreciated. Many thanks!
%PCA code,
img = imread('C:\users\m7-miller\desktop\250images\defective\inkblob01.png');
img_gray = rgb2gray(img);
img_gray_double = im2double(img_gray);
figure,
set(gcf,'numbertitle','off','name','Grayscale Image'),
imshow(img_gray_double)
%find mean of the image
img_mean = mean(img_gray_double);
[m n] = size(img_gray);
%Make column vector of mean image value
new_mean = repmat(img_mean,m,1);
%Mean corrected image
Corrected_img = img_gray_double - new_mean;
%Covariance matrix of corrected image
cov_img = cov(Corrected_img);
%Eigenvalues of covariance matrix - columns of V are e-vectors,
%diagonals of D e-values
[V, D] = eig(cov_img);
V_T = transpose(V);
Corrected_image_T = transpose(Corrected_img);
FinalData = V_T * Corrected_image_T;
% Image approximation by choosing only a selection of principal components
PCs = 3;
PCs = n - PCs;
Reduced_V = V;
for i = 1:PCs,
Reduced_V(:,1) =[];
end
Y=Reduced_V'* Corrected_image_T;
Compressed_img = Reduced_V*Y;
Compressed_img = Compressed_img' + new_mean;
figure,
set(gcf,'numbertitle','off','name','Compressed Image'),
imshow(Compressed_img)
% End of image compression
% Difference of original image and compressed
S = (img_gray_double - Compressed_img);
figure,
set(gcf,'numbertitle','off','name','Difference'),
imshow(S)
% Sum of the differences
F = sum(S);
G = sum(F)
Are you looking for the dir command?
files = dir('*.png');
for n=1:size(files,1)
filename = files(n).name;
img = imread(filename);
....
G = sum(F);
end