Save image in actual size in matlab - matlab

I want to save color image in original size (here is 146 by 220 pixel), but by this method the image will be saved in 1200 by 897 including extra marging. Actually the image will be save in larger size. I want to save it exactly in 146 by 220 pixel. Because i want to compare its pixels one by one with original image's. If i gain extra pixel comparing activity will be problematic for me.
Thank you in advance for your attention.
function []=doCmeans (imInput)
H = single(imInput(:));% original image is gray scale
nRegions = 5;
options = [2 100 1e-5 0];
[Center, U, obj_fun] = fcm (H,nRegions,options);
maxU = max(U);
for i = 1:nRegions
tmpindex = find (U(i,1))==maxU;
H (tmpindex)= i;
end
[r c]=size (imInput);
imFClass = reshape (H, r,c);
colormap(hsv(5));
h = figure('visible', 'off'); imshow(imFClass,[]);
print(h,'-djpeg',sprintf('ImFuzzy.jpg'));
end

The answer from Daniel is correct and is how you should do it, but if you still really need to save the image from the figure you have to do a couple of extra steps.
First you want to make sure that the figure has the exact same size of the image you're showing and then you want to get the content of the figure.
To do so, just give to imshow the arguments 'Border','tight'.
h = figure('visible', 'off'); imshow(imFClass,[], 'Border','tight');
Then you obtain and save the colour data from the frame as follow
myPic = getframe(h);
imwrite(myPic.cdata, 'yourPathName','yourFormat')
And this should do the trick.
However this is obviously useless if you just need to save the image and not really the content of a figure.

print saves the object you are passing, in this case a figure and not an image. The figure has probably a larger size. Use imwrite instead, and don't forget to pass the map.

Related

How can I merge multiple images into one and save it on matlab?

I need to merge multiple bitmap of same sizes into one image.That image is basically rotated in different angles and needs to be merged into one whole image. I have tried multiple methods but I come with many issues as I am not able to save that image.
I have tried multiple codes but I actually cannot make sense out of it. What I want to achieve is transparent overlay (not sure) that superimposes two images and you can actually see both one image
figure1 = figure;
ax1 = axes('Parent',figure1);
ax2 = axes('Parent',figure1);
set(ax1,'Visible','off');
set(ax2,'Visible','off');
[a,map,alpha] = imread('E:\training data\0.bmp');
I = imshow(a,'Parent',ax2);
set(I,'AlphaData',alpha);
F = imshow('E:\training data\200.bmp','Parent',ax1);
I just want to superimpose multiple images.
This is my data set:
This is what I want to achieve, i want to add all of the rotated images and achieved into one
This is what I get sadly, I have tried everything
The following does kind of what you want. First load the image, then divide it into 6 equal blocks, and add these. To add the pixel values, I first converted the image to doubles, since uint8 only can go up to pixel values of 255. This would mean that you will just see a large bright spot in the image because you are clipping.
Then add all the blocks. You will see in the output, that the car is not always perfect in the center of the block, so depending on what you are trying to achieve you may want to align the blocks using something like xcorr2.
% load image
A = imread('S82CW.jpg');
fig = figure(1); clf
image(A);
% convert A to double and divide in blocks.
A = double(A);
[img_h, img_w, ~] = size(A);
block_h = img_h/2;
block_w = img_w/3;
% split image in blocks
Asplit = mat2cell(A, repelem(block_h,2), repelem(block_w,3), 3);
% check if splitting makes sense
figure(2); clf
for k = 1:numel(Asplit)
subplot(3,2,k)
image(uint8(Asplit{k}))
end
% superimpose all blocks,
A_super = zeros(size(Asplit{1,1}),'like',Asplit{1,1} ); % init array, make sure same datatype
for k = 1:numel(Asplit)
A_super = A_super + Asplit{k};
end
% divide by max value in A and multiply by 255 to make pixel
% values fit in uint8 (0-255)
A_super_unit8 = uint8(A_super/max(A_super,[],'all')*255);
figure(3); clf;
image(A_super_unit8)

How can I traverse through pixels?

Suppose, I have the following image in my hand.
I have marked some pixels of the image as follows,
Now, I have obtained the pixel mask,
How can I traverse through only those pixels that are in that mask?
Given a binary mask, mask, where you want to iterate over all the true pixels in mask, you have at least two options that are both better than the double for loop example.
1) Logical indexing.
I(mask) = 255;
2) Use find.
linearIdx = find(mask);
I(linearIdx) = 255;
The original question:
How can I save only those pixels which I am interested in?
...
Question: Now, in the Step#2, I want to save those pixels in a data-structure (or, whatever) d so that I can apply another function f2(I, d, p,q,r) which does something on that image on the basis of those pixels d.
Create a binary mask
Try using a logical mask of the image to keep track of the pixels of interest.
I'll make up a random image for example here:
randImg = rand(64,64,3);
imgMask = false(size(randImg(:,:,1)));
imgMask(:,[1:4:end]) = true; % take every four columns This would be your d.
% Show what we are talking about
maskImg = zeros(size(randImg));
imgMaskForRGB = repmat(imgMask,1,1,3);
maskImg(imgMaskForRGB) = randImg(imgMaskForRGB);
figure('name','Psychadelic');
subplot(2,1,1);
imagesc(randImg);
title('Random image');
subplot(2,1,2);
imagesc(maskImg);
title('Masked pixels of interest');
Here's what it looks like:
It will be up to you to determine how to store and use the image mask (d in your case) as I am not sure how your functions are written. Hopefully this example will give you an understanding of how it can be done though.
EDIT
You added a second question since I posted:
But, now the problem is, how am I going to traverse through those pixels in K?
Vectrorization
To set all pixels to white:
randImg(imgMaskForRGB) = 255;
In my example, I accessed all of the pixels of interest at the same time with my mask in a vectorized fashion.
I translated my 2D mask into a 3D mask, in order to grab the RGB values of each pixel. That was this code:
maskImg = zeros(size(randImg));
imgMaskForRGB = repmat(imgMask,1,1,3);
Then to access all of these pixels in the image of interest, I used this call:
randImg(imgMaskForRGB)
These are your pixels of interest. If you want to divide these values in 1/2 you could do something like this:
randImg(imgMaskForRGB) = randImg(imgMaskForRGB)/2;
Loops
If you really want to traverse, one pixel at a time, you can always use a double for loop:
for r=1:size(randImg,1)
for c=1:size(randImg,2)
if(imgMask(r,c)) % traverse all the pixels
curPixel = randImg(r,c,:); % grab the ones that are flagged
end
end
end
Okay. I have solved this using the answer of #informaton,
I = imread('gray_bear.png');
J = rgb2gray(imread('marked_bear.png'));
mask = I-J;
for r=1:size(I,1)
for c=1:size(I,2)
if(mask(r,c))
I(r,c) = 255;
end
end
end
imshow(I);

How can i remove specific color from Image and Identify Positions?

I have an image as .png , i want to do following tasks with given image :
1 - Remove unnecessary White shade from image.
2 - Identify positions/coordinates of big black point in image.
For Task 1 my attempt is:
img = imread('1.png');
imshow(img);
I = img;
[r c] = size(I);
for i=1:r
for j=1:c
if I(i,j) > 230 %here i am changing 240 to different values to get result
%but this is just some hack
I(i,j) = 0;
end
end
end
imshow(I);
Where Original Image is :
And Matlab results are :
And for (2) i am out of ideas how can i do that any help appreciated.
Note: I am new in image processing, so kindly explain me in easy way so i can understand. thanks
For task 1, I am not entirely sure what you mean by "removing", from your code, I guess you would like to set the pixel values to 0.
A simpler and faster method would be:
img = imread('1.png');
img(img>230)=0;
This code sets all the values of img that are higher than 230 to zero.
img>230 creates a logical array with the size of img, true for elementes higher than 230, and false for others.
Then this logical array is used to set those pixels to 0. (But you could do anything you want with them)
Matlab was designed to do operations on vectors and matrices, looping through the elements is usually much slower.
For task 2, maybe look into this: http://nl.mathworks.com/help/images/examples/detect-and-measure-circular-objects-in-an-image.html

Save montage as image matlab

I have 225 image with put together with the montage function in matlab. And I can show them with montage. But i cannot save the montage as a complete image, please help me.
path = uigetdir;
D=dir(fullfile(path,'*.tif'));
imcell = cell(1,numel(D));
imcropped = cell(1,numel(D));
figure(1);
title('Drag square to crop picture, end with a double click',...
'FontSize', 15 , 'HandleVisibility' , 'off' ) ;
axis equal
set( gca , 'NextPlot' , 'replacechildren') ;
imcell1 = imread(D(50).name);
[~, rect] = imcrop(imcell1);
close(figure(1));
%
for i = 1:numel(D)
imcell{i} = imread(D(i).name);
imcropped{i} = imcrop(imcell{i}, rect);
end
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
The output on montage "h" is just a number.
I would like to point out a better way to do it. While Benoit_11's way is technically correct, it limits the resolution of the image to the size of your screen. When you use getframe(gca), Matlab is effectively taking a screenshot of the current axes contents, at whatever size your figure window is currently in.
A better way to do this is to use the handle, as it references the actual graphical output of montage() instead of what it displays as. To save an image from the handle, you need to get the cdata from the object it references with get:
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
MyMontage = get(h, 'CData');
imwrite(MyMontage, 'FancyName.tif', 'tif');
This way you get the full resolution of the montage, not just the resolution from displaying it.
For more information on image handles: http://www.mathworks.com/help/matlab/creating_plots/the-image-object-and-its-properties.html
You're almost there! The value 'h' is actually the handles to the image object created by the montage you made in the figure. What you can do is use getframe to capture the content of the figure (graphics object) and save it as an image. Here is a very simple example, with the code going directly after yours
h=montage(cat(4,imcropped{:}),'Size', [15 15] );
MyMontage = getframe(gca) %// Get content of current axes. I did it with sample images.
The output is the following:
MyMontage =
cdata: [384x1024x3 uint8] % Yours will be different
colormap: []
Hence you can save the actual data, stored in cdata, in a new file and you're good to go!
imwrite(MyMontage.cdata,'FancyName.tif','tif');

Create a bitmap from patch object in Matlab

I have a set of polygon vertices in in X, Y matrices and their colors are in RGB values in another matrix C.
I then use fill() function to generate patch objects that is displayed in a Matlab figure.
I want to create a bmp object from this figure. What I mean by a bmp object is the x,y coordinates of the pixels and there RGB values.
If I use the print() function, with '-dbmp' and a file name, matlab can write the bmp to a file. But then I have to read the file with imread() to create the bmp object.
Is there a way to create the bmp object without writing and reading to from a file?
Becauswe I have to perform this operation many times and writing and reading to file is time consuming and will reduce the life time of my disk too I guess.
Edit: code after editing according to answer
N = 5;
Tri = 100;
res = 200; %200 pixles per inch
G = zeros(Tri,9,N);
X = 2*rand(Tri,3,N);
Y = 2*rand(Tri,3,N);
R = randi([0 255],Tri,N)/255;
G = randi([0 255],Tri,N)/255;
B = randi([0 255],Tri,N)/255;
for c1=1:N
G(:,1:3,c1)= X(:,:,c1);
G(:,4:6,c1)= Y(:,:,c1);
G(:,7,c1)= R(:,c1);
G(:,8,c1)= G(:,c1);
G(:,9,c1)= B(:,c1);
end
for c2=1:N;
h = figure('Visible','off');
set(h, 'PaperUnits', 'inches', 'PaperPosition', [0 0 400 400]/res);
for c3 =1:Tri
h1 = fill(G(c3,1:3,c2), G(c3,4:6,c2), [G(c3,7,c2) G(c3,8,c2) G(c3,9,c2)]);
set(h1,'EdgeColor','None');
hold on;
end
%print(h,'-dbmp',['-r' num2str(res)],['file' num2str(c2)]);
F = getframe(h);
[a, b] = frame2im(F);
Tmp_v1 = a;
Tmp_v1 = Tmp_v1(:);
Norm_v1(c2) = norm(single(Tmp_v1));
end
Thank you.
If you have the current figure open, you can try the getframe idiom. Once you have access to this, you can access the frame's image data by looking at the cdata field in the structure. After you have this, you can use the imwrite command from MATLAB's image processing toolbox (let's hope you have it...) to write the image to file.
Here's an example:
x = 1 : 5;
y = 1 : 5;
plot(x,y); %// Plot a line
h = getframe;
img = h.cdata;
imwrite(img, 'testFrame.bmp');
This should be able to grab what is inside the current figure and save it to file. In this case, this will be a straight line from (x,y) = (1,1) to (x,y) = (5,5), with a slope of 1. Bear in mind that this won't save the title of the graph or the axes. This will only grab what is rendered inside the frame.
Edit from comments
Now that I know what you're really after, you want to generate a bunch of random polygons, then extract just the core image, without any axes or tick marks and so on. You'll have to modify your for loop where you're creating the images so that you want the figure to fill the entire window without any gray padding You'll also want to turn off the axis too. Also, when you're generating each image, you'll need to turn off the ticks. This is done with a combination of not writing any tick labels, as well as setting the tick length to 0. In other words, you'll need to modify your code so that it looks like this. You'll see where I inserted code by seeing the %// NEW statements in your code:
for c2=1:N;
h = figure('Visible','off');
subplot('position', [0 0 1 1]); %// NEW
axis off; %// NEW
set(h, 'PaperUnits', 'inches', 'PaperPosition', [0 0 400 400]/res);
for c3 =1:Tri
h1 = fill(G(c3,1:3,c2), G(c3,4:6,c2), [G(c3,7,c2) G(c3,8,c2) G(c3,9,c2)]);
set(h1,'EdgeColor','None');
set(gca,'xcolor','w','ycolor','w','xtick',[],'ytick',[]) %// NEW
set(gca,'Ticklength',[0 0]); %// NEW
hold on;
end
%print(h,'-dbmp',['-r' num2str(res)],['file' num2str(c2)]);
F = getframe(h);
close all; %// NEW
[a, b] = frame2im(F);
a = imresize(a, [400 400], 'nearest'); %// NEW
Tmp_v1 = a;
Tmp_v1 = Tmp_v1(:);
Norm_v1(c2) = norm(single(Tmp_v1));
end
This will still show you the frames being popped up for each image you're creating, but you should be able to get just pure image data at this point. Note that the images are still coming out as a bit larger than 400 x 400. This is due to the fact that once we have removed the borders and the tick marks and so on, the figure will stretch to fill the entire figure. To get around this, I use imresize and shrink the images back down to 400 x 400 as per your desired size.
Also, take note that every time you generate a new image, a new figure is spawned. Every time you call getframe, the figure with this randomly generated polygon image pops up, and getframe takes a snapshot of that current frame. There isn't a way to prevent this from happening, as you won't be able to take a snapshot of that figure. One way to get around this would be to close the figure after you grab the image. You can do a close all; after each call to getframe. That way, only one figure gets shown at any one time, but this still won't prevent the figure from showing up.
If I do find a solution to this, I'll let you know!