I want to show a stack of dicom files. I already have the code that loads the images, but i get an warning saying
Warning: Image is too big to fit on screen; displaying at 67%
> In imuitools\private\initSize at 71
In imshow at 282
In montage at 147
In dicom at 11
If you know how to fix this please let me know.
Here is my code:
% Preallocate the 256-by-256-by-1-by-20 image array.
X = repmat(uint16(0), [256 256 1 20]);
% Read the series of images.
for p=1:20
filename = sprintf('brain_%03d.dcm', p);
X(:,:,1,p) = dicomread(filename);
end
% Display the image stack.
montage(X,[])
The imshow function is very limited in its ability to rescale images, and suffers from some aliasing problems. To work around this, you can rescale your images using imresize prior to the call to imshow.
I had a lot of difficulty with imshow and the underlying image function, so I wrote a wrapper class that dynamically resizes images to fit the figure window. It is called RViewer, and it is a drop in replacement for image: http://www.mathworks.com/matlabcentral/fileexchange/46051-rviewer
Related
Very new to MatLab, just figuring some things out and had a question. I am basically trying to filter/blur an image using conv2() but I am getting an all white image when I am using imshow()
I am reading the image in with
testImage = imread('test.bmp');
This is a uint8 image of a grayscale.
I am trying to convolve the image with a 4 x 4 matrix.
fourByFour = ones(4);
When I actually execute, I am getting all white with imshow()
convolvedImage = conv2(testImage, fourByFour);
I should expect a filter placed on the image, not an entirely white one.
Any help would be appreciated.
I don't have your test image so I explain on an image. As the definition of conv2 it returns the two-dimensional convolution.
So please look at this little code:
clc;% clear the screen
clear all;% clear everything
close all;% close all figures
test = imread('test.bmp');
% read test image that is .bmp format and size :294x294x3 and uint8.
fourByFour = ones(4); % define 4 * 4 matrix all ones
convolvedImage = conv2(test(:,:,1), fourByFour);
%apply the ones matrix on image but to use conv2 on this image we apply on one of channels
figure, imshow(convolvedImage,[])
This is my command window, out put:
I'm using MAtlab 2017a, and if I use conv2(test, fourByFour); instead of conv2(test(:,:,1), fourByFour); ,the error is :
Error using conv2
N-D arrays are not supported.
So we should attention to class type and dimensions. And one more thing, in your command window please type edit conv2 you can read the details of this function and how to use it, but never edit it:). Thanks
test = imread('test.bmp');
% read test image that is .bmp format and size :294x294x3 and uint8.
fourByFour = ones(4);
% define 4 * 4 matrix all ones
test=rgb2gray(test);
% convert colorimage into gray
convolvedImage = conv2(double(test), double(fourByFour));
%perform the convolution
figure, imshow(convolvedImage,[])
% display the image
I have a program that creates a lot of plots which I want to save as fig001, fig002, .... At the moment, the only way I can do this is to either save them one by one as I go along using print() or so save them into a graphics object FIG.
Unfortunately, I have to create the plots sequentially (can't parallelise it). If I save as I go, then this takes quite a long time; if I store in FIG then do a parfor-loop over all the figures, then this is faster. However, it's still pretty slow, and it's a major bottleneck in my code.
Matlab is automatically writing a 1200x900 pixel image. In reality, it's just a graph with some (horizontal) straight lines on it. I really do not need a high image quality whatsoever; maybe reducing this would help speed things up? I can't find how to do this either.
I've had a look online, in particular at other SE questions, but I haven't been able to come up with a solution. There's various stuff about "playing around with the hardcore function". I'm a mathematician who wants a code to get some intuition for the problem; I'm not a proper programmer! As such, "play around with a function" (that might cause Matlab to crash) is rather difficult for me!
I've sorted this by using the Matlab movie function. Thank you Cecilia for your assistance!
Since your intention is to use the images in a slideshow. I would suggest making a movie and using that instead. I've run a few tests, and saving a movie is much faster than saving individual pngs. I see about a 5x speed up in my simple test.
numImages = 25;
%Saving one figure at a time
tic;
for i= 1:numImages
x = 0:0.1:2*pi;
y = i*sin(x);
plot(x, y);
fig = gcf;
print('img.png', '-dpng', '-r50'); %Downsample resolution
end
toc;
tic;
%Saving a movie
v = VideoWriter('mov.avi');
open(v);
for i = 1:numImages
x = 0:0.1:2*pi;
y = i*sin(x);
plot(x, y);
drawnow; %Force the figure to render
frame = getframe; %Convert the figure to a movie frame
writeVideo(v, frame); %Write the frame to the movie file
end
close(v);
toc;
Using writeVideo also has the advantage of never storing the whole movie in memory. Instead, as each frame is captured, it is immediately written to the file. The one downside is that because the frames need to be written in the correct sequence, you can not use a parfor
You could also consider making a movie matrix. Each element would be a frame. So to initialize the size of the matrix, you would need something like
numImages = 25;
mov(numImages) = struct('cdata',[],'colormap',[]);
Then using the parfor, you can assign all the images to your mov matrix in the correct order. After your loop is finished, you can write the movie to a file using VideoWriter. However, while generating your figures, you will need to keep your whole movie in memory, and there is an overhead associated with parfor, so it may not end up being more efficient.
If you made Matlab output a file like this, called "lines.txt" with each line describing the x1,y1 and x2,y2 of a line on your output image:
10 100 600 100
50 400 800 400
100 820 350 820
Then you could use ImageMagick to draw the lines like this:
#!/bin/bash
# Create the output image, 1200x900
convert -size 1200x900 xc:gray80 result.png
# Loop, reading one line at a time from the file "lines.txt"
while read x1 y1 x2 y2; do
echo Read line $x1,$y1 $x2,$y2
# Tell ImageMagick to draw the line on the image
convert result.png -stroke blue -strokewidth 5 -draw "line $x1,$y1 $x2,$y2" result.png
done < lines.txt
Obviously, you can draw non-horizontal lines and you could output a colour after the x,y coordinates and/or a thickness...
ImageMagick is installed on most Linux distros and is available for OSX and Windows. There are more efficient ways of plotting the lines, but this may be plenty to get you started.
Another option may be to use Gnuplot, see my other answer here.
On top of Cecilia's answer which suggests using getframe to generate a movie, I'd like to add that getframe can also be used to improve speed for saving static images. Combine it with frame2im to convert the figure into a rasterized image, and then use imwrite to save the rasterized image to a file.
frame = getframe(fig); % fig is the figure handle to save
[raster, raster_map] = frame2im(frame); % raster is the rasterized image, raster_map is the colormap
if isempty(raster_map)
imwrite(raster, fig_file);
else
imwrite(raster, raster_map, fig_file); % fig_file is the path to the image
end
In my particular case the time used to save the figures is reduced from ~60s for 19 files (using saveas) down to 7~9s using this method.
Do note that this method
Does not change the background color to white as saveas does;
Does not seem to support resolution and dpi other than that of the current figure;
Does not support saving as a vector image (obviously).
I am trying to create a movie in Matlab using series of functions under VideoWriter function. My code is somewhat like one shown below:
vidObj=VideoWriter('movie.avi');
open(vidObj);
for i=1:N %N is number of frames
[nx,ny]=coordinates(Lx,Ly,Nx,Ny,[x(i),-y(i)]);
%Lx and Ly refer to the length and height in meters.
%Nx and Ny are number of pixels (boxes) and fit into the respective L's.
%If Lx=10e-6 , with Nx=5, there will be 5 pixels in x dimension,
%each of length 2e-6 m.
[xf,yf]=ndgrid(nx,ny);
zf=zeros(size(xf))+z(i);
% generate a frame here
[E,H]=nfmie(an,bn,xf,yf,zf,rad,ns,nm,lambda,tf_flag,cc_flag);
Ecc=sqrt(real(E(:,:,1)).^2+real(E(:,:,2)).^2+real(E(:,:,3)).^2+imag(E(:,:,1)).^2+imag(E(:,:,2)).^2+imag(E(:,:,3)).^2);
clf
imagesc(nx/rad,ny/rad,Ecc)
rectangle('Position',[-rad(end),-rad(end),dia(end),dia(end)],'Curvature',[1,1]);
axis image;
axis off;
currFrame=getframe(gcf);
writeVideo(vidObj,currFrame);
end
close(vidObj);
return
This generated a movie called movie.avi. However, the movie (and the tif images generated from command window) has the dimensions of "420x560x3".
edit: the tif's are generated from the movie.avi using the following code:
obj = VideoReader('movie.avi');
vid = read(obj);
frames = obj.NumberOfFrames;
for x = 1 : frames
imwrite(vid(:,:,:,x),strcat('frame-',num2str(x),'.tif'));
end
I am trying to use these images in another software, IDL, following:
read Part 1 of this link
However, when runs on IDL, it detects the dimensions as [3x420x560], and therefore generates a really weird image when I run the normalization.
How do I fix this? Is using imwrite going to help?
I was able to successfully open the .tif in IDL, but it shows that the 420x560 is actually an image including an external grey boundary.
How do I remove this boundary? I tried seeing through my functions and they were fine. (I think)
I apologize in advance for asking so many questions. I am very new to this and need help. Thank you once again
I think that the grey boundary around your image is due to the fact that when the code grabs the frame (using getframe) it is being passed the handle to the current figure (gcf) which includes the grey boundary around the image. Try instead using the handle to the current axis
currFrame=getframe(gca);
I tried this and with gca there was no grey boundary around the image when I tried the
image(currFrame.cdata);
When I retrieved the frame, the data within that corresponded to the image was reduced in dimension. I'm not sure why the code does this but an alternative to getframe is to do the following
I = imread('someImage.jpg');
h = imagesc(I);
imageScData = get(h,'CData');
frameData = im2frame(imageScData);
Naturally, you won't have the first two lines since you are building your image at each iteration of the for loop. But I did notice that size(frameData.cdata)==size(I) - so no reduction.
You also mention how IDL (which I've never used) is reading in the files incorrectly or rather that the image dimensions are detected incorrectly. How are you writing out the image to a tif file? (I didn't see any MATLAB code above, like imwrite, indicating this.)
To fix interleave problem, i.e., 3 x 420 x 560 vs 420 vs 3 x 560 vs 420 x 560 x 3, when reading in IDL, use the INTERLEAVE keyword to READ_TIFF to specify how you want the result:
IDL> im = read_tiff(filename, interleave=2)
Hi all I am using montage command of matlab to display images. However I am facing a problem. The command that I use is given below:
dirOutput = dir('C:\Users\DELL\Desktop\book chapter\Journal chan vese\robust
contour initialization\book for document\4 phase\*.jpg');
fileNames = {dirOutput.name}'
montage(fileNames, 'Size', [1 6]);
export_fig combined1.jpg -r300
I have 6 images (all grayscale). However, the command prompt immediately throws an error like this:
//Error using montage>getImagesFromFiles (line 349)
//FILENAMES must contain images that are the same size.
//Error in montage>parse_inputs (line 225)
// [I,cmap] = getImagesFromFiles(varargin{1});
//Error in montage (line 112)
//[I,cmap,mSize,indices,displayRange] = parse_inputs(varargin{:});
//Error in montage_pics (line 3)
//montage(fileNames, 'Size', [1 6]);
I am even uploading some of my images here:
As can be seen clearly, all the images are grayscale. I then read the image size and they are as follows:
1.128X128 2.128X128*3 3.128X128*3 4.128X128 5.128X128*3 6.128X128*3.
So some of the images are treated as indeed colour images.
My question is how to use the montage command for such images. Another problem is that montage command always needs images of similar sizes. So I wanted to avoid this loopholes.
Of course I could use a software tool to convert the images to the required format but that is a bad way to work. I believe the below code if added to my original code will solve this problem
%Read Each Image
I=imread('image');
I=imresize(I,[128 128]);
I=I(:,:,1);
%Apply montage command
However I have failed to integrate this code in my original code. Please help me to solve this problem. Thanks in advance guys for your valuable suggestions and help.
To montage you have to make sure
The size matches
The datatype matches
All images are grayscale (or all images are rgb, but do not mix)
.
images={'eight.tif','fabric.png','football.jpg'};
%intended size
ssize=128;
%preallocation
IALL=zeros(ssize,ssize,1,numel(images));
for idx=1:numel(images)
%get image, ensure double to avoid issues with different colour depths
I=im2double(imread(images{idx}));
%resize
I=imresize(I,[ssize,ssize]);
%if rgb, change to gray
if size(I,3)>1 %rgb image
I=rgb2gray(I);
end
%insert
IALL(:,:,:,idx)=I;
end
montage(IALL);
so I'm using the imread function in matlab and when I save the TIFF file and open it in photoshop, it has a white border and I can't understand why. I want to maintain its resolution as a 512 by 512 image. Any ideas why? And how I can fix that?
Here's a sample code:
B = imread('W_noise1.tif');
for n = 1:5,
B = medfilt2(B);
end
B = filter2(fspecial('average',3),B)/255;
imshow(B)
Are you sure it's an issue with imread? I'd be surprised if it is.
See this link about medfilt2 where it explains that "medfilt2 pads the image with 0s on the edges, so the median values for the points within [m n]/2 of the edges might appear distorted."
EDIT: I tried to replicate your problem. This is an issue with print where it puts a white frame around the image after you save it. This functionality, print is made for printing plots. If you want to save the image, you should use imwrite.