how to get some portion from an image in matlab? - matlab

i have an image I of size 512x256.
i want to get some portion like a slice from this image I.
like i want I1 of size 512x50 .

To take a slice that includes the first 50 columns, and all rows, do the following
sliceOfImage = originalImage(:,1:50)
To take a slice that includes columns 100 to 149, call
sliceOfImage = originalImage(:,100:149)
etc.

x = [1:50]; % define the scope of x-axis (the "columns") for the portion of the image
y = [1:512]; %define the scope of y-axis (the "rows") for the portion of the image
I1 = I(x,y,:); % Create I1, the desired portion of the image. Assuming the original image is of RGB and you need to access all 3 colors.

Related

How can I merge multiple images into one and save it on matlab?

I need to merge multiple bitmap of same sizes into one image.That image is basically rotated in different angles and needs to be merged into one whole image. I have tried multiple methods but I come with many issues as I am not able to save that image.
I have tried multiple codes but I actually cannot make sense out of it. What I want to achieve is transparent overlay (not sure) that superimposes two images and you can actually see both one image
figure1 = figure;
ax1 = axes('Parent',figure1);
ax2 = axes('Parent',figure1);
set(ax1,'Visible','off');
set(ax2,'Visible','off');
[a,map,alpha] = imread('E:\training data\0.bmp');
I = imshow(a,'Parent',ax2);
set(I,'AlphaData',alpha);
F = imshow('E:\training data\200.bmp','Parent',ax1);
I just want to superimpose multiple images.
This is my data set:
This is what I want to achieve, i want to add all of the rotated images and achieved into one
This is what I get sadly, I have tried everything
The following does kind of what you want. First load the image, then divide it into 6 equal blocks, and add these. To add the pixel values, I first converted the image to doubles, since uint8 only can go up to pixel values of 255. This would mean that you will just see a large bright spot in the image because you are clipping.
Then add all the blocks. You will see in the output, that the car is not always perfect in the center of the block, so depending on what you are trying to achieve you may want to align the blocks using something like xcorr2.
% load image
A = imread('S82CW.jpg');
fig = figure(1); clf
image(A);
% convert A to double and divide in blocks.
A = double(A);
[img_h, img_w, ~] = size(A);
block_h = img_h/2;
block_w = img_w/3;
% split image in blocks
Asplit = mat2cell(A, repelem(block_h,2), repelem(block_w,3), 3);
% check if splitting makes sense
figure(2); clf
for k = 1:numel(Asplit)
subplot(3,2,k)
image(uint8(Asplit{k}))
end
% superimpose all blocks,
A_super = zeros(size(Asplit{1,1}),'like',Asplit{1,1} ); % init array, make sure same datatype
for k = 1:numel(Asplit)
A_super = A_super + Asplit{k};
end
% divide by max value in A and multiply by 255 to make pixel
% values fit in uint8 (0-255)
A_super_unit8 = uint8(A_super/max(A_super,[],'all')*255);
figure(3); clf;
image(A_super_unit8)

How can I traverse through pixels?

Suppose, I have the following image in my hand.
I have marked some pixels of the image as follows,
Now, I have obtained the pixel mask,
How can I traverse through only those pixels that are in that mask?
Given a binary mask, mask, where you want to iterate over all the true pixels in mask, you have at least two options that are both better than the double for loop example.
1) Logical indexing.
I(mask) = 255;
2) Use find.
linearIdx = find(mask);
I(linearIdx) = 255;
The original question:
How can I save only those pixels which I am interested in?
...
Question: Now, in the Step#2, I want to save those pixels in a data-structure (or, whatever) d so that I can apply another function f2(I, d, p,q,r) which does something on that image on the basis of those pixels d.
Create a binary mask
Try using a logical mask of the image to keep track of the pixels of interest.
I'll make up a random image for example here:
randImg = rand(64,64,3);
imgMask = false(size(randImg(:,:,1)));
imgMask(:,[1:4:end]) = true; % take every four columns This would be your d.
% Show what we are talking about
maskImg = zeros(size(randImg));
imgMaskForRGB = repmat(imgMask,1,1,3);
maskImg(imgMaskForRGB) = randImg(imgMaskForRGB);
figure('name','Psychadelic');
subplot(2,1,1);
imagesc(randImg);
title('Random image');
subplot(2,1,2);
imagesc(maskImg);
title('Masked pixels of interest');
Here's what it looks like:
It will be up to you to determine how to store and use the image mask (d in your case) as I am not sure how your functions are written. Hopefully this example will give you an understanding of how it can be done though.
EDIT
You added a second question since I posted:
But, now the problem is, how am I going to traverse through those pixels in K?
Vectrorization
To set all pixels to white:
randImg(imgMaskForRGB) = 255;
In my example, I accessed all of the pixels of interest at the same time with my mask in a vectorized fashion.
I translated my 2D mask into a 3D mask, in order to grab the RGB values of each pixel. That was this code:
maskImg = zeros(size(randImg));
imgMaskForRGB = repmat(imgMask,1,1,3);
Then to access all of these pixels in the image of interest, I used this call:
randImg(imgMaskForRGB)
These are your pixels of interest. If you want to divide these values in 1/2 you could do something like this:
randImg(imgMaskForRGB) = randImg(imgMaskForRGB)/2;
Loops
If you really want to traverse, one pixel at a time, you can always use a double for loop:
for r=1:size(randImg,1)
for c=1:size(randImg,2)
if(imgMask(r,c)) % traverse all the pixels
curPixel = randImg(r,c,:); % grab the ones that are flagged
end
end
end
Okay. I have solved this using the answer of #informaton,
I = imread('gray_bear.png');
J = rgb2gray(imread('marked_bear.png'));
mask = I-J;
for r=1:size(I,1)
for c=1:size(I,2)
if(mask(r,c))
I(r,c) = 255;
end
end
end
imshow(I);

Split up a binary image using their white boundaries in MATLAB

I'm trying to read the values in this image into variables using OCR in MATLAB. I'm having trouble doing so, so I tried to split up this image into smaller parts using the white boundary lines then trying to read it, but I dont know how to do this. Any help would be appreciated, thanks.
If the blocks are always delimited by a completely vertical line, you can find where they are by comparing the original image (here transformed from RGB to grayscale to be a single plane) to a matrix that is made of repeats of the first row of the original image only. Since the lines are vertical the intensity of the pixels in the first line will be the same throughout. This generates a binary mask that can be used in conjunction with a quick thresholding to reject those lines that are all black pixels in every row. Then invert this mask and use regionprops to locate the bounding box of each region. Then you can pull these out and do what you like.
If the lines dividing the blocks of text are not always vertical or constant intensity throughout then there's a bit more work that needs to be done to locate the dividing lines, but nothing that's impossible. Some example data would be good to have in that case, though.
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
imshow(img);
imgGray = rgb2gray(img);
imgMatch = imgGray == repmat(imgGray(1,:), size(imgGray, 1), 1);
whiteLines = imgMatch & (imgGray > 0);
boxes = regionprops(~whiteLines, 'BoundingBox');
for k = 1:6
subplot(3,2,k)
boxHere = round(boxes(k).BoundingBox);
imshow(img(boxHere(2):(boxHere(2)+boxHere(4)-1), boxHere(1):(boxHere(1)+boxHere(3)-1), :));
end
You can sum along the columns of a binary image corresponding to that input image and find peaks from the sum values. This is precisely achieved in the code here -
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
BW = im2bw(img,0.1); %// convert to a binary image with a low threshold
peak_sum_max = 30; %// max of sum of cols to act as threshold to decide as peak
peaks_min_width = 10; %// min distance between peaks i.e. min width of each part
idx = find( sum(BW,1)>=peak_sum_max );
split_idx = [1 idx( [true diff(idx)>peaks_min_width ] )];
split_imgs = arrayfun(#(x) img(:,split_idx(x):split_idx(x+1)),...
1:numel(split_idx)-1,'Uni',0);
%// Display split images
for iter = 1:numel(split_imgs)
figure,imshow(split_imgs{iter})
end
Please note that the final output split_imgs is a cell array with each cell holding image data for each split image.
If you would like to have the split images directly without the need for messing with cell arrays, after you have split_idx, you can do this -
%// Get and display split images
for iter = 1:numel(split_idx)-1
split_img = img(:,split_idx(iter):split_idx(iter+1));
figure,imshow(split_img)
end
There is now a built-in ocr function in the Computer Vision System Toolbox.

Using roifilt2 on an image in Matlab

I am trying to sum up all the values in a 400 x 640 image that are within a masked region using the roifilt2 function. I created a mask using roipoly and it is also stored as a 400 x 640 matrix with 0's in the cells I am uninterested in and 1's in the cells that I wish to sum up.
I was wondering how you would go about this, I have looked at the mathworks page for roifilt2 but I don't understand how to pass the sum function into this properly. This is what I'm trying:
fh = #(I)(sum(I,2));
I2 = roifilt2(I, mask, fh);
where I is my image and mask is my mask. I also keep getting the following error, even though my I and my mask are DEFINITELY the same size:
Error using roifilt2 (line 79)
The filtered image is not the same size as the original image.
Any help would be appreciated, Thanks!
The problem is that the sum changes the size of the output image, try by clearing all the values outside of the region then summing up
% Define the function you want to use as a filter.
% This function, named f, passes the input image x to the imsharpen
% function and specifies the strength of the sharpening effect
% by using the 'Amount' name-value pair argument.
% f simply puts the values to 0
f = #(x)x-x;
% Filter the ROI using the roifilt2 function and specifying the image, mask, and filtering function.
% This filter clears all the values which are not in the region of interest
interest_region = roifilt2(img, ~mask, f);
So the final sum of the values in your region will be:
img_sum = sum(interest_region,'all');
Anyway, as Raab70 wrote, you could multiply by the mask to obtain the same result without using roifilt2:
img_sum = sum(img.*mask,'all');

Average image (Type error)

I'm trying to write a function in matlab for averaging images (all of the same size and format (.png)). But it's not really working at the moment. The error i get is: "Error using +, Integers can only be combined with integers of the same class, or scalar doubles."
The code is below. The images are all resized to the same size, and have padding applied if the proportions aren't equal (padding is done with an alpha channel, to make the padding transparent). The images are all proper png's, and can be opened in photoshop etc. without errors.
If i understand correctly, you don't have to initialize or declare variables in matlab. Which is probably part of my problem. My normal (processing/java) approach would be to initialize containerAv to be of size (x, y, 3), add all the color values of all images to it, and then divide all values by the number of images. Giving you the average image.
I don't really know how to do this in matlab. What am i doing wrong? How do i rewrite this code so it gets me the rgb average image?
function imageCentroid(imageList, resizeFolder, outputFolder, x, y)
% local variable
centroidImage = zeros([x y 3]);
% loop through all images in the resizeFolder
for i=1:length(imageList)
% get filename and load image
fname = imageList(i).name;
container = imread([resizeFolder fname]);
% add container values to centroidImage
centroidImage = centroidImage + container;
end
% calculate mean image (divide by number of images)
centroidImage = centroidImage / length(imageList);
% save mean image
imwrite(centroidImage, [outputFolder 'centroid.png']);
end
Probably change:
container = imread([resizeFolder fname]);
to
container = im2double(imread([resizeFolder fname]));