MATLAB: applying filter to ROI or mask in greyscale image - matlab

I have a greyscale image (I), and would like to apply different filters to different regions of that image in matlab (R2015b) (random and irregular shaped regions). I have a binarized version of what I would like the first filter applied to (attached). I'm not sure the best way to make a mask...I can load this binary image and use bwconncomp to locate connected components and define them as single vectors which won't work with poly2mask. Any suggestions for A. how to get a mask out of this binary image and B. how to use this mask to apply a filter to that part of the greyscale image?
Thanks in advance!
MASK=imread('/Users/bk/Desktop/FIJI_image/mask4.tif');
BACK=imcomplement(MASK);
I=imread('/Users/bk/Desktop/FIJI_image/Orig.tif');
I(~MASK)=0;
SE=ones(13,13);
A=stdfilt(I, SE);
minZ=min(min(A));
maxZ=max(max(A));
Low_High=[minZ maxZ];
var5=255/maxZ;
B=uint8(A*var5);
C=(imadjust(B,stretchlim(B),[]));
imtool(C);

A binary image is a mask.
Given a grayscale image I and a binary image M with the same size, you can get the image I filtered by the mask M using:
J = I;
J(~M) = 0;
This is just masking. For filtering you can apply a filter on I with imfilter or any other one of MATLAB's filter functions. For example:
h = fspecial('motion', 50, 45);
K = imfilter(I, h);
Now you can get the original values of the pixels which are not in M:
K(~M) = I(~M);
So now K have filtered pixels in the locations where M is true, and untempered pixels in the locations where M is false.
Code for the example you added:
inputDir = 'temp2';
I = imread(fullfile(inputDir, 'PJlUm.png'));
M = imread(fullfile(inputDir, 'ewSPv.png'));
M = logical(M); % Convert M to a logical matrix, i.e. a mask.
Imasked = I;
Imasked(~M) = 0;
ImaskedAndStretched = Imasked;
ImaskedAndStretched(M) = imadjust(ImaskedAndStretched(M),stretchlim(ImaskedAndStretched(M)),[]);
IstretchedAtMask = I;
IstretchedAtMask(M) = ImaskedAndStretched(M);
figure;
subplot(3,2,1);
imshow(I);
title('Input Image');
subplot(3,2,2);
imshow(M);
title('Mask');
subplot(3,2,3);
imshow(Imasked);
title('Image Masked');
subplot(3,2,4);
imshow(ImaskedAndStretched);
title('Image Masked & Stretched');
subplot(3,2,5);
imshow(IstretchedAtMask);
title('Image Stretched At Mask');
The output:

Related

Functions that calculates a filter mask of size NXN and applies it to an input image I using conv2() function in Matlab

I am trying to write a function to create a filter mask of size NXN and then apply it to an image read in. Here is my attempt...
function Iout = noiseReduction(I, N)
image = imread(I);
figure(3)
subplot(2,1,1), imshow(image), title('Original Image', 'FontSize', 15);
mask = ones(3,3) * N;
Iout = conv2(image, mask);
subplot(2,1,2), imshow(uint8(Iout)), title('Blurred Image', 'FontSize', 15);
end
However, when I run the function I don't get any output in Blurred Image I just get a blank square. Can anyone help me figure out what is wrong with this? Any help would be fantastic.
mask = ones(3,3) * N;
This is not a NxN filter, but a 3x3 filter where each element has a value of N.
By convolving with such a filter, you obtain an image with very large values. You later cast this to uint8, clamping all values to 255. Hence the image looks all white.
Instead, define your kernel as:
mask = ones(N,N) / N^2;
Now mask is NxN and sums to 1, meaning that the output will remain in the same range as the input.

How to find radial distortion coefficients between two sets of points?

Title changed from: Specific transformation/distortion of an image using checkerboard coordinates
I have two checkerboard images. One of them is slightly more distorted than the other. I think it's a type of "barrel" distortion. I'm trying to compute the radial distortion parameters (or generate camera parameters) in order to distort one of the images to look like the other so that the checkerboard corners will line up.
Here is the binary undistorted image with its corners plotted in blue o's and the reference coordinates of the corners that we need to distort the image to plotted in red o's.
Most of the distortion is happening around the edges and the corners. I believe this is a type of radial distortion. How do I find the radial distortion coefficients between the two sets of coordinates representing the checkerboard corners?
Link to Image A (undistorted): http://imgur.com/rg4PNvp
Link to Image B (distorted): http://imgur.com/a/BIvid
I need to transform the checkerboard from Image B to have its corners line up with the corners from image A.
I have tried modifying the MATLAB Camera Calibration app generated script (link). I changed the world points that would be used to estimate camera parameters to equal my world points (corners) from Image A. However, this wasn't successful. The code I tried is can be seen in this pastebin: https://pastebin.com/D0StCb0p I used the same image in the imageFileNames because estimateCameraParameters requires at least 2 sets of coordinates.
Code:
% Define images to process
imageFileNames = {'C:\Users\asavelyev\Pictures\checkerB.tif',...
'C:\Users\asavelyev\Pictures\checkerB.tif',...
};
% Detect checkerboards in images
[imagePoints, boardSize, imagesUsed] = detectCheckerboardPoints(imageFileNames);
imageFileNames = imageFileNames(imagesUsed);
% Read the first image to obtain image size
originalImage = imread(imageFileNames{1});
[mrows, ncols, ~] = size(originalImage);
% AS: change these worldPoints to points of RGB image...
% Generate world coordinates of the corners of the squares
worldPoints = detectCheckerboardPoints('C:\Users\asavelyev\Pictures\checkerA.tif');
% Calibrate the camera
[cameraParams, imagesUsed, estimationErrors] = estimateCameraParameters(imagePoints, worldPoints, ...
'EstimateSkew', false, 'EstimateTangentialDistortion', false, ...
'NumRadialDistortionCoefficients', 2, 'WorldUnits', 'millimeters', ...
'InitialIntrinsicMatrix', [], 'InitialRadialDistortion', [], ...
'ImageSize', [mrows, ncols]);
% For example, you can use the calibration data to remove effects of lens distortion.
undistortedImage = undistortImage(originalImage, cameraParams);
This was solved by using this post from Mathematics StackOverflow: https://math.stackexchange.com/questions/302093/how-to-calculate-the-lens-distortion-coefficients-with-a-known-displacement-vect
Main issue I oversaw was the normalizion of the data points used in computing the K coefficients used in radial distortion.
Here is the MATLAB script I wrote for finding these coefficients:
% input images should be black and white checkerboards already thresholded into a binary image
% output image are the K coefficients used in radial distortion
function K = CalculateRadialDistortion(DistortedImg, UndistortedImg)
distortedCorners = detectCheckerboardPoints(DistortedImg);
undistortedCorners = detectCheckerboardPoints(UndistortedImg);
% normalize data
X1 = distortedCorners(:,1) - size(DistortedImg, 2)/2;
Y1 = distortedCorners(:,2) - size(DistortedImg, 1)/2;
X1p = undistortedCorners(:,1) - size(DistortedImg, 2)/2;
Y1p = undistortedCorners(:,2) - size(DistortedImg, 1)/2;
% X1p = (1+k1*r^2 + k2*r^4)X1 where r^2 = X1^2 + Y1^2
Rsq = X1.^2 + Y1.^2;
Rquad = Rsq.^2;
Rsqd = cat(1, Rsq, Rsq);
Rquadd = cat(1, Rquad, Rquad);
R = cat(2, Rsqd, Rquadd);
X1poX1 = X1p ./ X1;
X1poX1 = X1poX1 - 1;
Y1poY1 = Y1p ./ Y1;
Y1poY1 = Y1poY1 - 1;
X1Y1 = cat(1, X1poX1, Y1poY1);
K = linsolve(R, X1Y1);
end

How to smoothen the edges from an image obtained from imagesc function

I have an RGB image obtained from saving the imagesc function as shown below. how to refine/smoothen the edges present in the image.
It consists of sharper edges, where I need to smoothen them. Im not able to find a solution for performing this for an RGB image. Instead of the staircase effect seen in the image I'd like to even out the edges. Please help thanks in advance.
maybe imresize will help you:
% here im just generating an image similar to yours
A = zeros(20);
for ii = -2:2
A = A + (ii + 3)*diag(ones(20-abs(ii),1),ii);
end
A([1:5 16:20],:) = 0;A(:,[1:5 16:20]) = 0;
subplot(121);
imagesc(A);
title('original')
% resizing image with bi-linear interpolation
B = imresize(A,100,'bilinear');
subplot(122);
imagesc(B);
title('resized')
EDIT
here I do resize + filtering + rounding:
% generates image
A = zeros(20);
for ii = -2:2
A = A + (ii + 3)*diag(ones(20-abs(ii),1),ii);
end
A([1:5 16:20],:) = 0;A(:,[1:5 16:20]) = 0;
subplot(121);
imagesc(A);
title('original')
% resizing
B = imresize(A,20,'nearest');
% filtering & rounding
C = ceil(imgaussfilt(B,8));
subplot(122);
imagesc(C);
title('resized')
solution
use imfilter and fspecial to perform a convolution of you image with gaussian.
I = imread('im.png');
H = fspecial('gaussian',5,5);
I2 = imfilter(I,H);
change 'blurlevel' parameter (which determines the gaussian kernel size) to make the image smoother or sharper.
result
If you are just looking for straighter edges, like an elevation map you can try contourf.
cmap = colormap();
[col,row] = meshgrid(1:size(img,2), 1:size(img,1));
v = linspace(min(img(:)),max(img(:)),size(cmap,1));
contourf(col,row,img,v,'edgecolor','none');
axis('ij');
This produces the following result using a test function that I generated.

Apply a gaussian distribution in a specific part of an image

I have for example the following image and a corresponding mask.
I would like to weight the pixels inside the white circle with a Gaussian, g = #(x,y,xc,yc) exp(-( ((x-xc)^2)/0.5 + ((y-yc)^2)/0.5 ));, placed in the centroid (xc,yc) of the mask. x, y are the coordinates of the corresponding pixels. Could you please someone suggest a way to do that without using for loops?
Thanks.
By "weighting" pixels inside the ellipse, I assume you mean multiply elementwise by a 2D gaussian. If so, here's the code:
% Read images
img = imread('img.jpg');
img = im2double(rgb2gray(img));
mask = imread('mask.jpg');
mask = im2double(rgb2gray(mask)) > 0.9; % JPG Compression resulted in some noise
% Gaussian function
g = #(x,y,xc,yc) exp(-(((x-xc).^2)/500+((y-yc).^2)./200)); % Should be modified to allow variances as parameters
% Use rp to get centroid and mask
rp_mask = regionprops(mask,'Centroid','BoundingBox','Image');
% Form coordinates
centroid = round(rp_mask.Centroid);
[coord_x coord_y] = meshgrid(ceil(rp_mask.BoundingBox(1)):ceil(rp_mask.BoundingBox(1))+rp_mask.BoundingBox(3)-1, ...
ceil(rp_mask.BoundingBox(2)):ceil(rp_mask.BoundingBox(2))+rp_mask.BoundingBox(4)-1);
% Get Gaussian Mask
gaussian_mask = g(coord_x,coord_y,centroid(1),centroid(2));
gaussian_mask(~rp_mask.Image) = 1; % Set values outside ROI to 1, this negates weighting outside ROI
% Apply Gaussian - Can use temp variables to make this shorter
img_g = img;
img_g(ceil(rp_mask.BoundingBox(2)):ceil(rp_mask.BoundingBox(2))+rp_mask.BoundingBox(4)-1, ...
ceil(rp_mask.BoundingBox(1)):ceil(rp_mask.BoundingBox(1))+rp_mask.BoundingBox(3)-1) = ...
img(ceil(rp_mask.BoundingBox(2)):ceil(rp_mask.BoundingBox(2))+rp_mask.BoundingBox(4)-1, ...
ceil(rp_mask.BoundingBox(1)):ceil(rp_mask.BoundingBox(1))+rp_mask.BoundingBox(3)-1) .* gaussian;
% Show
figure, imshow(img_g,[]);
The result:
If you instead want to perform some filtering within that roi, there's a function called roifilt2 which will allow you to filter the image within that region as well:
img_filt = roifilt2(fspecial('gaussian',[21 21],10),img,mask);
figure, imshow(img_filt,[]);
The result:

How can I implement a fisheye lens effect (barrel transformation) in MATLAB?

How can one implement the fisheye lens effect illustrated in that image:
One can use Google's logo for a try:
BTW, what's the term for it?
I believe this is typically referred to as either a "fisheye lens" effect or a "barrel transformation". Here are two links to demos that I found:
Sample code for how you can apply fisheye distortions to images using the 'custom' option for the function maketform from the Image Processing Toolbox.
An image processing demo which performs a barrel transformation using the function tformarray.
Example
In this example, I started with the function radial.m from the first link above and modified the way it relates points between the input and output spaces to create a nice circular image. The new function fisheye_inverse is given below, and it should be placed in a folder on your MATLAB path so you can use it later in this example:
function U = fisheye_inverse(X, T)
imageSize = T.tdata(1:2);
exponent = T.tdata(3);
origin = (imageSize+1)./2;
scale = imageSize./2;
x = (X(:, 1)-origin(1))/scale(1);
y = (X(:, 2)-origin(2))/scale(2);
R = sqrt(x.^2+y.^2);
theta = atan2(y, x);
cornerScale = min(abs(1./sin(theta)), abs(1./cos(theta)));
cornerScale(R < 1) = 1;
R = cornerScale.*R.^exponent;
x = scale(1).*R.*cos(theta)+origin(1);
y = scale(2).*R.*sin(theta)+origin(2);
U = [x y];
end
The fisheye distortion looks best when applied to square images, so you will want to make your images square by either cropping them or padding them with some color. Since the transformation of the image will not look right for indexed images, you will also want to convert any indexed images to RGB images using ind2rgb. Grayscale or binary images will also work fine. Here's how to do this for your sample Google logo:
[X, map] = imread('logo1w.png'); % Read the indexed image
rgbImage = ind2rgb(X, map); % Convert to an RGB image
[r, c, d] = size(rgbImage); % Get the image dimensions
nPad = (c-r)/2; % The number of padding rows
rgbImage = cat(1, ones(nPad, c, 3), rgbImage, ones(nPad, c, 3)); % Pad with white
Now we can create the transform with maketform and apply it with imtransform (or imwarp as recommended in newer versions):
options = [c c 3]; % An array containing the columns, rows, and exponent
tf = maketform('custom', 2, 2, [], ... % Make the transformation structure
#fisheye_inverse, options);
newImage = imtransform(rgbImage, tf); % Transform the image
imshow(newImage); % Display the image
And here's the image you should see:
You can adjust the degree of distortion by changing the third value in the options array, which is the exponential power used in the radial deformation of the image points.
I think you are referring to the fisheye lens effect. Here is some code for imitating fisheye in matlab.
Just for the record:
This effect is a type of radial distortion called "barrel distortion".
For more information please see:
http: //en.wikipedia.org/wiki/Distortion_(optics)
Here is a different method to apply an effect similar to barrel distortion using texture mapping (adapted from MATLAB Documentation):
[I,map] = imread('logo.gif');
[h,w] = size(I);
sphere;
hS = findobj('Type','surface');
hemisphere = [ones(h,w),I,ones(h,w)];
set(hS,'CData',flipud(hemisphere),...
'FaceColor','texturemap',...
'EdgeColor','none')
colormap(map)
colordef black
axis equal
grid off
set(gca,'xtick',[],'ztick',[],'ytick',[],'box','on')
view([90 0])
This will give you the circular frame you are looking for but the aliasing artifacts might be too much to deal with.