to get last 20 columns of an image :Matlab - matlab

i have an image IMG ,i want to get its last (20) colums only.
i-e the image is of size 500x500 and i want the colums starting from 480 to 500 ,number of rows remain same.

You can put some basic math and the end keyword in your indexing. So you would have
smallerImage = rawImage(:, (end-20+1):end);
As a colormapped (NxMx1) example
load mandrill; %A colormapped (2d) Matlab demo image in the X variable
figure;
subplot(121)
image(X)
colormap(map)
title('Full picture')
subplot(122)
smallX = X( : , (end-20+1):end ); %This is the subsetting operation for a 2D image
image(smallX)
colormap(map)
title('Rightmost 20 columns')
An RGB example (NxMx3)
imdata = imread('ngc6543a.jpg');
figure;
subplot(121)
image(imdata )
colormap(map)
title('Full picture')
subplot(122)
smallImData = imdata ( : , (end-20+1):end , : ); %This is the subsetting operation for an RGB image, note 3rd dimension colon
image(smallImData )
colormap(map)
title('Rightmost 20 columns')

Try this:
cutImg = img(startrow:endrow,startcol:endcol);
Taken from:
Matlab Central

If you want to take the last n columns, use:
A(:,end-n+1:end)
For the first n columns use:
A(:,1:n)

Related

Saving an image after using range display

I am using kmeans clustering to segment an image. My function returns values between 1-3 with the same size as the input image, then I am using imshow(L, []); to display the image but I cannot find a way which would save the image exactly the same as displayed on the screen
You can use mat2gray to map the values in your matrix L to values between 0 (black) and 1 (white), similar as what imshow(L, []) does. Then use imwrite to save the image.
L = 1 + (3-1).*rand(500); % 500-by-500 image with values between 1 and 3
figure(1); clf;
imshow(L, [])
Img = mat2gray(L);
figure(2); clf;
imshow(Img)
imwrite(Img, 'yourimage.png')

Speeding up Octave / Matlab plot

Gnoivce and Hartmut helped a lot with this code but it takes a while to run.
The CData property in the bar command doesn't seem to be implemented in the Octave 4.0-4.2.1 version which I'm using. The work around for this was to plot all the single bars individually and set an individual color for each individual bar. People helped me out and got me this far but it takes 5 minutes for the plot to show does anyone know a way of speeding this up?
The following code runs:
marbles.jpg image file used below:
clear all,clf reset,tic,clc
rgbImage = imread('/tmp/marbles.jpg');
hsvImage = rgb2hsv(rgbImage); % Convert the image to HSV space
hPlane = 360.*hsvImage(:, :, 1); % Get the hue plane scaled from 0 to 360
binEdges = 0:360; %# Edges of histogram bins
N = histc(hPlane(:),binEdges); %# Bin the pixel hues from above
C = colormap(hsv(360)); %# create an HSV color map with 360 points
stepsize = 1; % stepsize 1 runs for a while...
for n=binEdges(2:stepsize:end) %# Plot the histogram, one bar each
if (n==1), hold on, end
h=bar(n,N(n));
set(h,'FaceColor',C(n,:)); %# set the bar color individually
end
axis([0 360 0 max(N)]); %# Change the axes limits
set(gca,'Color','k'); %# Change the axes background color
set(gcf,'Pos',[50 400 560 200]); %# Change the figure size
xlabel('HSV hue (in degrees)'); %# Add an x label
ylabel('Bin counts'); %# Add a y label
fprintf('\nfinally Done-elapsed time -%4.4fsec- or -%4.4fmins- or -%4.4fhours-\n',toc,toc/60,toc/3600);
Plot created after 5 mins:
To see original question original question
I'm guessing the loop is the bottleneck in your code that is taking so long? You could remove the loop and create the plot with one call to bar, then call set to modify the hggroup object and its child patch object:
h = bar(binEdges(1:end-1), N(1:end-1), 'histc'); % hggroup object
set(h, 'FaceColor', 'flat', 'EdgeColor', 'none');
hPatch = get(h, 'Children'); % patch object
set(hPatch, 'CData', 1:360, 'CDataMapping', 'direct');
Repeating your code with this fix renders right away for me in Octave 4.0.3:
As I suggested in a comment, I would use image (takes 0.12s on my system for your image).
EDIT: more comments, fix little bug, allow to create bins with stepsize > 1
img_fn = "17S9PUK.jpg";
if (! exist (img_fn, "file"))
disp ("downloading image from imgur.com...");
fflush (stdout);
urlwrite ("http://i.imgur.com/17S9PUK.jpg", "17S9PUK.jpg");
endif
rgbImage = imread (img_fn);
## for debugging so the matrixes fit on screen
if (0)
pkg load image
rgbImage = imresize (rgbImage, [6 8]);
endif
hsvImage = rgb2hsv(rgbImage);
hPlane = 360 .* hsvImage(:, :, 1);
## create bins, I've choosen 2 step to "smooth" the result
binEdges = 1:2:360;
N = histc (hPlane(:), binEdges)';
cm = permute (hsv (numel (binEdges)), [3 1 2]);
## Create an image with x = hue
img = repmat (cm, max(N), 1);
## Create binary mask which is used to black "img" dependent on N
sp = sparse (N(N > 0), (1:360)(N > 0), true, max(N), numel (binEdges));
mask = full (cumsum (flipud (sp)));
## extend mask in depth to suppress RGB
mask = repmat (mask, [1 1 3]);
## use inverted mask to "black out" pixels < N
img(logical (1 - flipud (mask))) = 0;
## show image
image (binEdges, 1:max(N), img)
set (gca, "ydir", "normal");
xlabel('HSV hue (in degrees)');
ylabel('Bin counts');
## print it for stackoverflow
print ("out.png")
Same as above but with bin width 1 (Elapsed time is 0.167423 seconds.)
binEdges = 1:360;

MATLAB Auto Crop

I am trying to automatically crop the image below to a bounding box. The background will always be the same colour. I have tried the answers at
Find the edges of image and crop it in MATLAB
and various applications and examples on Mathworks' file exchange but I get stuck at getting a proper boundingbox.
I was thinking to convert the image to black and white, converting it to binary and removing everything that's closer to white than black, but I'm not sure how to go about it.
Here's a nice way
img = im2double(imread('http://i.stack.imgur.com/ZuiEt.jpg')); % read image and convert it to double in range [0..1]
b = sum( (1-img).^2, 3 ); % check how far each pixel from "white"
% display
figure; imshow( b > .5 ); title('non background pixels');
% use regionprops to get the bounding box
st = regionprops( double( b > .5 ), 'BoundingBox' ); % convert to double to avoid bwlabel of logical input
rect = st.BoundingBox; % get the bounding box
% display
figure; imshow( img );
hold on; rectangle('Position', rect );
Following Jak's request, here's the second line explained
after converting img to double type (using im2double), the image is stored in memory as h-by-w-by-3 matrix of type double. Each pixel has 3 values between 0 and 1 (not 255!), representing its RGB values 0 being dark and 1 being bright.
Thus (1-img).^2 checks, for each pixel and each channel (RGB) how far it is from 1 - bright. The darker the pixel - the larger this distance.
Next, we sum the distance per channel to a single value per pixel using sum( . ,3 ) command leaving us with h-by-w 2D matrix of distances of each pixels from white.
Finally, assuming background is bright white we select all pixels that are significantly far from birght b > .5. This threshold is not perfect, but it captures well the boundary of the object.
Following the answer of Shai, I present a way to circumvent regionprops (image processing toolbox) just based on find on the black-white image.
% load
img = im2double(imread('http://i.stack.imgur.com/ZuiEt.jpg'));
% black-white image by threshold on check how far each pixel from "white"
bw = sum((1-img).^2, 3) > .5;
% show bw image
figure; imshow(bw); title('bw image');
% get bounding box (first row, first column, number rows, number columns)
[row, col] = find(bw);
bounding_box = [min(row), min(col), max(row) - min(row) + 1, max(col) - min(col) + 1];
% display with rectangle
rect = bounding_box([2,1,4,3]); % rectangle wants x,y,w,h we have rows, columns, ... need to convert
figure; imshow(img); hold on; rectangle('Position', rect);
to crop an image
first create boundry box where you want to crop.
crp = imcrop(original_image_name,boundry_box);
I have done this in my assignment. This really works!!!!!!

How to convert RGB images to grayscale in matlab without using rgb2gray

I'm currently using code:
i = imread('/usr/share/icons/matlab.png');
for k=1:1:m
for l=1:1:n
%a(k,l)=m*n;
a(k,l) = (.299*i(k,l,1))+(.587*i(k,l,2))+(.114*i(k,l,3));
end
end
imshow(a);
It shows only a white screen. Also the newly generated dimensions are n x m x 3 whereas it should be only m x n x 1.
If I use mat2gray it display the image like this
Since the image is a PNG, imread() is returning an integer image, with intensity values in the range [0 255] or equivalent, depending on the original bit depth. The conversion formula makes a a double image, which is expected to have intensities in the range [0 1]. Since all the pixel values in a are probably much greater than 1, they get clipped to 1 (white) by imshow().
The best option is to explicitly convert the image format before you start - this will take care of scaling things correctly:
i = imread('/usr/share/icons/matlab.png');
i = im2double(i);
a = .299*i(:,:,1) + .587*i(:,:,2) + .114*i(:,:,3); % no need for loops
imshow(a);
input=imread('test.jpg');
subplot(1,2,1), imshow(input), title('RGB Scale image');
[x,y,~] = size(input);
for i = 1:1:x
for j = 1:1:y
output(i,j) = 0.40*input(i,j,1) + 0.50*input(i,j,2) + 0.30*input(i,j,3);
end
end
subplot(1,2,2), imshow(output), title('Gray Scale image');

Difficulty with my self built histogram in MatLab

I am trying to implement a simple function that its the same with the default hist() by MatLab.
We have two same images with different brightness and we have to convert them to grayscale and then use the default function of MatLab hist() to get the histograms (so far so good!).
Then we have to implement the function hist my_hist() , and when i am trying to count the frequency of the intensity the results are not the same.
It seems that it sums-up the frequency of 254 & 255 to 254 and 255 is zero!I dont know what the problem is, any help would be appreciated.
here is the code for the command line:
%Read the images and convert them from rgb to grayscale
i=imread('pic1.jpg');
j=rgb2gray(i);
x=imread('pic2.jpg');
y=rgb2gray(x);
%Display the two images
figure
imshow(j)
figure
imshow(y)
%Display the histogram of the two images
[a,b] = hist(j(:),0:1:255);
figure
plot(b,a)
[c,d]=hist(y(:),0:1:255);
figure
plot(d,c)
%Call of the built-in function
my_hist('pic1.jpg','pic2.jpg')
And here is the code of the self built function:
function []= my_hist( x,y)
%Read the images and convert them from rgb to grayscale
pic1=imread(x);
i=rgb2gray(pic1);
pic2=imread(y);
j=rgb2gray(pic2);
%Initialize two vectors to be the axis for histogram
plotx=0:255;
ploty=zeros(1,256);
%Take the dimensions of the first image pic1
[m,n] = size(i);
%With 2 loops we go through the matrix of the image and count how many
%pixels have the same intensity
for k=1:m
for l=1:n
num=i(k,l)+1;
ploty(num)=ploty(num)+1;
end
end
%Display the histogram for the first image pic1
figure
plot(plotx,ploty);
%Initialize two vectors to be the axis for histogram
plotx2=0:255;
ploty2=zeros(1,256);
%Take the dimensions of the second image pic2
[m2,n2] = size(j);
%With 2 loops we go through the matrix of the image and count how many
%pixels have the same intensity
for o=1:m2
for p=1:n2
num2=j(o,p)+1;
ploty2(num2)=ploty2(num2)+1;
end
end
%Display the histogram for the second image pic2
figure
plot(plotx2,ploty2);
end
And here are the images pic1 and pic2.
This is a problem due to your image being of integer type uint8 which can only range from 0-255:
>> a= uint8(255)
a =
255
>> a=a+1
a =
255
Convert your data to say type uint16 with
j = uint16(j);
y = uint16(y);
and your problem should be gone:
>> a=uint16(a)
a =
255
>> a=a+1
a =
256