How can I change the outer limits of a Circular mask to a different colour - image

I have the following function that is successful in creating a grey circular mask over the image input, such that the new image is a grey border around a circular image. Example: Grey circular mask.
All I want to do is make the mask a very specific green, but I haven't been successful.
Here is the code:
function [newIm] = myCircularMask(im)
%Setting variables
rad = size(im,1)/2.1; %Radius of the circle window
im = double(im);
[rows, cols, planes]= size(im);
newIm = zeros(rows, cols, planes);
%Generating hard-edged circular mask with 1 inside and 0 outside
M = rows;
[X,Y] = meshgrid(-M/2:1:(M-1)/2, -M/2:1:(M-1)/2);
mask = double(zeros(M,M));
mask(X.^2 + Y.^2 < rad^2) = 1;
% Soften edge of mask
gauss = fspecial('gaussian',[12 12],0.1);
mask = conv2(mask,gauss,'same');
% Multiply image by mask, i.e. x1 inside x0 outside
for k=1:planes
newIm(:,:,k) = im(:,:,k).*mask;
end
% Make mask either 0 inside or -127 outside
mask = (abs(mask-1)*127);
% now add mask to image
for k=1:planes
newIm(:,:,k) = newIm(:,:,k)+mask;
end
newIm = floor(newIm)/255;
The type of green I would like to use is of RGB values [59 178 74].
I'm a beginner with MATLAB, so any help would be greatly appreciated.
Cheers!
Steve

After masking your image, create a color version of your mask:
% test with simple mask
mask = ones(10,10);
mask(5:7,5:7)=0;
% invert mask, multiply with rgb-values, make rgb-matrix:
r_green=59/255; g_green=178/255; b_green=74/255;
invmask=(1-mask); % use mask with ones/zeroes
rgbmask=cat(3,invmask*r_green,invmask*g_green,invmask*b_green);
Add this to your masked image.
Edit:
function [newIm] = myCircularMask(im)
%Setting variables
rad = size(im,1)/2.1; %Radius of the circle window
im = double(im);
[rows, cols, planes]= size(im);
newIm = zeros(rows, cols, planes);
%Generating hard-edged circular mask with 1 inside and 0 outside
M = rows;
[X,Y] = meshgrid(-M/2:1:(M-1)/2, -M/2:1:(M-1)/2);
mask = double(zeros(M,M));
mask(X.^2 + Y.^2 < rad^2) = 1;
% Soften edge of mask
gauss = fspecial('gaussian',[12 12],0.1);
mask = conv2(mask,gauss,'same');
% Multiply image by mask, i.e. x1 inside x0 outside
for k=1:planes
newIm(:,:,k) = im(:,:,k).*mask;
end
% Here follows the new code:
% invert mask, multiply with rgb-values, make rgb-matrix:
r_green=59/255; g_green=178/255; b_green=74/255;
invmask=(1-mask); % use mask with ones/zeroes
rgbmask=cat(3,invmask*r_green,invmask*g_green,invmask*b_green);
newIm=newIm+rgbmask;
Note that I haven't been able to test my suggestion, so there might be errors.

Related

Interp2 of image with transformed coordinates

I have 2 greyscale images that i am trying to align using scalar scaling 1 , rotation matrix [2,2] and translation vector [2,1]. I can calculate image1's transformed coordinates as
y = s*R*x + t;
Below the resulting images are shown.
The first image is image1 before transformation,
the second image is image1 (red) with attempted interpolation using interp2 shown on top of image2 (green)
The third image is when i manually insert the pixel values from image1 into an empty array (that has the same size as image2) using the transformed coordinates.
From this we can see that the coordinate transformation must have been successful, as the images are aligned although not perfectly (which is to be expected since only 2 coordinates were used in calculating s, R and t) .
How come interp2 is not producing a result more similar to when i manually insert pixel values?
Below the code for doing this is included:
Interpolation code
function [transformed_image] = interpolate_image(im_r,im_t,s,R,t)
[m,n] = size(im_t);
% doesn't help if i use get_grid that the other function is using here
[~, grid_xr, grid_yr] = get_ipgrid(im_r);
[x_t, grid_xt, grid_yt] = get_ipgrid(im_t);
y = s*R*x_t + t;
yx = reshape(y(1,:), m,n);
yy = reshape(y(2,:), m,n);
transformed_image = interp2(grid_xr, grid_yr, im_r, yx, yy, 'nearest');
end
function [x, grid_x, grid_y] = get_ipgrid(image)
[m,n] = size(image);
[grid_x,grid_y] = meshgrid(1:n,1:m);
x = [reshape(grid_x, 1, []); reshape(grid_y, 1, [])]; % X is [2xM*N] coordinate pairs
end
The manual code
function [transformed_image] = transform_image(im_r,im_t,s,R,t)
[m,n] = size(im_t);
[x_t, grid_xt, grid_yt] = get_grid(im_t);
y = s*R*x_t + t;
ymat = reshape(y',m,n,2);
yx = ymat(:,:,1);
yy = ymat(:,:,2);
transformed_image = zeros(m,n);
for i = 1:m
for j = 1:n
% make sure coordinates are inside
if (yx(i,j) < m & yy(i,j) < n & yx(i,j) > 0.5 & yy(i,j) > 0.5)
transformed_image(round(yx(i,j)),round(yy(i,j))) = im_r(i,j);
end
end
end
end
function [x, grid_x, grid_y] = get_grid(image)
[m,n] = size(image);
[grid_y,grid_x] = meshgrid(1:n,1:m);
x = [grid_x(:) grid_y(:)]'; % X is [2xM*N] coordinate pairs
end
Can anyone see what i'm doing wrong with interp2? I feel like i have tried everything
Turns out i got interpolation all wrong.
In my question i calculate the coordinates of im1 in im2.
However the way interpolation works is that i need to calculate the coordinates of im2 in im1 such that i can map the image as shown below.
This means that i also calculated the wrong s,R and t since they were used to transform im1 -> im2, where as i needed im2 -> im1. (this is also called the inverse transform). Below is the manual code, that is basically the same as interp2 with nearest neighbour interpolation
function [transformed_image] = transform_image(im_r,im_t,s,R,t)
[m,n] = size(im_t);
[x_t, grid_xt, grid_yt] = get_grid(im_t);
y = s*R*x_t + t;
ymat = reshape(y',m,n,2);
yx = ymat(:,:,1);
yy = ymat(:,:,2);
transformed_image = zeros(m,n);
for i = 1:m
for j = 1:n
% make sure coordinates are inside
if (yx(i,j) < m & yy(i,j) < n & yx(i,j) > 0.5 & yy(i,j) > 0.5)
transformed_image(i,j) = im_r(round(yx(i,j)),round(yy(i,j)));
end
end
end
end

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)

Matlab - Scale Colorbar of Image

How can I scale the colorbar axis of a false color image?
I read this post,and copied the code but it seems not to work correctly:
MATLAB Colorbar - Same colors, scaled values
Please see the two images below. In the first (without the scaling) the coloraxis goes
[1 2 3 4 5 6]*10^4
In the second image, it goes
[0.005 0.01 0.015 0.02 0.025]
The correct scaling (with C = 100000) would be
[0.1 0.2 0.3 0.4 0.5 0.6]
Without scaling
Wrong scaling
I want that the coloraxis is scaled by 1/C and I can freely choose C, so that when the pixel value = 10^4 and C=10^6 the scale should show 10^-2.
The reason why I multiply my image first by C is to get more decimals places, because all values below 1 will be displayed as zero without the C scaling.
When I run the code I get yticks as a workspace variable with the following values:
[500 1000 1500 2000 2500]
My code:
RGB = imread('IMG_0043.tif');% Read Image
info = imfinfo('IMG_0043.CR2'); % get Metadata
C = 1000000; % Constant to adjust image
x = info.DigitalCamera; % get EXIF
t = getfield(x, 'ExposureTime');% save ExposureTime
f = getfield(x, 'FNumber'); % save FNumber
S = getfield(x, 'ISOSpeedRatings');% save ISOSpeedRatings
date = getfield(x,'DateTimeOriginal');
I = rgb2gray(RGB); % convert Image to greyscale
K = 480; % Kamerakonstante(muss experimentel eavaluiert werden)
% N_s = K*(t*S)/power(f,2))*L
L = power(f,2)/(K*t*S)*C; %
J = immultiply(I,L); % multiply each value with constant , so the Image is Calibrated to cd/m^2
hFig = figure('Name','False Color Luminance Map', 'ToolBar','none','MenuBar','none');
% Create/initialize default colormap of jet.
cmap = jet(16); % or 256, 64, 32 or whatever.
% Now make lowest values show up as black.
cmap(1,:) = 0;
% Now make highest values show up as white.
cmap(end,:) = 1;
imshow(J,'Colormap',cmap) % show Image in false color
colorbar % add colorbar
h = colorbar; % define colorbar as variable
y_Scl = (1/C);
yticks = get(gca,'YTick');
set(h,'YTickLabel',sprintfc('%g', [yticks.*y_Scl]))
ylabel(h, 'cd/m^2')% add unit label
title(date); % Show date in image
caxis auto % set axis to auto
datacursormode on % enable datacursor
img = getframe(gcf);
nowstr = datestr(now, 'yyyy-mm-dd_HH_MM_SS');
folder = 'C:\Users\Taiko\Desktop\FalseColor\';
ImageFiles = dir( fullfile(folder, '*.jpg') );
if isempty(ImageFiles)
next_idx = 1;
else
lastfile = ImageFiles(end).name;
[~, basename, ~] = fileparts(lastfile);
file_number_str = regexp('(?<=.*_)\d+$', basename, 'match' );
last_idx = str2double(file_number_str);
next_idx = last_idx + 1;
end
newfilename = fullfile( folder, sprintf('%s_%04d.jpg', nowstr, next_idx) );
imwrite(img.cdata, newfilename);
Problems:
1) You are getting YTick of the figure (gca) but not the color bar. That would give you the "pixel" coordinates of the graph, instead of the actual values. Use yticks = get(h,'YTick');.
2) caxis auto Should come before overwriting YTicks (and after enabling the color bar); otherwise the scale and ticks will mismatch.
3) Do you mean C = 100000?
Result:

MATLAB second axis for colorbar following a convention

i want to make a second axis for the same colorbar of an false color image. the second scale should follow this convention : [new values] = Log10([old values]/108000)/-0.4 . i have this code for the first axis:
C = 10
hFig = figure('Name','False Color Luminance Map', 'ToolBar','none','MenuBar','none');
% Create/initialize default colormap of jet.
cmap = parula(16); % or 256, 64, 32 or whatever.
% Now make lowest values show up as black.
cmap(1,:) = 0;
% Now make highest values show up as white.
cmap(end,:) = 1;
imshow(J,'Colormap',cmap) % show Image in false color
colorbar % add colorbar
h = colorbar; % define colorbar as variable
caxis auto
y_Scl = (1/C);
yticks = get(h,'YTick');
set(h,'YTickLabel',sprintfc('%g', [yticks.*y_Scl]))
in a previous post here i got this lines for an second axis:
BarPos = get(hBar1,'position');
ylabel(hBar1,'label','FontSize',12);
haxes = axes('position',BarPos,'color','none','ytick',0:5:15,'ylim',[0 15],'xtick',[]);
how can i make the second axis use the the yticks of the first axis as an input for the convention?
EDIT: here is what i came up with. the thing is the values are wrong :/
fname='IMG_0041'; % select target image
C = 1000; % Constant to adjust image
K = 480; % Cameraconstant
RGB = imread([fname, '.tif']);% Read Image as tif
info = imfinfo([fname,'.CR2']); % get Metadata from CR2
x = info.DigitalCamera; % get EXIF
t = getfield(x, 'ExposureTime');% save ExposureTime
f = getfield(x, 'FNumber'); % save FNumber
S = getfield(x, 'ISOSpeedRatings');% save ISOSpeedRatings
date = getfield(x,'DateTimeOriginal'); % save DateTimeOriginal
I = rgb2gray(RGB); % convert Image to greyscale
% N_s = K*(t*S)/power(f,2))*L
L = power(f,2)/(K*t*S)*C; % calculate L/N_s
J = immultiply(I,L);
hFig = figure('Name','False Color Luminance Map', 'ToolBar','none', 'MenuBar','none');
% Create/initialize default colormap of jet.
cmap = parula(16); % or 256, 64, 32 or whatever.
% Now make lowest values show up as black.
cmap(1,:) = 0;
% Now make highest values show up as white.
cmap(end,:) = 1;
imshow(J,'Colormap',cmap) % show Image in false color
colorbar % add colorbar
h = colorbar; % define colorbar as variable
caxis auto
y_Scl = (1/C);
yticks = get(h,'YTick');
set(h,'YTickLabel',sprintfc('%g', [yticks.*y_Scl]))
BarPos = get(h,'position');
haxes = axes('position',BarPos,'color','none','ylim',[0 150]);
set(haxes,'YTickLabel', sprintfc('%g', log10(yticks.*y_Scl/108000)/-0.4));
https://www.sendspace.com/file/39wwm9 -> files for testing the code

Resize a polygon image in matlab

I have two polygon images defined by 25 control points. I want to replace one polygon by another one in matlab. Below is an example of TC and BP.
I have added the code. I am not happy with the output texture in the replaced area. Also, I found the that if the polygon shape of the second image is smaller than the first image polygon shape then the output looks very bad.
clc;clear all;close all
im_original = imread('tc.jpg');
im_original=im2double(im_original);
%% ROI (X,Y) coordinates, variable name (pt_original)
load('tc.mat');
im_morphed = imread('bp.jpg');
img_morphed=im2double(im_morphed);
%% ROI (X,Y) coordinates, variable name (pt_morphed)
load('bp.mat');
%% Replace Face
[img_proc,mask] = defineRegion(im_original,pt_original);
img_morphed_proc = histeq_rgb(img_morphed, im_original, mask, mask);
sigma = 5;
se = strel('square',sigma);
mask = imerode(mask,se);
w = fspecial('gaussian',[50 50],sigma);
mask = imfilter(double(mask),w);
img_result = bsxfun(#times,double(img_morphed_proc),double(mask)) + bsxfun(#times,double(im_original),double(1-mask));
imshow(img_result)
function [img_proc,mask] = defineRegion(img, landmark)
sz = size(img);
k =convhull(landmark(:,2),landmark(:,1));
[YY,XX] = meshgrid(1:sz(1),1:sz(2));
in = inpolygon(XX(:),YY(:),landmark(k,1),landmark(k,2));
mask = reshape(in,[sz(2),sz(1)])';
img_proc = bsxfun(#times,im2double(img),double(mask));
end
function img_proc = histeq_rgb(img_src, img_dest, mask_src, mask_dest)
img_proc = img_src;
for i = 1 : 3
tmp_src = img_src(:,:,i);
tmp_src = tmp_src(mask_src);
tmp_dest = img_dest(:,:,i);
tmp_dest = tmp_dest(mask_dest);
t = histeq(tmp_src,imhist(tmp_dest));
tmp_proc = img_proc(:,:,i);
tmp_proc(mask_src) = t;
img_proc(:,:,i) = tmp_proc;
end
end
Output Image

Resources