Decrease Matlab for loop - matlab

% read image
I = imread(im);
H = zeros(256,1);
% m = width, n = height
[m,n] = size(I);
% loop for checking values
for GrayValue = 0:255
for i = 1:m
for j = 1:n
if I(i,j) == GrayValue % read each pixel coordinate
H(GrayValue+1) = H(GrayValue+1)+1;
end
end
end
end
This function it go get image file as im and will show a histogram of values count in the image. How can i reduce the time taken to execute this MATLAB function. It is similar to imhist() . But I want to make a similar imhist() function. I cannot figure out to remove which loop.

Obligatory bsxfun solution:
H=sum(bsxfun(#eq,I(:),0:255))
And a method that might be easier to understand. This just replaces your two inner loops with a search.
I=randi(256,50,50)-1;
H=zeros(256,1);
G=zeros(256,1);
for GrayValue=0:255
[ii,jj]=find(I==GrayValue);
G(GrayValue+1)=length(ii);
end

Assuming I to be a grayscale image, you can use histc to get H -
H = sum(histc(I,0:255),2)
Thus, the complete code would be -
% read image
I = imread(im);
H = sum(histc(I,0:255),2)
If you were looking for a little less-advanced code, you can avoid one nested loop -
% read image
I = imread(im);
H = zeros(256,1);
% loop for checking values
for GrayValue = 0:255
for i = 1:numel(I)
if I(i) == GrayValue % read each pixel coordinate
H(GrayValue+1) = H(GrayValue+1)+1;
end
end
end

Related

Using Optimization algorithm for white matter fiber tracking

Actually I use MATLAB code to implement my work which it's summarize as a following:
I used a program applied the Bayesian approach to solve fiber tracking, I have a problem in load the dataset, which it's Medical Image. I need any hint to help me to open this data set to continue my work. the following code shows the load dataset function:
function data = Load_DMRI_Data(dataset)
% Load diffusion tensor MRI data and return it in
% a structure together with gradients and b-values.
% The data must be stored in a data structure for further
% processing, see code.
% The gradients are stored as a(3xg) matrix, where g is the
% number of acquired DWI volumens (including the b=0 ones).
% The b-values are stored in a corresponding (1xg) vector.
if strcmp(dataset,'gordon')
readdir = '/projects/lmi/data/diffusion/gk-3t/041020-02156-bvalexpr/data/003/';
intensity = zeros(256,256,31,32);
for g = 1:32
for slice = 1:31
fid = fopen(sprintf('%sI.%03d',readdir,(g-1)*31+slice),'r');
im = fread(fid,'int16');
im = im(end-256^2+1:end);
intensity(:,:,slice,g) = reshape(im,[256 256])';
fclose(fid);
end
end
G = load('gradients.mat');
G = [[1;1;1] G.g]; % Add arbitrary gradient direction for b=0
b = [0 1000*ones(1,31)];
data = struct('intensity',intensity,'G',G,'b',b,'FOV',240,'SliceThickness',4);
elseif strcmp(dataset,'pc')
readdir = 'c:\Work\DiffusionData\';
intensity = zeros(256,256,1,32);
for g = 1:32
for slice = 16:16 % Use slice 16 as test slice
fid = fopen(sprintf('%sI.%03d',readdir,(g-1)*31+slice),'r','ieee-be');
im = fread(fid,'int16');
im = im(end-256^2+1:end);
intensity(:,:,slice-15,g) = reshape(im,[256 256])';
fclose(fid);
end
end
G = load(sprintf('%sgradients.mat',readdir));
G = [[1;1;1] G.g]; % Add arbitrary gradient direction for b=0
b = [0 1000*ones(1,31)]; % b-values
data = struct('intensity',intensity,'G',G,'b',b);
end
The website for dataset : http://www.sci.utah.edu/~gk/DTI-data/

Image corruption in matlab parfor loop

I have some code for an adaptive median filter (see below) which works perfectly until I attempt to run it as a parallel loop, in which case there are values missing or corrupted and the image I get at the end is incorrect (see http://i.stack.imgur.com/Rt6dV.jpg).
Matlab doesn't throw up any errors but appears to be either dropping random data, or overwriting them. The only thing I could find which would even vaguely match this problem was information on custom type definitions and set functions, but all of my input images are uint8 so I don't have any custom set functions or type definitions. (http://fluffynukeit.com/problems-with-matlab-parfor-data-disappearing/)
The error occurs specifically between lines 63 and 86, when I attempt to change
for Index = 1:length(ss)
to
parfor Index = 1:length(ss)
and I can't for the life of me figure out why.
I usually call the function with an image, I, in uint8 format (although any format should work), w_size is an odd number relating to the size of the window for filtering, and M can be set from 0 to 2, where lower numbers reduce the amount of pixels considered when median filtering by increasing the weight of the standard deviation of the current block. So a typical function call would be thus:
I = imread('image.tif');
J = Par_AMF(I, 5, 1);
figure;
imshow(J)
I should finish by saying that typically the size of images I'm using make the parallel processing a huge time saver, usually about half the time of the non-parallel execution, so although there isn't much point for smaller images the ones I'm using would really benefit from it.
function [FIm] = Par_AMF(Im, w_size, M)
% PAR_AMF Adaptive median filter
% Performs a local adaptive median filtering operation
% Inputs: Im - Image to be filtered
% w_size - Window size for filter
% M - Sigma weighting, range from 0 to 2
%
% Output: FIm - Filtered image
tic;
sz_oldim = size(Im);
w_option = floor(w_size/2);
% ----------------------------------------------------------------------- %
% Padding edges of image matrix
Pad_im = padarray(Im,[w_option, w_option],0,'both');
% ----------------------------------------------------------------------- %
% Stage 1
% Calculate the local Mean and Standard Deviation for finding Speckle
% Pixels
% ----------------------------------------------------------------------- %
sz = size(Pad_im);
start_index = w_option+1;
end_index1=(sz(1)-w_option);
end_index2=(sz(2)-w_option);
LB = zeros(sz_oldim);
UB = LB;
first_loop1 = start_index:end_index1;
first_loop2 = start_index:end_index2;
ss = cell(numel(LB), 1);
Index = 1;
for c = first_loop2
for r = first_loop1
ss{Index} = Pad_im(r-w_option:r+w_option,c-w_option:c+w_option);
Index = Index+1;
end
end
% This parfor functions as expected:
parfor Index = 1:length(ss)
ss1=ss{Index}(:);
if any(ss1 > 0)
local_mn = mean(ss1);
local_sig = std(double([ss1;local_mn]));
LB(Index) = local_mn - (M*local_sig);
UB(Index) = local_mn + (M*local_sig);
end
end
% ----------------------------------------------------------------------- %
% UB is the Upper Bound Limit; LB is the Lower Bound Limit
% ----------------------------------------------------------------------- %
% ----------------------------------------------------------------------- %
% Using UB and LB mark pixels as speckle or valid pixels and update only if
% central pixel of window is speckle pixels with median value calculated
% again with only speckle pixels with the window
% ----------------------------------------------------------------------- %
TempOut = Im;
% When this for loop is changed to a parfor (which should definitely work)
% the output is corrupted horribly:
% parfor Index = 1:length(ss)
for Index = 1:length(ss)
ss1 = ss{Index}(:);
ss2 = ss1;
if any(ss1>0)
zz = 0;
for z = 1:length(ss1)
if (ss1(z) < LB(Index) || ss1(z) > UB(Index))
ss1(z) = 0;
ss2(z) = 0;
else
ss1(z)=1;
zz= zz+1;
end
end
if zz > 0
new_ss1 = ss2(ss2~=0);
if(ss1(ceil(length(ss1)/2)) == 0)
md = median(new_ss1);
TempOut(Index) = md;
end
end
end
end
looptime = toc;
disp(['Total processing time ', num2str(looptime./60), ' minutes'])
FIm = TempOut;
end
EDIT: In Matlab version R2015a

Hough transform to detect and delete lines

I want to use the Hough transform to detect lines in my image.But instead of plotting the lines I want to delete each line detected in my original image.
image=imread('image.jpg');
image = im2bw(image);
BW=edge(image,'canny');
imshow(BW);
figure,imshow(BW);
[H,T,R] = hough(BW);
P = houghpeaks(H,100,'threshold',ceil(0.3*max(H(:))));
lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
Now after this I have got all the lines. But I want to delete all these lines from my original image, keeping rest of the image as before. Is there some way I can do this?
Edit I am uploading an image.I want to delete all the lines and keep the circular part.This is just an example image.Basically my objective is to delete the line segments and keep rest of the image
The issue you have is that your lines are thicker than one pixel.
The lines from the hough transform seem to be one pixel thick and
that doesn't help.
I propose that you delete the lines that you get from the Hough transform first.
This will sort of divide the hockey rink of whatever it is into segments
that will be easier to process.
Then you label each segment with bwlabel. For each object, find the
endpoints and fit a line between the endpoints. If the line and the object
have more pixels in common than a certain threshold, then we say that the object
is a line and we delete it from the image.
You may have to play around with the Hough transform's threshold value.
This technique has some flaws though. It will delete a filled square,
rectangle or circle but you haven't got any of those so you should be ok.
Results
Explanation
This is your code that I modified a bit. I removed the gradient because it
it easier to work with solid objects. The gradient gave very thin lines.
I also work on the complement image because the bw functions work with 1
as forgound rather than 0 as in your original image.
org_image_bw=im2bw(double(imread('http://i.stack.imgur.com/hcphc.png')));
image = imcomplement(org_image_bw);
[H,T,R] = hough(image);
P = houghpeaks(H,100,'threshold',ceil(0.27*max(H(:))));
lines = houghlines(image,T,R,P,'FillGap',5,'MinLength',7);
Loop through the lines you have got and delete them
processed_image = image;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
% // Use the question of a line y = kx + m to calulate x,y
% // Calculate the maximum number of elements in a line
numOfElems = max(max(xy(:,1))-min(xy(:,1)),max(xy(:,2))-min(xy(:,2)) ) ;
% // Cater for the special case where the equation of a line is
% // undefined, i.e. there is only one x value.
% // We use linspace rather than the colon operator because we want
% // x and y to have the same length and be evenly spaced.
if (diff(xy(:,1)) == 0)
y = round(linspace(min(xy(:,2)),max(xy(:,2)),numOfElems));
x = round(linspace(min(xy(:,1)),max(xy(:,1)),numOfElems));
else
k = diff(xy(:,2)) ./ diff(xy(:,1)); % // the slope
m = xy(1,2) - k.*xy(1,1); % // The crossing of the y-axis
x = round(linspace(min(xy(:,1)), max(xy(:,1)), numOfElems));
y = round(k.*x + m); % // the equation of a line
end
processed_image(y,x) = 0; % // delete the line
end
This is what the image looks after we have deleted the detected lines. Please note that the original hockey rink and been divided into multiple objects.
Label the remaining objects
L = bwlabel(processed_image);
Run through each object and find the end points.
Then fit a line to it. If, let's say 80% the fitted line covers
the object, then it is a line.
A fitted line could look like this. The diagonal blue line represents the fitted line and covers most of
the object (the white area). We therefore say that the object is a line.
% // Set the threshold
th = 0.8;
% // Loop through the objects
for objNr=1:max(L(:))
[objy, objx] = find(L==objNr);
% Find the end points
endpoints = [min(objx) min(objy) ...
;max(objx) max(objy)];
% Fit a line to it. y = kx + m
numOfElems = max(max(endpoints(:,1))-min(endpoints(:,1)),max(endpoints(:,2))-min(endpoints(:,2)) ) ;
% // Cater for the special case where the equation of a line is
% // undefined, i.e. there is only one x value
if (diff(endpoints(:,1)) == 0)
y = round(linspace(min(endpoints(:,2)),max(endpoints(:,2)),numOfElems));
x = round(linspace(min(endpoints(:,1)),max(endpoints(:,1)),numOfElems));
else
k = diff(endpoints(:,2)) ./ diff(endpoints(:,1)); % the slope
m = endpoints(1,2) - k.*endpoints(1,1); % The crossing of the y-axis
x = round(linspace(min(endpoints(:,1)), max(endpoints(:,1)), numOfElems));
y = round(k.*x + m);
% // Set any out of boundary items to the boundary
y(y>size(L,1)) = size(L,1);
end
% // Convert x and y to an index for easy comparison with the image
% // We sort them so that we are comparing the same pixels
fittedInd = sort(sub2ind(size(L),y,x)).';
objInd = sort(sub2ind(size(L),objy,objx));
% // Calculate the similarity. Intersect returns unique entities so we
% // use unique on fittedInd
fitrate = numel(intersect(fittedInd,objInd)) ./ numel(unique(fittedInd));
if (fitrate >= th)
L(objInd) = 0;
processed_image(objInd) = 0;
% // figure(1),imshow(processed_image)
end
end
Display the result
figure,imshow(image);title('Original');
figure,imshow(processed_image);title('Processed image');
Complete example
org_image_bw=im2bw(double(imread('http://i.stack.imgur.com/hcphc.png')));
image = imcomplement(org_image_bw);
[H,T,R] = hough(image);
P = houghpeaks(H,100,'threshold',ceil(0.27*max(H(:))));
lines = houghlines(image,T,R,P,'FillGap',5,'MinLength',7);
processed_image = image;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
% // Use the question of a line y = kx + m to calulate x,y
%Calculate the maximum number of elements in a line
numOfElems = max(max(xy(:,1))-min(xy(:,1)),max(xy(:,2))-min(xy(:,2)) ) ;
% // Cater for the special case where the equation of a line is
% // undefined, i.e. there is only one x value.
% // We use linspace rather than the colon operator because we want
% // x and y to have the same length and be evenly spaced.
if (diff(xy(:,1)) == 0)
y = round(linspace(min(xy(:,2)),max(xy(:,2)),numOfElems));
x = round(linspace(min(xy(:,1)),max(xy(:,1)),numOfElems));
else
k = diff(xy(:,2)) ./ diff(xy(:,1)); % the slope
m = xy(1,2) - k.*xy(1,1); % The crossing of the y-axis
x = round(linspace(min(xy(:,1)), max(xy(:,1)), numOfElems));
y = round(k.*x + m); % // the equation of a line
end
processed_image(y,x) = 0; % // delete the line
end
% // Label the remaining objects
L = bwlabel(processed_image);
% // Run through each object and find the end points.
% // Then fit a line to it. If, let's say 80% the fitted line covers
% // the object, then it is a line.
% // Set the threshold
th = 0.8;
% // Loop through the objects
for objNr=1:max(L(:))
[objy, objx] = find(L==objNr);
% Find the end points
endpoints = [min(objx) min(objy) ...
;max(objx) max(objy)];
% Fit a line to it. y = kx + m
numOfElems = max(max(endpoints(:,1))-min(endpoints(:,1)),max(endpoints(:,2))-min(endpoints(:,2)) ) ;
% Cater for the special case where the equation of a line is
% undefined, i.e. there is only one x value
if (diff(endpoints(:,1)) == 0)
y = round(linspace(min(endpoints(:,2)),max(endpoints(:,2)),numOfElems));
x = round(linspace(min(endpoints(:,1)),max(endpoints(:,1)),numOfElems));
else
k = diff(endpoints(:,2)) ./ diff(endpoints(:,1)); % the slope
m = endpoints(1,2) - k.*endpoints(1,1); % The crossing of the y-axis
x = round(linspace(min(endpoints(:,1)), max(endpoints(:,1)), numOfElems));
y = round(k.*x + m);
% // Set any out of boundary items to the boundary
y(y>size(L,1)) = size(L,1);
end
% // Convert x and y to an index for easy comparison with the image
% // We sort them so that we are comparing the same pixels
fittedInd = sort(sub2ind(size(L),y,x)).';
objInd = sort(sub2ind(size(L),objy,objx));
% Calculate the similarity. Intersect returns unique entities so we
% use unique on fittedInd
fitrate = numel(intersect(fittedInd,objInd)) ./ numel(unique(fittedInd));
if (fitrate >= th)
L(objInd) = 0;
processed_image(objInd) = 0;
% // figure(1),imshow(processed_image)
end
end
% // Display the result
figure,imshow(image);title('Original');
figure,imshow(processed_image);title('Processed image');
You could use J. E. Bresenham's algorightm. It is implemented by A. Wetzler in the following matlab function, which I tested myself.
The algorithm will give you the pixel coordinates of where the line would be, given that you will provide the start and end point of the line, which is already given in lines in your code above.
Here is the code I used, which uses the matlab function referenced above:
%This is your code above ========
image=imread('hcphc.png');
image = im2bw(image);
BW=edge(image,'canny');
imshow(BW);
figure,imshow(BW);
[H,T,R] = hough(BW);
P = houghpeaks(H,100,'threshold',ceil(0.3*max(H(:))));
lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
% =========
% Proposed solution:
% This will work for as many lines as you detected
for k=1:length(lines)
% Call Bresenham's algorithm
[x, y] = bresenham(lines(k).point1(1), lines(k).point1(2), ...
lines(k).point2(1), lines(k).point2(2));
% This is where you replace the line, here I use 0, but you can use
% whatever you want. However, note that if you use BW, you should only
% replace with 0 or 1, because is a logical image. If you want to use
% the original image, well, you know what to do.
BW(y, x) = 0;
% And now watch the lines disapear! (you can remove this line)
imagesc(BW), drawnow; pause(1);
end
Remember, download the matlab function first.

Matlab plot in loop error

I am creating figures in a for loop. The figure is a 2D mesh plot, which is supposed to be updated every iteration. The value to be plotted in a 200x200 array.
My problem is: It seems the calculation is running every iteration, but the plot is always the first one created, no matter I just plot or save to file.
Here is my code:
x = 1:200;
y = x;
for i = 1:100000
c = calculate(stuff, c); % value to be created, nothing to do with x and y
h = figure;
mesh(x,y,c);
saveas(h, sprintf('FIG%d.jpg',i);
drawnow; % did not work with or without this command
close(h);
end
First, thank you for all your inputs and suggestions! I didn't expect to get so many help within such a short time!
Then, I can answer some of the confusions here.
To Daniel: yes the c is changing. The program is calculating c based on its previous value. And there is sufficient step for c to change.
To R.Schifini: I tried pause(.1) but it didn't help unfortunately
To Andrew: thanks for pointing it. The complete program is attached now. And as to Daniel, the program calculate the value of c based on its previous values.
To The-Duck: I tried clf(h, 'reset') but unfortunately it didn't help.
Complete code:
Main program: please refer to wikipedia for the physical equation if you are interested
http://en.wikipedia.org/wiki/Cahn%E2%80%93Hilliard_equation
% Program to calculate composition evolution for nucleation and growth
% by solving Cahn-Hilliard equation - Time dependent non-linear
% differential equation
% Parameter
sig = 0.1; % J/m^2
delta = 10E-9; % m
D = 1E-9; %m^2/s
A = 10*sig/delta; % J/m
K = 3*sig*delta; % J/m^3
M = D/(2*A); % m^2/s
N = 200; % mesh size
dt = 1E-12; %s
h = delta/10;
% Rng control
r = -1+2.*rand(N);
beta = 1E-3;
n = 10000;
% initialization
c0 = zeros(200);
c0 = c0+ 0.1+beta.*r;
c = c0;
x = h.*linspace(-N/2,N/2,N);
y=x;
% Iteration
for i = 1:n
LP_c = laplacian(c,h);
d_f = A*(4*(c.^3)-6*(c.^2)+2*c);
sub = d_f - (2*K)*LP_c;
LP_RHS = laplacian(sub,h);
RHS = M*LP_RHS;
c = c + dt.*RHS;
% Save image every 2000 steps
% if ( i==1000 || i==10000 || i==100000)
% h = mesh(x,y,c);
% pause(.1);
% saveas(h, sprintf('FIG%d.jpg',i));
% clf(h,'reset');
% end
end
%h = figure;
mesh(x,y,c);
Laplacian function:
function LP_c = laplacian(c,h)
v1 = circshift(c,[0 -1]);
v2 = circshift(c,[0 1]);
v3 = circshift(c,[-1 0]);
v4 = circshift(c,[1 0]);
LP_c = (v1+v2+v3+v4-4.*c)./(h^2);
end
Result:
You can see the commented part in main program is for plotting periodically. They all give the same plots for each iteration. I tried the current OR version, also tried if ( mod(i,2000) == 0) to plot more pics. There is no difference. Shown:
However, if I comment out the periodic plotting, just run the program for different values of n, I got different plots, and they obey physical laws (evolving structure), shown in time order
Therefore I excluded the possibility that c might not update itself. It has to be some misuse of the plotting function of matlab. Or maybe some memory issue?
An interesting point I discovered during edition session: If I put the command h = figure in front of the loop and plot after the loop end, like this:
h = figure;
% Iteration
for i = 1:n
LP_c = laplacian(c,h);
d_f = A*(4*(c.^3)-6*(c.^2)+2*c);
sub = d_f - (2*K)*LP_c;
LP_RHS = laplacian(sub,h);
RHS = M*LP_RHS;
c = c + dt.*RHS;
end
mesh(x,y,c);
It seems all value of c calculated during the loop will overlap and give a figure shown below: I guess this indicates some facts about the plotting function of matlab, but I am not sure
Btw, can I answer directly to each comment and high light the new added section in my post? Sorry I am not as familiar with Stack Overlow as I should have :)
I ran your routine and with the following changes it works for me:
% Iteration
for i = 1:n
LP_c = laplacian(c,h);
d_f = A*(4*(c.^3)-6*(c.^2)+2*c);
sub = d_f - (2*K)*LP_c;
LP_RHS = laplacian(sub,h);
RHS = M*LP_RHS;
c = c + dt.*RHS;
% Save image every 2000 steps
if ( mod(i,2000)==0)
h1 = mesh(x,y,c);
drawnow;
saveas(h1, sprintf('FIG%d.jpg',i));
end
end
The main change is the figure handle variable from h to h1. Why? You are already using variable h in your equations.
Regards,

Exporting movie from matlab

I am trying to make a movie in matlab.
for i=1:runs;
for k=1:NO_TIMES
B = 0;
[conf dom_size] = conf_update_massmedia(time(k),conf);
shortconf=conf(1:N);
for j=1:N;
sigma(j,1:N) = conf(1+(j-1)*N:j*N);
end
figure(1)
imagesc(sigma);
colorbar;
set(gcf,'PaperPositionMode','auto');
F(k)=getframe(gcf);
end
end
movie2avi(F,'B=0.avi','Compression','none')
So my problem is that i only get a movie from the last run of the loop, i have tried to move the code for the figure around, but nothing seems to work, is there anyone who are able to help?
Pall
As #tmpearce mentioned, the problem is because of overwriting the F matrix.
I suggest you to:
Initialized your F matrix.
Always indent you code to make it readable (see here for example).
This is one of the million solutions:
f_ind = 1; % Frame index.
F = zeros(runs * NO_TIMES, 1); % initialization of Frames matrix.
figure; % remove figure(1) from your inner loop haowever.
for i = 1:runs;
for k = 1:NO_TIMES
% ...
F(f_ind)=getframe(gcf);
f_ind = f_ind + 1;
end
end
movie2avi is a little outdated and struggles on various operating systems. A better option is using the VideoWriter command:
vidObj = VideoWriter('B=0.avi');
vidObj.FrameRate=23;
open(vidObj);
for i=1:runs;
for k=1:NO_TIMES
B = 0;
[conf dom_size] = conf_update_massmedia(time(k),conf);
shortconf=conf(1:N);
for j=1:N;
sigma(j,1:N) = conf(1+(j-1)*N:j*N);
end
figure(1)
imagesc(sigma);
colorbar;
set(gcf,'PaperPositionMode','auto');
F=getframe(gcf);
writeVideo(vidObj,F);
end
end
close(vidObj);