Geometric mean filter in MATLAB - matlab

I = imread("example.tif");
G = imfilter(log(I), h, 'replicate');
G = exp(G);
G = G .^ (1/numel(h));
It gives the following error. Also, What do I need to write instead of 'h' parameter?
Check for incorrect argument data type or missing argument in call to function 'log'.

Follow the following example with comments for illustration.
I = imread('example.tif');
% Convert the image to double.
I = rgb2gray(im2double(I));
% Create the function you want to apply to the image — a geometric mean filter.
fun = #(x) geomean(x(:));
% Apply the filter to the image.
G = nlfilter(I,[5 5],fun);
% Display the original image and the filtered image, side-by-side.
montage({I,G})
title('Original Image (Left) and Geometric-Mean Filtered Image (Right)')

Related

How to draw a line between two coordinates of an image permanently in Matlab? [duplicate]

This question already has answers here:
MATLAB: Drawing a line over a black and white image
(5 answers)
Closed 4 years ago.
I have a set of points that I want to connect sequentially. Suppose the points are (A1,A2,A3,...A9); I want to connect A1 to A2, A2 to A3 and so on and finally connect A9 to A1.
All I need is to know a function that would help me connect A1 to A2, I could do the rest using for loops.
I know connecting two points is a question that has been asked here several times before but I couldn't find the answer I required. Several of the solutions suggest using "plot" and "line" but these functions overlay the results on the image and don't actually make any changes to the original image.
I did try them out and managed to save the resulting figure using the "saveas" and "print" functions but the image doesn't get saved in the proper format and there are a lot of problems using the parameters for these functions. Besides, I don't really want to save the image, it's just an unnecessary overhead I was willing to add if I could get the desired image with the lines.
I've also tried "imline" to draw lines but it seems to be interactive.
This particular question reflects my problem perfectly but when I ran the code snippets given as solutions, all of them gave a set of dots in the resulting image.
I tried the above mentioned codes in the link with this image that I found here.
A dotted line was an output for all three code snippets in the link above.
For example, I ran the first code like this:
I = imread('berries_copy.png');
grayImage=rgb2gray(I);
img =false(size(grayImage,1), size(grayImage,2));
I wrote the above piece of code just to get a black image for the following operations:
x = [500 470]; % x coordinates
y = [300 310]; % y coordinates
nPoints = max(abs(diff(x)), abs(diff(y)))+1; % Number of points in line
rIndex = round(linspace(y(1), y(2), nPoints)); % Row indices
cIndex = round(linspace(x(1), x(2), nPoints)); % Column indices
index = sub2ind(size(img), rIndex, cIndex); % Linear indices
img(index) = 255; % Set the line points to white
imshow(img); % Display the image
This is the resulting image for the above code as well as the other two, which as you can see, is just a few points on a black background which isn't the desired output.
I changed the code and used the "plot" function for the same to get this output which is what I want. Is there anyway I can change the dotted output into a solid line?
Or if could anyone suggest a simple function or a method that would draw a line from A1 to A2 and would actually make a change in the input image, I'd be grateful. (I really hope this is just me being a novice rather than Matlab not having a simple function to draw a line in an image.)
P.S. I don't have the Computer Vision toolbox and if possible, I'd like to find a solution that doesn't involve it.
Your first problem is that you are creating a blank image the same size as the image you load with this line:
img =false(size(grayImage,1), size(grayImage,2));
When you add the line to it, you get a black image with a white line on it, as expected.
Your second problem is that you are trying to apply a solution for grayscale intensity images to an RGB (Truecolor) image, which requires you to modify the data at the given indices for all three color planes (red, green, and blue). Here's how you can modify the grayscale solution from my other answer:
img = imread('berries_copy.png'); % Load image
[R, C, D] = size(img); % Get dimension sizes, D should be 3
x = [500 470]; % x coordinates
y = [300 310]; % y coordinates
nPoints = max(abs(diff(x)), abs(diff(y)))+1; % Number of points in line
rIndex = round(linspace(y(1), y(2), nPoints)); % Row indices
cIndex = round(linspace(x(1), x(2), nPoints)); % Column indices
index = sub2ind([R C], rIndex, cIndex); % Linear indices
img(index) = 255; % Modify red plane
img(index+R*C) = 255; % Modify green plane
img(index+2*R*C) = 255; % Modify blue plane
imshow(img); % Display image
imwrite(img, 'berries_line.png'); % Save image, if desired
And the resulting image (note the white line above the berry in the bottom right corner):
You can use the Bresenham Algorithm. Of course it has been implemented and you can find it here: Bresenham optimized for Matlab. This algorithm selects the pixels approximating a line.
A simple example, using your variable name could be:
I = rgb2gray(imread('peppers.png'));
A1 = [1 1];
A2 = [40 40];
[x y] = bresenham(A1(1),A1(2),A2(1),A2(2));
ind = sub2ind(size(I),x,y);
I(ind) = 255;
imshow(I)
You can use imshow to display a image and then use plot to plot lines and save the figure. Check the below code:
I = imread('peppers.png') ;
imshow(I)
hold on
[m,n,p] = size(I) ;
%% Get random points A1, A2,..A10
N = 9 ;
x = (n-1)*rand(1,N)+1 ;
y = (m-1)*rand(1,N)+1 ;
P = [x; y]; % coordinates / points
c = mean(P,2); % mean/ central point
d = P-c ; % vectors connecting the central point and the given points
th = atan2(d(2,:),d(1,:)); % angle above x axis
[th, idx] = sort(th); % sorting the angles
P = P(:,idx); % sorting the given points
P = [P P(:,1)]; % add the first at the end to close the polygon
plot( P(1,:), P(2,:), 'k');
saveas(gcf,'image.png')

Cannot create a histogram data by reading an Image file

I am trying to create a histogram data by reading an Image file:
>> img = imread('Flowers.jpg');
>> g = img(:,:,2);
>> bins = 0:1:255;
>> H = hist(g(:), bins);
?? Error using ==> full
Function 'full' is not defined for values of class 'uint8'.
Error in ==> C:\MATLAB\toolbox\matlab\datafun\hist.m
On line 66 ==> xx = full(real(xx)); y = full(real(y)); % For compatibility
>> version
ans =
6.5.0.180913a (R13)
>>
I am not sure why I am receiving this error?
If you have the Image Processing toolbox, I recommend you use imhist instead. This will handle uint8 images natively, without having to do any conversion, and works on binary and greyscale images.
Similarly to hist, you can either call it without outputs to just get the image directly, or get the outputs and plot the result yourself. Unlike hist, you can only give it a number of bins (for greyscale, this defaults to 256), not a vector.
img = imread('Flowers.jpg');
g = img(:,:,2);
[counts, x] = imhist(g);
stem(x,counts); % or bar, or whatever you prefer
The output x here will be the same as your bins.

How to multiply binary image and rgb image in matlab?

I have a binary image which is the segmented form of another color image .
As you know , a binary image is 2-d but an rgb image is 3-d , how can i multiply them together ?
i tried this code which resulted in a strange pic
function skinCrop(bwSkin,colorSkin)
for i = 1:size(colorSkin,1)
for j = 1:size(colorSkin,1)
if bwSkin(i,j) == 0
colorSkin(i,j,:) = 0;
end
end
end
imshow(colorSkin);
end
The original image was
The resulting image was :
I expected it to be a hand against a dark background , so why do the right part appear that way ?
You should avoid loops when not needed in matlab:
mask = cat(3,bwSkin,bwSkin,bwSkin);
output = mask.*colorSkin;
You might have to change the types in order for the multiplication to succeed:
output = uint8(mask).*colorSkin;
Or:
output = double(mask).*colorSkin;
You are using the wrong dimension length for your second dimension:
for j = 1:size(colorSkin,1)
should be
for j = 1:size(colorSkin,2)
A more efficient way to do the multiplication is
function mult = skinCrop( bwSkin, colorSkin )
%
% multiplying 3D color image with 2D mask
%
mult = nsxfun( #times, bwSkin, colorSkin );
% show the result
imshow( mult ); title('skin cropped image');
As #zenopy noted, you might need to cast your variable to double type.

Image processing using MATLAB, matrices

I'm currently working with MATLAB to do some image processing. I've been set a task to basically recreate the convolution function for applying filters. I managed to get the code working okay and everything seemed to be fine.
The next part was for me to do the following..
Write your own m-function for unsharp masking of a given image to produce a new output image.
Your function should apply the following steps:
Apply smoothing to produce a blurred version of the original image,
Subtract the blurred image from the original image to produce an edge image,
Add the edge image to the original image to produce a sharpened image.
Again I've got code mocked up to do this but I run into a few problems. When carrying out the convolution, my image is cropped down by one pixel, this means when I go to carry out the subtraction for the unsharpening the images are not the same size and the subtraction cannot take place.
To overcome this I want to create a blank matrix in the convolution function that is the same size as the image being inputted, the new image will then go on top of this matrix so in affect the new image has a one pixel border around it to make it to its original size. When I try and implement this, all I get as an output is the blank matrix I just created. Why is this happening and if so would you be able to help me fix it?
My code is as follows.
Convolution
function [ imgout ] = convolution( img, filter )
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
[height, width] = size(img); % height, width: number of im rows, etc.
[filter_height, filter_width] = size(filter);
for height_bound = 1:height - filter_height + 1; % Loop over output elements
for width_bound = 1:width - filter_width + 1;
imgout = zeros(height_bound, width_bound); % Makes an empty matrix the correct size of the image.
sum = 0;
for fh = 1:filter_height % Loop over mask elements
for fw = 1:filter_width
sum = sum + img(height_bound - fh + filter_height, width_bound - fw + filter_width) * filter(fh, fw);
end
end
imgout(height_bound, width_bound) = sum; % Store the result
end
end
imshow(imgout)
end
Unsharpen
function sharpen_image = img_sharpen(img)
blur_image = medfilt2(img);
convolution(img, filter);
edge_image = img - blur_image;
sharpen_image = img + edge_image;
end
Yes. Concatenation, e.g.:
A = [1 2 3; 4 5 6]; % Matrix
B = [7; 8]; % Column vector
C = [A B]; % Concatenate

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.