Resize an image along rows only or columns only in matlab - image

I'm writing a function in matlab to zoom or shrink an image using bicubic interpolation. However, my function resizes an image along both rows and columns. What if I want to enlarge the image along the rows only, or along the columns only? This is my code so far
function pic_new = zoom_image(pic, zoom_value)
actualSize = size(pic);
newSize = max(floor(zoom_value.*actualSize(1:2)),1);
newX = ((1:newSize(2))-0.5)./zoom_value+0.5; %# New image pixel X coordinates
newY = ((1:newSize(1))-0.5)./zoom_value+0.5;
oldClass = class(pic); %# Original image type
pic = double(pic); %# Convert image to double precision for interpolation
if numel(actualSize) == 2
pic_new = interp2(pic,newX,newY(:),'cubic');
end
pic_new = cast(pic_new,oldClass);
end
Updated: I was able to resize the image both along rows and columns. However, it doesn't work right
This is the original image: https://imagizer.imageshack.us/v2/895x383q90/r/903/4jM76I.png
This is the image after being enlarge 2.5 along rows and shrunk 1.3 along columns: https://imagizer.imageshack.us/v2/323x465q90/r/673/EHIaoB.png
Why is there such a black box in the result image?
Updated 2: This is how I did: in the command window type
>> img = imread('pic.pgm');
>> newImage = zoom_image(img, 2.5, 1/1.3);
>> imshow(newImage)

Using imresize it can be easily achieved
pic_new = imresize( pic, newSize, 'bicubic' );
Where newSize is the new size of the image (height and width). The new aspect ratio can be arbitrary and does not have to be the same as the aspect ratio of the new image.
For example, shrinking an image by 1/2 along the rows and leaving number of columns unchanged:
[nCol nRows] = size( pic(:,:,1) );
pic_new = imresize( pic, [nCols round( nRows/2 ) ], 'bicubic' );

Try editing your function to have a separate zoom for rows and columns, a la
function pic_new = zoomfunc(pic, zoom_valueX, zoom_valueY)
actualSize = size(pic);
newSize = max(floor([zoom_valueY zoom_valueX].*actualSize(1:2)),1);
newX = ((1:newSize(2))-0.5)./zoom_valueX+0.5; %# New image pixel X coordinates
newY = ((1:newSize(1))-0.5)./zoom_valueY+0.5;
oldClass = class(pic); %# Original image type
pic = double(pic); %# Convert image to double precision for interpolation
if numel(actualSize) == 2
pic_new = interp2(pic,newX,newY(:),'cubic');
end
pic_new = cast(pic_new,oldClass);
end

Related

Adjust Image on button

How can I adjust an image to a button in Tkinter?
Actually i have this :
originalImg = Image.open(currentphotofolderPath + file)
img = ImageTk.PhotoImage(originalImg)
Button(photoFrame, image = img, borderwidth=0, height = 200, width = 200)
The problem the image does not adjust to the button with 200x200
I don't want to resize the image with PhotoImage.resize()
The zoom() function should fix your issue:
Return a new PhotoImage with the same image as this widget but zoom it
with X and Y.
Adding the code line below before instantiating the Button() widget should be helpful:
originalImg = Image.open(currentphotofolderPath + file)
originalImg.zoom(200, 200)
img = ImageTk.PhotoImage(originalImg)
Button(photoFrame, image=img, borderwidth=0, height=200, width=200)
you have a couple of choices, the zoom function as posted by Billal, or you create a resize function:
def Resize_Image(image, maxsize):
r1 = image.size[0]/maxsize[0] # width ratio
r2 = image.size[1]/maxsize[1] # height ratio
ratio = max(r1, r2)
newsize = (int(image.size[0]/ratio), int(image.size[1]/ratio))
image = image.resize(newsize, Image.ANTIALIAS)
return image
which will then resize the Image (not the PhotoImage) to the biggest possible size while retaining the aspect ratio (without knowing it beforehand)
note that the resize method should use less memory than the zoom method (if thats an important factor)

Overlapping grayscale and RGB Images

I would like to overlap two images, one grayscale and one RGB image. I would like to impose the RGB image on top of the grayscale image, but ONLY for pixels greater than a certain value. I tried using the double function in MATLAB, but this seems to change the color scheme and I cannot recover the original RGB colors. What should I do in order to retain the original RGB image instead of mapping it to one of the MATLAB colormaps? Below is my attempt at superimposing:
pixelvalues = double(imread('hello.png'));
PixelInt = mean(pixelvalues,3);
I1 = ind2rgb(Brightfield(:,:,1), gray(256)); %Brightfield
I2 = ind2rgb(PixelInt, jet(256)); %RGB Image
imshow(I2,[])
[r,c,d] = size(I2);
I1 = I1(1:r,1:c,1:d);
% Replacing those pixels below threshold with Brightfield Image
threshold = 70;
I2R = I2(:,:,1); I2G = I2(:,:,2); I2B = I2(:,:,3);
I1R = I1(:,:,1); I1G = I1(:,:,2); I1B = I1(:,:,3);
I2R(PixelInt<threshold) = I1R(PixelInt<threshold);
I2G(PixelInt<threshold) = I1G(PixelInt<threshold);
I2B(PixelInt<threshold) = I1B(PixelInt<threshold);
I2(:,:,1) = I2R; I2(:,:,2) = I2G; I2(:,:,3) = I2B;
h = figure;
imshow(I2,[])
Original RGB Image:
Brightfield:
Overlay:
Is the content of pixelvalues what you show in your first image? If so, that image does not use a jet colormap. It has pink and white values above the red values, whereas jet stops at dark red at the upper limits. When you take the mean of those values and then generate a new RGB image with ind2rgb using the jet colormap, you're creating an inherently different image. You probably want to use pixelvalues directly in generating your overlay, like so:
% Load/create your starting images:
pixelvalues = imread('hello.png'); % Color overlay
I1 = repmat(Brightfield(:, :, 1), [1 1 3]); % Grayscale underlay
[r, c, d] = size(pixelvalues);
I1 = I1(1:r, 1:c, 1:d);
% Create image mask:
PixelInt = mean(double(pixelvalues), 3);
threshold = 70;
mask = repmat((PixelInt > threshold), [1 1 3]);
% Combine images:
I1(mask) = pixelvalues(mask);
imshow(I1);
Note that you may need to do some type conversions when loading/creating the starting images. I'm assuming 'hello.png' is a uint8 RGB image and Brightfield is of type uint8. If I load your first image as pixelvalues and your second image as I1, I get the following when running the above code:
Create a mask and use it to combine the images:
onionOrig = imread('onion.png');
onionGray = rgb2gray(onionOrig);
onionMask = ~(onionOrig(:,:,1)<100 & onionOrig(:,:,2)<100 & onionOrig(:,:,3)<100);
onionMasked(:,:,1) = double(onionOrig(:,:,1)) .* onionMask + double(onionGray) .* ~onionMask;
onionMasked(:,:,2) = double(onionOrig(:,:,2)) .* onionMask + double(onionGray) .* ~onionMask;
onionMasked(:,:,3) = double(onionOrig(:,:,3)) .* onionMask + double(onionGray) .* ~onionMask;
onionFinal = uint8(onionMasked);
imshow(onionFinal)

How to save the size of image in txt file with matlab

I want to find the size of an image (height, width, and area) and save the size value in txt file. I tried this command:
img = imread('TN4.jpg');
abu=rgb2gray(img);
imwrite(abu,'abu.jpg');
cb=imclearborder(abu);
imwrite(cb,'cb.jpg')
thresh=graythresh(cb);
b=im2bw(cb,thresh);
imwrite(b,'b.jpg');
bw=bwareaopen(b,100);
bwfill=imfill(bw,'holes');
imwrite(bwfill,'bw.jpg');
s = regionprops(bwfill,'BoundingBox');
out = bsxfun(#times,img,uint8(bwfill));
objects=cell(numel(s),1);
for idx = 1:numel(s)
bb=floor(s(idx).BoundingBox);
objects{idx} = out(bb(2):bb(2)+bb(4), bb(1):bb(1)+bb(3),:);
end
k1=objects{1};
c1=rgb2gray(k1);
t1=graythresh(c1);
biner1=im2bw(c1,t1);
[height, width] = size(biner1);
a1 = bwarea(biner1);
h1=height(biner1);
w1=width(biner1);
X = [(h1);(w1);(a1)];
save datagrading.txt X -ascii
but i got warning massage
??? Index exceeds matrix dimensions.
Error in ==> exercise at 35
h1=height(biner1);
can anyone help me?
Thank you
height and width are scalars yet (it looks like to me...) you are assuming that they are functions.... no they're not functions. Just use height and width on its own and place it into your X matrix:
[height, width] = size(biner1);
a1 = bwarea(biner1);
%h1=height(biner1); %// Remove
%w1=width(biner1); %// Remove
X = [height;width;a1]; %// Change
save datagrading.txt X -ascii
Since you have multiple objects and you want to save the height, width and area of these objects, just loop over each one, find the quantities you desire, place them into an overall matrix and save it:
X = zeros(3, numel(objects));
for k = 1 : numel(objects)
k1=objects{k}; %// Change
c1=rgb2gray(k1);
t1=graythresh(c1);
biner1=im2bw(c1,t1);
[height, width] = size(biner1);
a1 = bwarea(biner1);
X(:,k) = [height;width;a1];
end
save datagrading.txt X -ascii
X is now a 3 x s matrix where s is the total number of objects you have. Therefore, each column contains the height, width and area of each object.
You declared
[height, width] = size(biner1);
So height(biner1) will refer to the biner1-th element of height, which is not existent.
Use X = [(height);(width);(a1)]; instead.

Mid line through a set of dicom images in matlab

I have a set of Dicom images on matlab and i would like to add a midline going through all the images
I am outputting the images via imshow3d function
thanks
Edit: here's what i have, the random points are not in the middle they just run through the image
>> clc;
>>clear;
>>%imports dicom images
>>run DicomImport.m;
>>%random points for shortest distance test
>>a = [1 10 200];
>>b = [500 512 300];
>>ab = b - a;
>>n = max(abs(ab)) + 1;
>>s = repmat(linspace(0, 1, n)', 1, 3);
>>for d = 1:3
>> s(:, d) = s(:, d) * ab(d) + a(d);
>>end
>>s = round(s);
>>Z = 593;
>>N = 512;
>>X = zeros(N, N, Z);
>>X(sub2ind(size(X), s(:, 1), s(:, 2), s(:, 3))) = 1;
>>C = find(X);
>>ans.Img(C) = 5000;
>> %shows image
>>imshow3D(ans.Img);
So it looks like ans.Img contains the 3D matrix consisting of your image stack. It looks like you've got something going, but allow me to do this a bit differently. Basically, you need to generate a set of coordinates where we can access the image stack and draw a vertical line in the middle of the each image in the image stack. Do something like this. First get the dimensions of the stack, then determine the halfway point for the columns. Next, generate a set of coordinates that will draw a line down the middle for one image. After you do this, repeat this for the rest of the slices and get the column major indices for these:
%// Get dimensions
[rows,cols,slices] = size(ans.Img);
%// Get halfway point for columns
col_half = floor(cols/2);
%// Generate coordinates for vertical line for one slice
coords_middle_row = (1:rows).';
coords_middle_col = repmat(col_half, rows, 1);
%// Generate column major indices for the rest of the slices:
ind = sub2ind(size(ans.Img), repmat(coords_middle_row, slices, 1), ...
repmat(coords_middle_col, slices, 1), ...
reshape(kron(1:slices, ones(rows, 1)), [], 1));
%// Set the pixels accordingly
ans.Img(ind) = 5000;
This code is quite similar to the answer I provided to one of your earlier question; i.e. I don't use imshow3D but the framework is similar and simpler to modify in order to suit your need. In this case, upon pressing a pushbutton a line appears at the middle of the stack and you can scroll through it with the slider. I hope this can be of help.
function LineDicom(~)
clc
clear
close all
%// Load demo data
S = load('mri');
%// Get dimensions and number of slices.
ImageHeight = S.siz(1); %// Not used here
ImageWidth = S.siz(2); %// Not used here
NumSlices = S.siz(3);
S.D = squeeze(S.D);
%// Create GUI
hFig = figure('Position',[100 100 400 400],'Units','normalized');
%// create axes with handle
handles.axes1 = axes('Position', [0.2 0.2 0.6 0.6]);
%// create y slider with handle
handles.y_slider = uicontrol('style', 'Slider', 'Min', 1, 'Max', NumSlices, 'Value',1, 'Units','normalized','position', [0.08 0.2 0.08 0.6], 'callback', #(s,e) UpdateY);
handles.SlideryListener = addlistener(handles.y_slider,'Value','PostSet',#(s,e) YListenerCallBack);
%// Create pusbutton to draw line
handles.DrawLineButton= uicontrol('style', 'push','position', [40 40 100 30],'String','Draw line', 'callback', {#DrawLine,handles});
%// Flag to know whether pushbutton has been pushed
handles.LineDrawn = false;
%// Show 1st slice
imshow(S.D(:,:,1))
guidata(hFig,handles);
%// Listeners callbacks followed by sliders callbacks. Used to display each
%// slice smoothly.
function YListenerCallBack
handles = guidata(hFig);
%// Get current slice
CurrentSlice = round(get(handles.y_slider,'value'));
hold on
imshow(S.D(:,:,CurrentSlice));
%// If button was button, draw line
if handles.LineDrawn
line([round(ImageWidth/2) round(ImageWidth/2)],[1 ImageHeight],'Color','r','LineWidth',2);
end
drawnow
guidata(hFig,handles);
end
function UpdateY(~)
handles = guidata(hFig); %// Get handles.
CurrentSlice = round(get(handles.y_slider,'value'));
hold on
imshow(S.D(:,:,CurrentSlice));
if handles.LineDrawn
line([round(ImageWidth/2) round(ImageWidth/2)],[1 ImageHeight],'Color','r','LineWidth',2);
end
drawnow
guidata(hFig,handles);
end
%// Pushbutton callback to draw line.
function DrawLine(~,~,handles)
line([round(ImageWidth/2) round(ImageWidth/2)],[1 ImageHeight],'Color','r','LineWidth',2);
handles.LineDrawn = true;
guidata(hFig,handles);
end
end
Sample output:
and after moving the slider up:
Is this what you meant? If not I'll remove that answer haha and sorry.

Octave imwrite loses grayscale

I am using Octave 3.6.4 to process an image and store it afterwards. The image I read is grayscale, and after calculations the matrix should be of the same type. However, if I open the stored image, there are no gray pixels. There are only black and white ones and the gray ones got lost. They are essentially all white.
Here is the processing code:
function aufgabe13()
[img, map, alpha] = imread("Buche.png");
[imax, jmax] = size(img);
a = 0.7;
M = 255 * ones(imax,jmax + round(imax * a));
for i = 1:imax
begin = round((imax-i)*a);
M(i,begin +1 : begin + jmax) = img(i,:);
end
imwrite(M, 'BucheScherung.png', 'png');
end
So what am I doing wrong?
The reason why is because M is a double matrix so the values are expected to be between [0,1] when representing an image. Because your values in your image are between [0,255] when read in (type uint8), a lot of the values are white because they're beyond the value of 1. What you should do is convert the image so that it is double precision and normalized between [0,1], then proceed as normal. This can be done with the im2double function.
In other words, do this:
function aufgabe13()
[img, map, alpha] = imread("Buche.png");
img = im2double(img); % Edit
[imax, jmax] = size(img);
a = 0.7;
M = ones(imax,jmax + round(imax * a)); % Edit
for i = 1:imax
begin = round((imax-i)*a);
M(i,begin +1 : begin + jmax) = img(i,:);
end
imwrite(M, 'BucheScherung.png', 'png');
end

Resources