Determine the minimum bounding box to capture an object in MATLAB - matlab

I have background subtracted images as input. The idea is to reduce search areas for person detection by using a smaller search area for the HOG algorithm. The output required is a bounding box around the person and the pixel positions of the box corners.
This is the input image:
This is the required output:
This is what I have tried so far:
x=imread('frame 0080.png');
y=im2bw(x);
s=regionprops(y);
imshow(y);
hold on
for i=1:numel(s)
rectangle('Position',s(i).BoundingBox,'edgecolor','y')
end
This was the output I got:

It looks like you have tried what I have suggested. However, you want the bounding box that encapsulates the entire object. This can easily be done by using the BoundingBox property, then calculating each of the four corners of each rectangle. You can then calculate the minimum spanning bounding box that encapsulates all of the rectangles which ultimately encapsulates the entire object.
I do notice that there is a thin white strip at the bottom of your image, and that will mess up the bounding box calculations. As such, I'm going to cut the last 10 rows of the image before we proceed calculating the minimum spanning bounding box. To calculate the minimum spanning bounding box, all you have to do is take all of the corners for all of the rectangles, then calculate the minimum and maximum x co-ordinates and minimum and maximum y co-ordinates. These will correspond to the top left of the minimum spanning bounding box and the bottom right of the minimum spanning bounding box.
When taking a look at the BoundingBox property using regionprops, each bounding box outputs a 4 element vector:
[x y w h]
x,y denote the top left co-ordinate of your bounding box. x would be the column and y would be the row of the top left corner. w,h denote the width and the height of the bounding box. We would use this and compute top left, top right, bottom left and bottom right of every rectangle that is detected. Once you complete this, stack all of these rectangle co-ordinates into a single 2D matrix, then calculate the minimum and maximum x and y co-ordinates. To calculate the rectangle, simply use the minimum x and y co-ordinates as the top left corner, then calculate the width and height by subtracting the maximum and minimum x and y co-ordinates respectively.
Without further ado, here's the code. Note that I want to extract all of the bounding box co-ordinates in a N x 4 matrix where N denotes the number of bounding boxes that are detected. You would have to use reshape to do this correctly:
% //Read in the image from StackOverflow
x=imread('http://i.stack.imgur.com/mRWId.png');
% //Threshold and remove last 10 rows
y=im2bw(x);
y = y(1:end-10,:);
% //Calculate all bounding boxes
s=regionprops(y, 'BoundingBox');
%// Obtain all of the bounding box co-ordinates
bboxCoords = reshape([s.BoundingBox], 4, []).';
% // Calculate top left corner
topLeftCoords = bboxCoords(:,1:2);
% // Calculate top right corner
topRightCoords = [topLeftCoords(:,1) + bboxCoords(:,3) topLeftCoords(:,2)];
% // Calculate bottom left corner
bottomLeftCoords = [topLeftCoords(:,1) topLeftCoords(:,2) + bboxCoords(:,4)];
% // Calculate bottom right corner
bottomRightCoords = [topLeftCoords(:,1) + bboxCoords(:,3) ...
topLeftCoords(:,2) + bboxCoords(:,4)];
% // Calculating the minimum and maximum X and Y values
finalCoords = [topLeftCoords; topRightCoords; bottomLeftCoords; bottomRightCoords];
minX = min(finalCoords(:,1));
maxX = max(finalCoords(:,1));
minY = min(finalCoords(:,2));
maxY = max(finalCoords(:,2));
% Draw the rectangle on the screen
width = (maxX - minX + 1);
height = (maxY - minY + 1);
rect = [minX minY width height];
% // Show the image
imshow(y);
hold on;
rectangle('Position', rect, 'EdgeColor', 'yellow');
This is the image I get:

Related

How do i create a rectangular mask at known angles?

I have created a synthetic image that consists of a circle at the centre of a box with the code below.
%# Create a logical image of a circle with image size specified as follows:
imageSizeY = 400;
imageSizeX = 300;
[ygv, xgv] = meshgrid(1:imageSizeY, 1:imageSizeX);
%# Next create a logical mask for the circle with specified radius and center
centerY = imageSizeY/2;
centerX = imageSizeX/2;
radius = 100;
Img = double( (ygv - centerY).^2 + (xgv - centerX).^2 <= radius.^2 );
%# change image labels from double to numeric
for ii = 1:numel(Img)
if Img(ii) == 0
Img(ii) = 2; %change label from 0 to 2
end
end
%# plot image
RI = imref2d(size(Img),[0 size(Img, 2)],[0 size(Img, 1)]);
figure, imshow(Img, RI, [], 'InitialMagnification','fit');
Now, i need to create a rectangular mask (with label == 3, and row/col dimensions: 1 by imageSizeX) across the image from top to bottom and at known angles with the edges of the circle (see attached figure). Also, how can i make the rectangle thicker than 1 by imageSizeX?. As another option, I would love to try having the rectangle stop at say column 350. Lastly, any ideas how I can improve on the resolution? I mean is it possible to keep the image size the same while increasing/decreasing the resolution.
I have no idea how to go about this. Please i need any help/advice/suggestions that i can get. Many thanks!.
You can use the cos function to find the x coordinate with the correct angle phi.
First notice that the angle between the radius that intersects the vertex of phi has angle with the x-axis given by:
and the x coordinate of that vertex is given by
so the mask simply needs to set that row to 3.
Example:
phi = 45; % Desired angle in degrees
width = 350; % Desired width in pixels
height = 50; % Desired height of bar in pixels
theta = pi-phi*pi/180; % The radius angle
x = centerX + round(radius*cos(theta)); % Find the nearest row
x0 = max(1, x-height); % Find where to start the bar
Img(x0:x,1:width)=3;
The resulting image looks like:
Note that the max function is used to deal with the case where the bar thickness would extend beyond the top of the image.
Regarding resolution, the image resolution is determined by the size of the matrix you create. In your example that is (400,300). If you want higher resolution simply increase those numbers. However, if you would like to link the resolution to a higher DPI (Dots per Inch) so there are more pixels in each physical inch you can use the "Export Setup" window in the figure File menu.
Shown here:

How to rotate a bounding box at any angle in matlab?

I felt confused to crop an image along any angle, i.e. pi/4, how can I make it?
The following example demonstrates how to crop rotated bounding box.
The example doesn't show how to select the bounding box, and the angle (user interface is excluded).
For keeping the example simple, the bounding box parameters are: center, size and angle (instead of 4 corners).
Center is kept in place, when rotating.
Size is the width and height of destination crop area (size after rotation).
In case you need to calculate corners transformation, you can use rotation matrix: https://en.wikipedia.org/wiki/Rotation_matrix
Code sample:
%Bounding box parameters: center, width, height and angle.
%Center is selected, because center is kept the same when rotating.
center_x = 256; %Center column index (applied center is 256.5)
center_y = 192; %Center row index (applied center is 192.5)
width = 300; %Number of columns of destination (cropped) area (even integer)
height = 200; %Number of rows of destination (cropped) area (even integer)
phi = 120; %Rotation angle in degrees
%Read sample image.
I = imread('peppers.png');
%Add center cross, for verifying center is kept.
I(center_y-1:center_y, center_x-30:center_x+30, :) = 255;
I(center_y-30:center_y+30, center_x-1:center_x, :) = 255;
%Rotate the entire input image, dimensions of J will be the same as I.
J = imrotate(I, phi, 'bicubic', 'crop');
%Crop rectangular are with size width by height around center_x, center_y from J.
C = J(center_y-height/2+1:center_y+height/2, center_x-width/2+1:center_x+width/2, :);
%Display result:
figure;imshow(C);
Result:

How can I obtain the bounding box of an object to separate it from the background [duplicate]

I have background subtracted images as input. The idea is to reduce search areas for person detection by using a smaller search area for the HOG algorithm. The output required is a bounding box around the person and the pixel positions of the box corners.
This is the input image:
This is the required output:
This is what I have tried so far:
x=imread('frame 0080.png');
y=im2bw(x);
s=regionprops(y);
imshow(y);
hold on
for i=1:numel(s)
rectangle('Position',s(i).BoundingBox,'edgecolor','y')
end
This was the output I got:
It looks like you have tried what I have suggested. However, you want the bounding box that encapsulates the entire object. This can easily be done by using the BoundingBox property, then calculating each of the four corners of each rectangle. You can then calculate the minimum spanning bounding box that encapsulates all of the rectangles which ultimately encapsulates the entire object.
I do notice that there is a thin white strip at the bottom of your image, and that will mess up the bounding box calculations. As such, I'm going to cut the last 10 rows of the image before we proceed calculating the minimum spanning bounding box. To calculate the minimum spanning bounding box, all you have to do is take all of the corners for all of the rectangles, then calculate the minimum and maximum x co-ordinates and minimum and maximum y co-ordinates. These will correspond to the top left of the minimum spanning bounding box and the bottom right of the minimum spanning bounding box.
When taking a look at the BoundingBox property using regionprops, each bounding box outputs a 4 element vector:
[x y w h]
x,y denote the top left co-ordinate of your bounding box. x would be the column and y would be the row of the top left corner. w,h denote the width and the height of the bounding box. We would use this and compute top left, top right, bottom left and bottom right of every rectangle that is detected. Once you complete this, stack all of these rectangle co-ordinates into a single 2D matrix, then calculate the minimum and maximum x and y co-ordinates. To calculate the rectangle, simply use the minimum x and y co-ordinates as the top left corner, then calculate the width and height by subtracting the maximum and minimum x and y co-ordinates respectively.
Without further ado, here's the code. Note that I want to extract all of the bounding box co-ordinates in a N x 4 matrix where N denotes the number of bounding boxes that are detected. You would have to use reshape to do this correctly:
% //Read in the image from StackOverflow
x=imread('http://i.stack.imgur.com/mRWId.png');
% //Threshold and remove last 10 rows
y=im2bw(x);
y = y(1:end-10,:);
% //Calculate all bounding boxes
s=regionprops(y, 'BoundingBox');
%// Obtain all of the bounding box co-ordinates
bboxCoords = reshape([s.BoundingBox], 4, []).';
% // Calculate top left corner
topLeftCoords = bboxCoords(:,1:2);
% // Calculate top right corner
topRightCoords = [topLeftCoords(:,1) + bboxCoords(:,3) topLeftCoords(:,2)];
% // Calculate bottom left corner
bottomLeftCoords = [topLeftCoords(:,1) topLeftCoords(:,2) + bboxCoords(:,4)];
% // Calculate bottom right corner
bottomRightCoords = [topLeftCoords(:,1) + bboxCoords(:,3) ...
topLeftCoords(:,2) + bboxCoords(:,4)];
% // Calculating the minimum and maximum X and Y values
finalCoords = [topLeftCoords; topRightCoords; bottomLeftCoords; bottomRightCoords];
minX = min(finalCoords(:,1));
maxX = max(finalCoords(:,1));
minY = min(finalCoords(:,2));
maxY = max(finalCoords(:,2));
% Draw the rectangle on the screen
width = (maxX - minX + 1);
height = (maxY - minY + 1);
rect = [minX minY width height];
% // Show the image
imshow(y);
hold on;
rectangle('Position', rect, 'EdgeColor', 'yellow');
This is the image I get:

Finding the area of the black spots in a circle MATLAB

Is it possible to find the area of the black pixelation of an area within a circle? in other words I want to find the number of pixels (the area) of the RGB 0,0,0 (black pixels) within the circle. I do not want the areas of the white pixels (1,1,1) within the circle. I also have a radius of the circle if that helps. Here is the image:
Here is the code:
BW2= H(:,:) <0.45 ;%& V(:,:)<0.1;
aa=strel('disk',5);
closeBW = imclose(BW2,aa);
figure, imshow(closeBW)
imshow(closeBW)
viscircles([MYY1 MYX1], round(MYR2/2))
MYY1,MYX2, and the other values are calculated by my program. How can I find the area of the black pixelation in my circle?
Here is an idea:
1) Calculate the total # of black pixels in your original image (let's call it A).
2) Duplicate that image (let's call it B) and replace all pixels inside the circle with white. To do that, create a binary mask. (see below)
3) Calculate the total # of black pixels in that image (i.e. B).
4) Subtract both values. That should give you the number of black pixels within the circle.
Sample code: I used a dummy image I had on my computer and created a logical mask with the createMask method from imellipse. That seems complicated but in your case since you have the center position and radius of the circle you can create directly your mask like I did or by looking at this question/answer.
Once the mask is created, use find to get the linear indices of the white pixels of the mask (i.e. all of it) to replace the pixels in the circle of your original image with white pixels, which you use to calculate the difference in black pixels.
clc;clear;close all
A = im2bw(imread('TestCircle.png'));
imshow(A)
Center = [160 120];
Radius = 60;
%// In your case:
% Center = [MYY1 MYX1];
% Radius = round(MYR2/2);
%// Get sum in original image
TotalBlack_A = sum(sum(~A))
e = imellipse(gca, [Center(1) Center(2) Radius Radius]);
%// Create the mask
ROI = createMask(e);
%// Find white pixels
white_id = find(ROI);
%// Duplicate original image
B = A;
%// Replace only those pixels in the ROI with white
B(white_id) = 1;
%// Get new sum
NewBlack_B = sum(sum(~B))
%// Result!
BlackInRoi = TotalBlack_A - NewBlack_B
In this case I get this output:
TotalBlack_A =
158852
NewBlack_B =
156799
BlackInRoi =
2053
For this input image:

How to detect certain moving points in a video using Matlab

I have a video of moving hose in an experiment and I need to detect certain points in that hose and calculate the amplitude of their movements, I am using the code below and I am able to extract the required point using detectSURFFeatures, the function get many unnecessary points so I am using cuba = ref_pts.selectStrongest(5); to choose only five points, the problem is I can not get a function to put a bounding box about this 5 points and get their pixel values through the video, Kindly advice what functions can be used, thanks :)
clear;
clc;
% Image aquisition from Video and converting into gray scale
vidIn = VideoReader('ItaS.mp4');
%% Load reference image, and compute surf features
ref_img = read(vidIn, 1);
ref_img_gray = rgb2gray(ref_img);
ref_pts = detectSURFFeatures(ref_img_gray);
[ref_features, ref_validPts] = extractFeatures(ref_img_gray, ref_pts);
figure; imshow(ref_img);
hold on; plot(ref_pts.selectStrongest(5));
cuba = ref_pts.selectStrongest(5);
stats1 = round(cuba.Location);
If you want to find the bounding box which covers all the five points you selected: stats1 now contains (x, y) coordinates of the selected 5 points. Find min and max for x and y coordinates. min values of x and y gives you the starting point of the rectangle. Width and height of the bounding box is now the difference of max and min in y and x directions.
If you want to extract the part of the original image inside the bounding box: just copy that part to another variable as you want. Consider the following example.
img2 = img1(y:h, x:w, :)
Here, x and y are the x and y coordinates of the top left corner of the bounding box. w and h are the width and height of the bounding box.