I am given an assignment to implement Range filter. Here is my code for that:
I=imread('cameraman.tif');
I=im2double(I);
mkdir('./output_images/');
%Salt and pepper
SP= imnoise(I,'salt & pepper',0.004);
stemName='Salt&pepper';
OutputFileName = ['./output_images/' stemName '_noise.tif'];
imwrite( SP,OutputFileName);
[row col]=size(SP);
%SP=padarray(SP,[3 2],'replicate','both');
for i=2:row-1
for j=2:col-1
neigbours=[0 0 0; 0 0 0;0 0 0];
neibours(1,1)=SP(i-1,j-1);
neibours(1,2)=SP(i-1,j);
neibours(1,3)=SP(i-1,j+1);
neibours(2,1)=SP(i,j-1);
neibours(2,3)=SP(i,j+1);
neibours(3,1)=SP(i+1,j-1);
neibours(3,2)=SP(i+1,j);
neibours(3,3)=SP(i+1,j+1);
neibours(2,2)=SP(i,j);
maxi= max(neibours(:));
mini= min(neibours(:));
newvalue= maxi-mini;
SP(i,j)=newvalue;
end
end
OutputFileName = ['./output_images/' stemName '_filtered.tif'];
imwrite( SP,OutputFileName);
Noise is applied to image I and then saved to SP. A new array is created neibours in which all the neighbors including current pixel is added. Then the difference between max and min is calculated and stored to current pixel. Problem is that when I compare the image generated from this code and the one generated from builtin function rangefilt() results are different.
I was updating same matrix SP. When I created a new matrix S and stored values in that one, it produced the same results as that of built in one.
Related
Setup
I have an array of captured data. The data may be captured on just 1 device or up to a dozen devices, with each device being a column in the array. I have a prior statement which I execute on the array to then turn it into a logical array to find particular points of interest in the data. Due to the nature of the data, there are many 0's and only a few 1's. I need to return an array with the indices of the 1's so I can go back and capture the data between those points (see update below).
find is an obvious choice for a function - however, the result I need, needs to have 1 column for each device. Normally find will do a linear index regardless of the dimensions of the array.
The devices follow a pattern - but aren't exactly the same. So, complicating this is the fact that the number of 1's in each column is close to, but not guaranteed to be exactly the same depending on the exact timing the data capture is stopped (they are most often different from each other by 1 element, but could be different by more).
MATLAB CODE ATTEMPTS
Because of that difference, I can't use the following simple code:
for p = 1:np
indices( :, p ) = find( device.data.cross( :, p ) );
end
Notes:
np is the number of columns in the data = number of devices captured.
devices is a class representing the collection of devices
data is a TimeTable containing captured data on all the devices
cross is a column in the data TimeTable which contains the logical array
Even this simple code is inefficient and generates the Code Analyzer warning:
The variable 'indices' appears to change size on every loop
iteration (within a script). Consider preallocating for speed.
As expected, it doesn't work as I get an error similar to the following:
Unable to perform assignment because the size of the left side is
448-by-1 and the size of the right side is 449-by-1.
I know why I get this error - each column in an array in MATLAB has to have the same number of rows, so I can't make the assignment if the row size doesn't match. I need to pad the "short" columns somehow. In this case, repeating the last index will work for my later operations without causing an error.
I can't figure out a "good" way to do this. I can't pre-populate the array rows because I don't know how many rows there will be until I've done the find operation.
I can change the code as follows:
indices = [];
for p = 1:np
tempindices = find( devices.data.cross(:, p) );
sizediff = size( tempindices, 1 ) - size( indices, 1 );
if p > 1
if sizediff > 0
padding = repmat(indices(end, 1:(p - 1)), sizediff, 1);
indices = [indices; padding];
elseif sizediff < 0
padding = repmat(tempindices(end), abs(sizediff), 1);
tempindices = [tempindices; padding];
end
end
indices(:,p) = tempindices;
end
Note: padarray would have been useful here, but I don't have the Image Processing Toolbox so I cannot use it.
This code works, but it is very inefficient, it creates multiple otherwise unneeded variables in the workspace and generates multiple "appears to change size on every loop iteration" warnings in Code Analyzer. Is there a more efficient way to do this?
Update / Additional Information:
Some more context is needed for my issue. Given that devices.data.cross is a logical array, to just "pick" the data I want from other columns in my table (as I originally described my problem) I could select a column from devices.data.cross and pass that logical column as a subscript to get that data. I do that where it works. However, for some of the columns I need to select "chunks" of the data between the indices and that's where (I think) I need the indices. Or, at least I don't know of another way to do it.
Here is example code of how I use the indices:
for p = 1:np
for i = 2:num_indices
these_indices = indices(i-1, p):( indices(i, p) - 1 );
rmsvoltage = sqrt( mean( devices.data.voltage(these_indices).^2 ) );
end
end
This is just one routine I do on the "chunks" of data. I also have a couple of functions where these chunks of data are passed for processing.
When I understood your problem correctly, the code below should work. I'm using the approach that Cris Luengo suggested in a comment under your question.
Key element is [rowIdcs, colIdcs] = find( cros ); which gives you the subscripts of positions in cros having a value of one. Please find further comments inline.
% Create some data for testing
volt = randn(10,10);
cros = randi(10,10,10) > 9;
% Get rowIdcs and colIdcs, which have both a size of Nx1,
% with N denoting the number of ones in the mask.
% rowIdcs and colIdcs are the subscripts of the ones in the mask.
[rowIdcs, colIdcs] = find( cros );
% The number of chunks is equal to number N of ones found in the mask;
numChunks = numel( rowIdcs );
% Initilize a vector for the rms
rms = zeros( numChunks, 1 );
% Loop over the chunks
for k = 1 : numChunks
curRow = rowIdcs(k);
curCol = colIdcs(k);
% Get indices of range over neighbouring rows
chunkRowIdcs = curRow + [-1 0 1]; %i.e. these_indices in your example
% Remove indices that are out of range
chunkRowIdcs( chunkRowIdcs < 1 | chunkRowIdcs > size(volt,1) ) = [];
% Get voltages covered by chunk
chunkVoltages = volt( chunkRowIdcs, curCol );
% Get RMS over voltages
rms(k) = sqrt( mean( chunkVoltages(:).^2 ));
end
I wanted to move the DICOM images around x-axis with the value 4.2 milimeter and have written the following code:
srcFile2=dir('C:\Users\User\Desktop\Projekt\meine B.A\Programmieren\Archiv CBCT_A_04_08\*.dcm');
for i=1:88
filename2=strcat('C:\Users\User\Desktop\Projekt\meine B.A\Programmieren\Archiv CBCT_A_04_08\',srcFile2(i).name);
CBCT(:,:,i)=dicomread(filename2);
end
info_CBCT=dicominfo('C:\Users\User\Desktop\Projekt\meine B.A\Programmieren\Archiv CBCT_A_04_08\CT.Test CatPhan.Image 1');
info_CBCT.PixelSpacing(1);
info_CBCT.PixelSpacing(2);
CBCT=double(CBCT);
cb_ref = imref2d(size(CBCT),info_CBCT.PixelSpacing(1),info_CBCT.PixelSpacing(2))
T = [1 0 0;0 1 0;4.2 0 1];%-2.5883
tform_t = affine2d(T);
for j=1:88
Axial_CBCT_Trans1(:,:,j)= imwarp(CBCT(:,:,j),tform_t);
end
It worked without any error message. Then I subtracted the image before and after the translation.
Axial_CBCT_Trans1(:,:,48)-CBCT(:,:,48);
After the subtraction the difference is zero. this has the following that the image is not shifted around x-axis.
Does anyone have this problem?
I would ask if my code is written correctly?
Can the command (affine2d) be used in DIOM images or is there another command for the DICOM data , to move the DICOM images in x axis?
By default imwarp automatically centralize the output image.
You may add 'OutputView' argument for avoiding the automatic centralization.
Replace imwarp(CBCT(:,:,j),tform_t); with:
imwarp(CBCT(:,:,j), tform_t, 'OutputView', imref2d(size(CBCT(:,:,j))));
Here is a code sample that reproduce the issue (without DCOM):
I = imread('peppers.png');
T = [1 0 0; 0 1 0; 40.2 0 1];
tform_t = affine2d(T);
J = imwarp(I, tform_t); % Automatic centralization
K = imwarp(I, tform_t, 'OutputView', imref2d(size(I)));
figure;imshow(J);title('J'); % Displayed without translation.
figure;imshow(K);title('K'); % Displayed with translation.
I have a following code
x=randi([1 150],1,400);
d=max(x);
m=numel(x);
y=zeros(d,1);
p=zeros(d,d);
for k=1:m-1
y(x(k))=y(x(k))+1;
p(x(k),x(k+1))=p(x(k),x(k+1))+1;
end
p=bsxfun(#rdivide,p,y);
p(isnan(p)) = 0;
j=prod(p(p~=0));
[~,~,idx] = unique(x);
q=prod(hist(idx,1:max(idx))/numel(x));
s=log(j);
l=log(q);
g=s+l
In above code random no. generated from 1 to 150 with sequence length 400. finally I am getting output g,suppose random no. sequence generated by code is
x=[5,96,96,55,55,65,65,65,12,12,6,7,9,9,9,31,31,14,26,26,26,101,101,145,145,...]
so code is given output for whole sequence, but i want output for sliding window of size 10, i.e. o/p for sequence
[5,96,96,55,55,65,65,65,12,12],
then skipping 1st element and adding next element so window size should remain same, i.e.
[96,96,55,55,65,65,65,12,12,6],
then next for
[96,55,55,65,65,65,12,12,6,7],
likewise up to last, how to do it.
One easy way, using for loop, is below code.
x=randi([1 150],1,12)
m=numel(x);
N=10; %Window length
for n=0:m-N;
y=x(1+n:N+n)
end
Full code will be below.
xr=randi([1 150],1,20)
z=numel(xr);
N=10; %Window length
gAll=zeros(1,z-N+1);
for n=0:z-N;
x=xr(1+n:N+n)
d=max(x);
m=numel(x);
y=zeros(d,1);
p=zeros(d,d);
for k=1:m-1
y(x(k))=y(x(k))+1;
p(x(k),x(k+1))=p(x(k),x(k+1))+1;
end
p=bsxfun(#rdivide,p,y);
p(isnan(p)) = 0;
j=prod(p(p~=0));
[~,~,idx] = unique(x);
q=prod(hist(idx,1:max(idx))/numel(x));
s=log(j);
l=log(q);
g=s+l
gAll(n+1)=g;
end
plot(gAll)
My code works in the following manner:
1.First, it obtains several images from the training set
2.After loading these images, we find the normalized faces,mean face and perform several calculation.
3.Next, we ask for the name of an image we want to recognize
4.We then project the input image into the eigenspace, and based on the difference from the eigenfaces we make a decision.
5.Depending on eigen weight vector for each input image we make clusters using kmeans command.
Source code i tried:
clear all
close all
clc
% number of images on your training set.
M=1200;
%Chosen std and mean.
%It can be any number that it is close to the std and mean of most of the images.
um=60;
ustd=32;
%read and show images(bmp);
S=[]; %img matrix
for i=1:M
str=strcat(int2str(i),'.jpg'); %concatenates two strings that form the name of the image
eval('img=imread(str);');
[irow icol d]=size(img); % get the number of rows (N1) and columns (N2)
temp=reshape(permute(img,[2,1,3]),[irow*icol,d]); %creates a (N1*N2)x1 matrix
S=[S temp]; %X is a N1*N2xM matrix after finishing the sequence
%this is our S
end
%Here we change the mean and std of all images. We normalize all images.
%This is done to reduce the error due to lighting conditions.
for i=1:size(S,2)
temp=double(S(:,i));
m=mean(temp);
st=std(temp);
S(:,i)=(temp-m)*ustd/st+um;
end
%show normalized images
for i=1:M
str=strcat(int2str(i),'.jpg');
img=reshape(S(:,i),icol,irow);
img=img';
end
%mean image;
m=mean(S,2); %obtains the mean of each row instead of each column
tmimg=uint8(m); %converts to unsigned 8-bit integer. Values range from 0 to 255
img=reshape(tmimg,icol,irow); %takes the N1*N2x1 vector and creates a N2xN1 matrix
img=img'; %creates a N1xN2 matrix by transposing the image.
% Change image for manipulation
dbx=[]; % A matrix
for i=1:M
temp=double(S(:,i));
dbx=[dbx temp];
end
%Covariance matrix C=A'A, L=AA'
A=dbx';
L=A*A';
% vv are the eigenvector for L
% dd are the eigenvalue for both L=dbx'*dbx and C=dbx*dbx';
[vv dd]=eig(L);
% Sort and eliminate those whose eigenvalue is zero
v=[];
d=[];
for i=1:size(vv,2)
if(dd(i,i)>1e-4)
v=[v vv(:,i)];
d=[d dd(i,i)];
end
end
%sort, will return an ascending sequence
[B index]=sort(d);
ind=zeros(size(index));
dtemp=zeros(size(index));
vtemp=zeros(size(v));
len=length(index);
for i=1:len
dtemp(i)=B(len+1-i);
ind(i)=len+1-index(i);
vtemp(:,ind(i))=v(:,i);
end
d=dtemp;
v=vtemp;
%Normalization of eigenvectors
for i=1:size(v,2) %access each column
kk=v(:,i);
temp=sqrt(sum(kk.^2));
v(:,i)=v(:,i)./temp;
end
%Eigenvectors of C matrix
u=[];
for i=1:size(v,2)
temp=sqrt(d(i));
u=[u (dbx*v(:,i))./temp];
end
%Normalization of eigenvectors
for i=1:size(u,2)
kk=u(:,i);
temp=sqrt(sum(kk.^2));
u(:,i)=u(:,i)./temp;
end
% show eigenfaces;
for i=1:size(u,2)
img=reshape(u(:,i),icol,irow);
img=img';
img=histeq(img,255);
end
% Find the weight of each face in the training set.
omega = [];
for h=1:size(dbx,2)
WW=[];
for i=1:size(u,2)
t = u(:,i)';
WeightOfImage = dot(t,dbx(:,h)');
WW = [WW; WeightOfImage];
end
omega = [omega WW];
end
% Acquire new image
% Note: the input image must have a bmp or jpg extension.
% It should have the same size as the ones in your training set.
% It should be placed on your desktop
ed_min=[];
srcFiles = dir('G:\newdatabase\*.jpg'); % the folder in which ur images exists
for b = 1 : length(srcFiles)
filename = strcat('G:\newdatabase\',srcFiles(b).name);
Imgdata = imread(filename);
InputImage=Imgdata;
InImage=reshape(permute((double(InputImage)),[2,1,3]),[irow*icol,1]);
temp=InImage;
me=mean(temp);
st=std(temp);
temp=(temp-me)*ustd/st+um;
NormImage = temp;
Difference = temp-m;
p = [];
aa=size(u,2);
for i = 1:aa
pare = dot(NormImage,u(:,i));
p = [p; pare];
end
InImWeight = [];
for i=1:size(u,2)
t = u(:,i)';
WeightOfInputImage = dot(t,Difference');
InImWeight = [InImWeight; WeightOfInputImage];
end
noe=numel(InImWeight);
% Find Euclidean distance
e=[];
for i=1:size(omega,2)
q = omega(:,i);
DiffWeight = InImWeight-q;
mag = norm(DiffWeight);
e = [e mag];
end
ed_min=[ed_min MinimumValue];
theta=6.0e+03;
%disp(e)
z(b,:)=InImWeight;
end
IDX = kmeans(z,5);
clustercount=accumarray(IDX, ones(size(IDX)));
disp(clustercount);
Running time for 100 images:Elapsed time is 103.947573 seconds.
QUESTIONS:
1.It is working fine for M=50(i.e Training set contains 50 images) but not for M=1200(i.e Training set contains 1200 images).It is not showing any error.There is no output.I waited for 10 min still there is no output.What is the problem?Where i was wrong?
To answer your second question, you can simply 'save' any generated variable as a .mat file in your working directory (Current folder) which can be accessed later. So in your code, if the 'training eigenfaces' is given by the variable 'u', you can use the following:
save('eigenface.mat','u')
This creates a .mat file with the name eigenface.mat which contains the variable 'u', the eigenfaces. Note that this variable is saved in your Current Folder.
In a later instance when you are trying out with your test data, you can simply 'load' this variable:
load('eigenface.mat')
This automatically loads 'u' into your workspace.
You can also save additional variables in the same .mat file if necessary
save('eigenface.mat','u','v'...)
The answer to the first question is that the code is simply not done running yet. Vectorizing the code (instead of using a for loop), as suggested in the comment section above can improve the speed significantly.
[EDIT]
Since the images are not very big, the code is not significantly slowed down by the first for loop. You can improve the performance of the rest of the code by vectorizing the code. Vectorized operations are faster than for-loops. This link might be useful in understanding vectorization:
http://www.mathworks.com/help/matlab/matlab_prog/vectorization.html
For example, the second for-loop can be replaced by the following vectorized form, as suggested in the comments
tempS = double(S);
meanS = mean(S,1);
stdS = std(S,0,1);
S = (tempS - meanS) ./ stdS;
Use MATLAB's timer functions tic and toc for finding how long the first for-loop alone is taking to execute. Add tic before the for loop and toc after it. If the time taken for 50 images is about 104 seconds, then it would be significantly more for 1200 images.
I am trying to find the max value and its location. Following is the example of the programme,
fname = dir('*.mat');
nfiles = length(fname);
vals = cell(nfiles,1);
phen = cell(nfiles,1);
for i = 1:nfiles
vals{i} = load(fname(i).name);
phen{i} = (vals{i}.phen);
[M, position] = max(phen{i},[],3);
clear vals
end
After the program is executed, all the position is showing 1. There are total 15 files and M is taking the values of the last file.
How to overcome this prpoblem? Any help will be appreciated
I am not sure I understand your question.
However, at every iteration you are computing the max value and position and overwriting them in the next iteration (i.e. not storing them anywhere). So at the end of the loop M and position would correspond to the last entry phen{nfiles}.
Each time you run through your for loop, you are overwriting M with the max from the most recently loaded phen from the dimension of 3. Since your data is only two dimensional, you probably should be using a dimension of 1 or 2 instead of 3. Because you are using 3, max is returning 1 to position. Fix the dimension issue and position should then be the correct value.
What you could do is make M and position the size of nfiles. So instead of
[M, position] = max(phen{i},[],3);
do
%create M and positions arrays here
%ex. M(nfiles) = 0; or a smaller value if your values are negative
%do the same for positions
[M(i), positions(i)] = max(phen{i},[],1); %1 or 2 correction here here!
then after your for loop
...
end
[maxM, maxMposition] = max(M);
position = positions(maxMposition);