Cannot create a histogram data by reading an Image file - matlab

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.

Related

Geometric mean filter in 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)')

How to use histogram handler in matlab

I am trying to accumulate several histogram outputs into a cell array, but it seems that it's impossible to plot or do anything after the first execution of a single histogram command, because it's only an handle to deleted Histogram.
>> x = randn(10000,1);
>> h = histogram(x);
>> h
h =
handle to deleted Histogram
>> whos h
Name Size Bytes Class Attributes
h 1x1 104 matlab.graphics.chart.primitive.Histogram
I am aware that it's possible to write the histogram upon its calculation to a file, How do I save histogram to file in matlab?. Though I am trying to accumulate it into a cell array for later analysis.
This is due to the BeingDeleted property of histogram which can be read-only so you cannot change it.
However, you can copy the properties in another struct for later use. Modify your code as follows:
x = randn(10000,1);
h = histogram(x);
prop = properties(h);
for i = 1:length(prop)
newh.(prop{i}) = h.(prop{i});
end
Now all the properties of h are stored in newh which will remain there even after you close the histogram figure.
As has been suggested in comments, the proper way to do this, if all you need is the histogram values, is to use histcounts:
x = randn(10000,1);
[N,edges] = histcounts(x);
this way you can collect all bins x and y values (edges and N, respectively), and plot them later with bar. Here is a demonstration with a comparison between the results:
subplot 121
h = histogram(x)
title('histogram')
subplot 122
b = bar(edges(1:end-1),N,'FaceColor',lines(1),...
'FaceAlpha',0.6)
title('bar')
If it is important to show the histogram in the exact same way that histogarm does, you can set some more properties of bar.

How to pass Imagesc frame into Matlab imwrite and imread?

I take a gray-colormap frame of imagesc, try to gray2ind-ind2rgb for imwrite and then read it again by imread but I get the error which indicates that the dimensions do not match.
Assignment has more non-singleton rhs dimensions than non-singleton subscripts
Error in ind2rgb (line 34)
rout(:,:,1) = r;
Error in test_imagesc_output_imwrite (line 14)
Crgb = ind2rgb(Cind, parula(256)); % https://stackoverflow.com/a/39968435/54964
Code where I am uncertain how to pass 1-gray(1024) colormap details to gray2ind correctly; I think gray2ind(I,256) can lose pieces of information; also, ind2rgb(Cind, parula(256) is not correct but I cannot use there 1-gray(1024) directly
clear all; close all; clc;
x = [5 8];
y = [3 6];
C = [0 2 4 6; 8 10 12 14; 16 18 20 22];
f=figure;
hax=axes(f);
imagesc(hax, x,y,C) % I could not use here I=imagesc and then I.CData for some reason
colormap(hax, 1-gray(1024));
I=getframe(hax);
I=I.cdata;
assert(isa(I, 'uint8'), sprintf('I is not uint8 but %s', class(I)));
Cind = gray2ind(I, 256);
% TODO here something
Crgb = ind2rgb(Cind, parula(256)); % https://stackoverflow.com/a/39968435/54964
imwrite(Crgb, '/home/masi/Images/1.png');
I=imread('/home/masi/Images/1.png');
assert(isa(I, 'uint8'), sprintf('I is not uint8 but %s', class(I)));
f2=figure;
hax=axes(f2);
imagesc(hax2, I);
Fig. 1 Imagsc gray image which is getframe and tried to be stored by imwrite and read by imread
Matlab: 2016a
OS: Debian 8.5 64 bit
Hardware: Asus Zenbook UX303UA
Motivation: I am getting artefact in export_fig as described here but also now observing phase shifts from 1-gray to gray when saving [I,alpha]=export_fig(...) so trying with Matlab imwrite/imread
Your variabel I is RGB data (M x N x 3) so when you pass it to gray2ind you are getting back an M x N x 3 matrix of indices. ind2rgb accepts a 2D array of indices and not the 3D array that you're passing it.
I'm not quite sure what you expect, but you could first convert I to a true grayscale image first using rgb2gray
I = getframe(hax);
I = rgb2gray(I.cdata);
Cind = gray2ind(I, 256);
Crgb = ind2rgb(Cind, parula(256));
Or you could skip all of this and just set the colormap of your figure to parula and pass I.cdata directly to imwrite
imagesc(C, 'Parent', hax);
% Use an inverted parula colormap which seems to be what you're trying to do
colormap(flipud(parula(256)));
I = getframe(hax);
imwrite(I.cdata, '1.png')

error while drawing several x-marks on a binary image in matlab

I am trying to draw several x-marks on a binary image to some co-ordinates.
My output should look like this
To do this i have written some codes below
clear all;
% Here four co-ordinates are provided as an example. In my main code the co- ordinates will be hundred or thousands
position{1}.x = 10;
position{1}.y = 10;
position{2}.x = 20;
position{2}.y = 20;
position{3}.x = 30;
position{3}.y = 30;
position{4}.x = 40;
position{4}.y = 40;
% Read image as binary
image = imread('test34.jpg');
figure('name','Main Image'),imshow(image);
gray_image=rgb2gray(image);
level = graythresh(gray_image);
binary_image = im2bw(image,level);
% Define color of the x-marker and initializing shapes which i want to draw
red = uint8([255 0 0]);
markerInserter = vision.MarkerInserter('Shape','X-mark','BorderColor','Custom','CustomBorderColor',red);
i = 1;
% The loop will continue to the number of co-ordinates which will never be predefined in my main code
while i<=numel(position)
% Converting binary to RGB for only once.
if i == 1
rgb = repmat(binary_image, [1, 1, 3]);
else
rgb = repmat(binary_image, [1, 1, 1]);
end
% Position where x-marks will be drawn
Pts = int32([position{i}.x position{i}.y]);
% Draw x-marks
binary_image = step(markerInserter, rgb, Pts);
i = i+1;
end
figure('name','binary_image'),imshow(binary_image);
But i am getting these errors
Error using images.internal.imageDisplayValidateParams>validateCData
(line 119)
If input is logical (binary), it must be two-dimensional.
Error in images.internal.imageDisplayValidateParams (line 27)
common_args.CData = validateCData(common_args.CData,image_type);
Error in images.internal.imageDisplayParseInputs (line 78)
common_args = images.internal.imageDisplayValidateParams(common_args);
Error in imshow (line 227)
[common_args,specific_args] = ...
Error in test2 (line 39)
figure('name','binary_image'),imshow(binary_image);
I have tried some examples but they are experimented on RGB image while i need it on binary image and that's where i am getting errors.
Why i am getting these errors and what will be the solution?
Please provide explanation with proper code.
You code seems a bit complicated (to me) for what it is intended. Here is a simple example demonstrating how to draw red crosses using scatter on a binary image. As you see, the image in itself is binary and the markers are in color, so the 'net' image is no longer binary... Also, there is no need to convert your RGB image to graylevels before applying im2bw.
And don't forget to use hold on to avoid discarding the image when adding the markers!
Here is the code with comments:
clear
clc
close all
%// Read image
MyImage = imread('peppers.png');
%// Convert to binary. No need to use rgb2gray.
MyBWImage = im2bw(MyImage(:,:,2));
%// Define some x- and y positions for markers
xpositions = linspace(10,300,40);
ypositions = linspace(20,500,40);
imshow(MyBWImage)
%// IMPORTANT!!
hold on
%// Draw markers
scatter(xpositions.',ypositions.',80,'r','x')
With output:
Is this what you meant?

Why isn't this inverse Fourier transform giving the correct results?

I want to invert the Fourier transform of an image in MATLAB, but the result is not the original image (as it should be). There is obviously some implementation detail that I don't know about that's causing the issue. Here's the code:
img = imread('img.jpg');
fft = fft2(img);
inv = ifft2(fft);
imshow(inv);
Since fft2 and ifft2 both perform calculations in either double or single precision, your image data (which is likely of type uint8) gets converted to type double first before being processed by fft2. You will therefore have to convert your output image inv back to an unsigned 8-bit integer using the function uint8 to recover the original image:
>> img = imread('peppers.png'); % Load a sample image
>> fft = fft2(img); % Get the Fourier transform
>> inv = ifft2(fft); % Get the inverse Fourier transform
>> inv = uint8(inv); % Convert to uint8
>> imshow(inv); % Show the image
>> isequal(img, inv) % Test if inv matches the original image img
ans =
1 % It does!
NOTE: As an additional tip, I would avoid naming your variables fft and inv since functions with those names already exist in MATLAB.
Also if you are trying to do FFT on color (24-bit) image - note that imread() will return M x N x 3 array. So you should perform FFT on each R/G/B channel separately.
See this for detail.