Using the affine2d command with the dicom images in matlab - matlab

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.

Related

How to plot a "moving" graph for real time values along the x-axis (using psychtoolbox)?

I am writing a code for a real time experiment using psychtoolbox to present the stimulus. In my experiment, I need to show the subject a graph that indicates his performance. I have plotted the graph using this simple code:
% Draw the graph
figure('visible','off','color',[0 0 0]);
pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
hold on;
pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
colormap([79 167 255;255 187 221]/256);
plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
axis([0,Num_timepoint+2,-10,10]);
saveas(gcf,'line_chart.png'); %save it
close(figure);
line_chart=imread('line_chart.png'); %read it
resized_plot=imresize(line_chart,0.5);
imageSize = size(resized_plot);
[imageHeight,imageWidth,colorChannels]=size(resized_plot);
bottomRect = [xCenter-imageWidth/1.5, yCenter+gapdown, xCenter+imageWidth/1.5, yCenter+gapdown+imageHeight];
imageDisplay=Screen('MakeTexture', win0, resized_plot);
Screen('DrawTexture', win0, imageDisplay, [], bottomRect);
Unfortunately, this simple code is very slow. In addition, I couldn't make the graph moving along x axis, as soon as the new value comes.
Any help would be Awesome. Thanks in advance for your efforts.
Why are you saving the figure and redisplaying as an image? Maybe I'm missing something but you should be able to accomplish what you need by updating the existing plot with the fresh data using the handles properties of the plot:
.... First time through we need the initial plot ....
% Set up figure with colormaps and such but leave as 'visible','on'
hPlot = plot(plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
hAxes = gca;
.... Loop over your real time updates ....
% Assuming value0 has subject's results from t=0 to t=now
hPlot.XData = value0; hPlot.YData = [1:subloop];
hAxes.XLim = [0 numTimePoints+2];
hAxes.YLim = [-10 10]
.... Continue test and update value0 ....
I think that should keep your plots current without having to save the figure as image to file then reopen the image to display to subject.
If you want to move your data one sample, you can use the circshift function. For example, if you want your new values to appear on the left hand side, you can shift all values 1 sample rightward, then add your new value in the first position.
For converting a MATLAB figure to a Psychtoolbox texture, you don't need to save, then load the temporary images. You can instead use the getframe function to capture the MATLAB figure data, which can then be given to MakeTexture to turn it into a Psychtoolbox texture.
I'm not sure what values you're actually using for subloop, value0, etc. but there is an example that I think might be close to what you want. In this example, 30 frames of figures are plotted, with each figure being on screen for 1 second. New data points are generated randomly and appear from the left hand side of the figure.
Depending on the details of your experiment, you may find that this approach is still too slow. You could also create the figure directly via Psychtoolbox drawing methods like DrawLines, etc. though that would require more effort.
try
win0 = Screen('OpenWindow', 0, 0);
Num_timepoint = 100;
subloop = 100;
value0 = zeros(1,100);
num_demo_frames = 30;
% Draw the graph
fig_h = figure('visible','off','color',[0 0 0]);
pcolor([0 Num_timepoint+2],[-10 0],ones(2,2));
hold on;
pcolor([0 Num_timepoint+2],[0 10],2*ones(2,2));
colormap([79 167 255;255 187 221]/256);
plot_h = plot(1:subloop,value0,'*-',...
'color',[0,0,0],...
'LineWidth',1,...
'MarkerSize',5,...
'MarkerEdgeColor','k',...
'MarkerFaceColor',[0.5,0.5,0.5]);
axis([0,Num_timepoint+2,-10,10]);
for f = 1:num_demo_frames
new_value = randn(1,1);
data_values = plot_h.YData;
data_values = circshift(data_values, 1);
data_values(1) = new_value;
plot_h.YData = data_values;
plot_values = getframe(fig_h);
imageDisplay=Screen('MakeTexture', win0, plot_values.cdata);
Screen('DrawTexture', win0, imageDisplay);
Screen('Flip', win0);
WaitSecs(1);
end
sca;
catch e
sca;
rethrow(e);
end

Rangefilt implementation

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.

Matlab get vector of specific pixels

I am pretty new to Matlab and encountered a problem when working with images.
I want to get a pixel that is in a specific colour (blue) in the following image:
image
My current code looks something like this:
function p = mark(image)
%// display image I in figure
imshow(image);
%// first detect all blue values higher 60
high_blue = find(image(:,:,3)>60);
%cross elements is needed as an array later on, have to initialize it with 0
cross_elements = 0;
%// in this iteration the marked values are reduced to the ones
%where the statement R+G < B+70 applies
for i = 1:length(high_blue)
%// my image has the size 1024*768, so to access the red/green/blue values
%// i have to call the i-th, i+1024*768-th or i+1024*768*2-th position of the "array"
if ((image(high_blue(i))+image(high_blue(i)+768*1024))<...
image(high_blue(i)+2*768*1024)+70)
%add it to the array
cross_elements(end+1) = high_blue(i);
end
end
%// delete the zero element, it was only needed as a filler
cross_elements = cross_elements(cross_elements~=0);
high_vector = zeros(length(cross_elements),2);
for i = 1:length(cross_elements)
high_vector(i,1) = ceil(cross_elements(i)/768);
high_vector(i,2) = mod(cross_elements(i), 768);
end
black = zeros(768 ,1024);
for i = 1:length(high_vector)
black(high_vector(i,2), high_vector(i,1)) = 1;
end
cc = bwconncomp(black);
a = regionprops(cc, 'Centroid');
p = cat(1, a.Centroid);
%// considering the detection of the crosses:
%// RGB with B>100, R+G < 100 for B<150
%// consider detection in HSV?
%// close the figure
%// find(I(:,:,3)>150)
close;
end
but it is not optimized for Matlab, obviously.
So i was wondering if there was a way to search for pixels with specific values,
where the blue value is larger than 60 (not hard with the find command,
but at the same time the values in the red and green area not too high.
Is there a command I am missing?
Since English isn't my native language, it might even help if you gave me some suitable keywords for googling ;)
Thanks in advance
Based on your question at the end of the code, you could get what you want in a single line:
NewImage = OldImage(:,:,1) < SomeValue & OldImage(:,:,2) < SomeValue & OldImage(:,:,3) > 60;
imshow(NewImage);
for example, where as you see you provide a restriction for each channel using logical operators, that you can customize of course (eg. using | as logical OR). Is this what you are looking for? According to your code you seem to be looking for specific regions in the image like crosses or coins is that the case? Please provide more details if the code I gave you is completely off the track :)
Simple example:
A = imread('peppers.png');
B = A(:,:,3)>60 & A(:,:,2)<150 & A(:,:,1) < 100;
figure;
subplot(1,2,1);
imshow(A);
subplot(1,2,2)
imshow(B);
Giving this:

normalize values for imadjust

I am trying to use imadjust, and in order to do that I have to normalize the values in my image (grayscale image) to 0~1. I have tried the following:
for getting min/max values:
minValue = min(I(:));
maxValue = max(I(:));
than I tried using imadjust in some ways:
Iadjusted = imadjust(I,[lowestValue/highestValue; highestValue/highestValue] ,[0 1]);
Iadjusted = imadjust(I,[lowestValue/255; highestValue/255] ,[]);
Iadjusted = imadjust(I,[double(lowestValue/highestValue); double(highestValue/highestValue)] ,[]);
but none of them worked. Each of them shows error/ shows the original image without any change. When I displayed min/max values the results were right, but when I am trying to display to normalization it always shows 0 or 1. What am I doing wrong?
In MATLAB images are stored using uint8 by default, therefore in [0 1] you can only have two integer number (i.e. 0 and 1). To do what you want between and get an image with range [0, 1] you have to use doubles.
Therefore if you want to use imadjust:
I = double(I)/255;
J = imadjust(I,[min(I(:)); max(I(:))],[0.0; 1.0]);
(Imadjust with doubles wants everything to be between 0 and 1. This is true in general for images expressed with doubles).
This function adjusts a signal (can be image) to the range [0,1]
function normsig = normalize(sig)
sig = double(sig);
normsig = (sig-min(sig(:))) / (max(sig(:))-min(sig(:))) ;
end
usage for an image signal:
img = imread('xxxx.jpg','jpg');
figure; imshow(img);
normalizedimg = normalize(img);
figure; imshow(normalizedimg);

Set hold on for some parts of a figure, not others

Below is my matlab code that plots a black line as it rotates around the origin. For the most part the code works, but because I use 'hold on', once I plot a line, it stays there for the entirety of the program.
What I'd like is something more like a second hand on a clock (only moving counter clockwise). For a particular value of i, the black line prints, and after i increments, that previous line is gone. However, I would like the red and blue lines and the plotted text to stay on the plot from iteration to iteration. I tried using the set() command and couldn't get it working, any ideas?
scalar = 3;
a = [3/scalar 2/scalar];
b = [-4/scalar .5/scalar];
starts = zeros(2,2);
ends = [a;b];
hold on
quiver(0,0,a(1),a(2),'color',[0 0 1],'linewidth',3);
quiver(0,0,b(1),b(2),'color',[1 0 0],'linewidth',3);
axisSize = 15/scalar;
axis([-axisSize axisSize -axisSize axisSize])
mintheta = [500, 500];
%waitforbuttonpress
for i=1:360
theta = [cos(2*pi()*i/360) sin(2*pi()*i/360)];
minDot = min(a*theta',-1*(b*theta'));
theta = theta/minDot;
hold on
if (minDot > 0)
if (norm(theta) < norm(mintheta))
mintheta = theta;
end
text(-4.5, 4, 'Drawing all Theta vectors,');
text(-4.5, 3.7, 'according to constraint that');
text(-4.5, 3.4, 'all dotProducts >= 1');
text(-4.5, 2.5, 'Yellow indicates a non-separating plane,');
text(-4.5, 2.2, 'SVM looks for shortest possible');
text(-4.5, 1.9, 'Theta (will be shown in green).');
quiver(0,0,theta(1),theta(2),'color',[0 0 0],'linewidth',5);
quiver(0,0,3/scalar,2/scalar,'color',[0 0 1],'linewidth',3);
quiver(0,0,-4/scalar,.5/scalar,'color',[1 0 0],'linewidth',3);
axis([-axisSize axisSize -axisSize axisSize])
else
quiver(0,0,cos(2*pi()*i/360),sin(2*pi()*i/360),'color',[1 1 0],'linewidth',5);
end
pause(.05);
end
quiver(0,0,mintheta(1),mintheta(2),'color',[0 1 0],'linewidth',3);
This should get you started:
% set up axis
axisSize = 5;
axis([-axisSize axisSize -axisSize axisSize])
cla
hold on
% draw quiver at initial position
q = quiver(0,0,cos(2*pi()*0/360),sin(2*pi()*0/360),'color',[0 0 0],'linewidth',5);
for i = 1:360
% modify data inside quiver plot
set(q,...
'xdata',0,...
'ydata',0,...
'udata',cos(2*pi()*i/360),...
'vdata',sin(2*pi()*i/360))
pause(.05);
end
Also, I would put the text outside the loop. It only needs to be created once, and MATLAB doesn't render stacks of identical text very nicely for some reason.