I need to create a binary mask. I have some coordinates and I make those coordinates and inside that region equal to 1, and background equal to zero.
Here is what I have done, but the problem is ROI located not in the correct position and located on the right bottom of the image. I appreciate if someone could point me to the right direction.
function [X,Y, BW] = Create_mask(X,Y,im)
X = round(X);
Y = round(Y);
X ( X < 1 ) = 1;
Y ( Y < 1 ) = 1;
BW = im > 255;
for p = 1:length(X)
BW(Y(p),X(p)) = 1;
end
for n = 0:(1/round(sqrt((X(end)-X(1))^2 + (Y(end)-Y(1))^2 ))):1
xn = round(X(1) +(X(end) - X(1))*n);
yn = round(Y(1) +(Y(end) - Y(1))*n);
BW(yn,xn) = 1;
end
se = strel('disk',10);
BW = imclose(BW,se);
BW = imdilate(BW,se);
BW = imfill(BW,'holes');
im( im < 255 ) = 0;
im = imclose(im,se);
BW = BW * 255;
BW = im2uint8(BW);
% BW = imresize(BW, [256 256],'nearest');
figure;
imshow(BW);
% close all;
end
Here is the output the function:
I was expecting to be similar to this image. This is not the exact solution but it shows my expectation.
X and Y coordinates are attached here, The first col is X and the second Y.
you can do this by calling function inpolygon, try this
function mask=createmask(x,y, cmin, cmax, dx)
if(nargin<3)
cmin=min([x(:) y(:)]);
end
if(nargin<4)
cmax=max([x(:) y(:)]);
end
if(nargin<5)
dx=(cmax-cmin)/100;
end
if(length(dx)==1)
dx=[dx dx];
end
[xi,yi]=meshgrid(cmin(1):dx(1):cmax(1),cmin(2):dx(2):cmax(2));
mask=reshape(inpolygon(xi(:),yi(:),x(:),y(:)), size(xi));
to test
xv = [0 3 3 0 0 NaN 1 1 2 2 1];
yv = [0 0 3 3 0 NaN 1 2 2 1 1];
mask=createmask(xv,yv, [-1 -1], [4 4]);
imagesc(mask)
Working on a little project to do with computer graphics. So far I have (I think) everything in order as the code below patches my world to the screen fine.
However, I have a final hurdle to jump: I would like the code to patch for different values of theta. In the code, it is set at 2*pi/4 but I would like to iterate and patch for every angle between 0:pi/4:2*pi. However, when I try to put the code in a for or while loop it doesn't seem to do what I expect, that is, to patch with one angle, then patch with another etc.
Really stuck I have tried a lot of stuff and now I'm just without any ideas. Would really appreciate any help or suggestions.
function world()
% Defining House Vertices
house_verts = [-5, 0, -5;
5, 0, -5;
5, 10, -5;
0,15,-5;
-5,10,-5;
-5,0,5;
5,0,5;
5,10,5;
0,15,5;
-5,10,5];
% Sorting out the homeogenous co-ordinates
ones = [1,1,1,1,1,1,1,1,1,1];
ones=transpose(ones);
house_verts = [house_verts, ones];
house_verts = transpose(house_verts);
% House faces
house_faces = [1,2,3,4,5;
2,7,8,3,3;
6,7,8,9,10;
1,6,10,5,5;
3,4,9,8,8;
4,5,10,9,9;
1,2,7,6,6];
world_pos = [];
% creating a street
street_vector = [1,0,1]; % the direction of the street
orthog_street_vector = [-1,0,1];
for i = 1:15
% current_pos1 and 2 will be the positions of the two houses
% opposite each other on the street
current_pos1 = 30*i*street_vector + 50*orthog_street_vector;
current_pos2 = 30*i*street_vector - 50*orthog_street_vector;
world_pos = [world_pos;current_pos1;current_pos2];
end
% initialising world vertices and faces
world_verts = [];
world_faces = [];
% Populating the street
for i =1:size(world_pos,1)
T = transmatrix(world_pos(i,:)); % a translation matrix
s = [1,1/2 + rand(),1];
S=scalmatrix(s); % a matrix for a random scaling of the height (y-coordinate)
Ry = rotymatrix(rand()*2*pi); % a matrix for a random rotation about the y-axis
A = T*Ry*S; % the compound transformation matrix to take the house into the world
obj_faces = size(world_verts,2) + house_faces; %increments the basic house faces to match the current object
obj_verts = A*house_verts;
world_verts = [world_verts, obj_verts]; % adds the vertices to the world
world_faces = [world_faces; obj_faces]; % adds the faces to the world
end
% initialising aligned vertices
align_verts = [];
% Aligning the vertices to the particular camera at angle theta
for elm = world_verts
x = 350 + 350*cos(2*pi/4);
z = 350 + 350*sin(2*pi/4);
y = 80;
u = [x,y,z];
v = [250,0,250];
d = v - u;
phiy = atan2(d(1),d(3));
phix = -atan2(d(2),sqrt(d(1)^2+d(3)^2));
T = transmatrix([-u(1),-u(2),-u(3)]);
Ry = rotymatrix(phiy);
Rx = rotxmatrix(phix);
A = Rx*Ry*T;
align_verts = [align_verts, A*elm];
end
% initialising projected vertices
proj_verts=[];
% Performing the projection
for elm = align_verts
proj = projmatrix(10);
projverts = proj*elm;
projverts = ((10/projverts(3))*projverts);
proj_verts = [proj_verts,projverts];
end
% Displaying the world
for i = 1:size(world_faces,1)
for j = 1:size(world_faces,2)
x(j) =proj_verts(1,world_faces(i,j));
z(j) = proj_verts(2,world_faces(i,j));
end
patch(x,z,'w')
end
end
function T = transmatrix(p)
T = [1 0 0 p(1) ; 0 1 0 p(2) ; 0 0 1 p(3) ; 0 0 0 1];
end
function S = scalmatrix(s)
S = [s(1) 0 0 0 ; 0 s(2) 0 0 ; 0 0 s(3) 0 ; 0 0 0 1];
end
function Ry = rotymatrix(theta)
Ry = [cos(theta), 0, -sin(theta),0;
0,1,0,0;
sin(theta),0,cos(theta),0;
0,0,0,1];
end
function Rx = rotxmatrix(phi)
Rx = [1, 0, 0, 0;
0, cos(phi), -sin(phi), 0;
0, sin(phi), cos(phi), 0;
0, 0, 0, 1];
end
function P = projmatrix(f)
P = [1,0,0,0
0,1,0,0
0,0,1,0
0,0,1/f,0];
end
Updated code: managed to get the loop to work but now there is some bug i don't understand when it does a full rotation again any help would be great.
function world()
% Defining House Vertices
house_verts = [-5, 0, -5;
5, 0, -5;
5, 10, -5;
0,15,-5;
-5,10,-5;
-5,0,5;
5,0,5;
5,10,5;
0,15,5;
-5,10,5];
% Sorting out the homeogenous co-ordinates
ones = [1,1,1,1,1,1,1,1,1,1];
ones=transpose(ones);
house_verts = [house_verts, ones];
house_verts = transpose(house_verts);
% House faces
house_faces = [1,2,3,4,5;
2,7,8,3,3;
6,7,8,9,10;
1,6,10,5,5;
3,4,9,8,8;
4,5,10,9,9;
1,2,7,6,6];
world_pos = [];
% creating a street
street_vector = [1,0,1]; % the direction of the street
orthog_street_vector = [-1,0,1];
for i = 1:15
% current_pos1 and 2 will be the positions of the two houses
% opposite each other on the street
current_pos1 = 30*i*street_vector + 50*orthog_street_vector;
current_pos2 = 30*i*street_vector - 50*orthog_street_vector;
world_pos = [world_pos;current_pos1;current_pos2];
end
% initialising world vertices and faces
world_verts = [];
world_faces = [];
% Populating the street
for i =1:size(world_pos,1)
T = transmatrix(world_pos(i,:)); % a translation matrix
s = [1,1/2 + rand(),1];
S=scalmatrix(s); % a matrix for a random scaling of the height (y-coordinate)
Ry = rotymatrix(rand()*2*pi); % a matrix for a random rotation about the y-axis
A = T*Ry*S; % the compound transformation matrix to take the house into the world
obj_faces = size(world_verts,2) + house_faces; %increments the basic house faces to match the current object
obj_verts = A*house_verts;
world_verts = [world_verts, obj_verts]; % adds the vertices to the world
world_faces = [world_faces; obj_faces]; % adds the faces to the world
end
% initialising aligned vertices
align_verts = [];
% initialising projected vertices
proj_verts=[];
% Aligning the vertices to the particular camera at angle theta
theta = 0;
t = 0;
while t < 100
proj_verts=[];
align_verts = [];
for elm = world_verts
x = 300 + 300*cos(theta);
z = 300 + 300*sin(theta);
y = 80;
u = [x,y,z];
v = [200,0,200];
d = v - u;
phiy = atan2(d(1),d(3));
phix = -atan2(d(2),sqrt(d(1)^2+d(3)^2));
T = transmatrix([-u(1),-u(2),-u(3)]);
Ry = rotymatrix(phiy);
Rx = rotxmatrix(phix);
A = Rx*Ry*T;
align_verts = [align_verts, A*elm];
end
% Performing the projection
for elm = align_verts
proj = projmatrix(6);
projverts = proj*elm;
projverts = ((6/projverts(3))*projverts);
proj_verts = [proj_verts,projverts];
end
% Displaying the world
for i = 1:size(world_faces,1)
for j = 1:size(world_faces,2)
x(j) = proj_verts(1,world_faces(i,j));
z(j) = proj_verts(2,world_faces(i,j));
end
patch(x,z,'w')
pbaspect([1,1,1]); % adjusts the aspect ratio of the figure
end
title('Projected Space', 'fontsize', 16, 'interpreter', 'latex')
xlabel('$x$', 'fontsize', 16, 'interpreter', 'latex')
ylabel('$z$', 'fontsize', 16, 'interpreter', 'latex')
zlabel('$y$', 'fontsize', 16, 'interpreter', 'latex')
axis([-5,5,-5,2,0,5]) % sets the axes limits
view(0,89)
pause(0.0000001)
theta = theta + 0.01;
clf
end
end
function T = transmatrix(p)
T = [1 0 0 p(1) ; 0 1 0 p(2) ; 0 0 1 p(3) ; 0 0 0 1];
end
function S = scalmatrix(s)
S = [s(1) 0 0 0 ; 0 s(2) 0 0 ; 0 0 s(3) 0 ; 0 0 0 1];
end
function Ry = rotymatrix(theta)
Ry = [cos(theta), 0, -sin(theta),0;
0,1,0,0;
sin(theta),0,cos(theta),0;
0,0,0,1];
end
function Rx = rotxmatrix(phi)
Rx = [1, 0, 0, 0;
0, cos(phi), -sin(phi), 0;
0, sin(phi), cos(phi), 0;
0, 0, 0, 1];
end
function P = projmatrix(f)
P = [1,0,0,0
0,1,0,0
0,0,1,0
0,0,1/f,0];
end
I have a 2D image (matrix). I have found the local maxima of this image. Now I want to define the boundaries around each local maxima in such a way that I want all the pixels around the local maxima that have a value above 85% of the maximum.
Here is my existing code:
function [location]= Mfind_peak_2D( Image,varargin )
p = inputParser;
addParamValue(p,'max_n_loc_max',5);
addParamValue(p,'nb_size',3);
addParamValue(p,'thre',0);
addParamValue(p,'drop',0.15);
parse(p,varargin{:});
p=p.Results;
if sum(isnan(Image(:)))>0
Image(isnan(Image))=0;
end
hLocalMax = vision.LocalMaximaFinder;
hLocalMax.MaximumNumLocalMaxima = p.max_n_loc_max;
hLocalMax.NeighborhoodSize = [p.nb_size p.nb_size];
end
This should do the job (the code is full of comments and should be pretty self-explanatory but if you have doubts feel free to ask for more details):
% Load the image...
img = imread('peppers.png');
img = rgb2gray(img);
% Find the local maxima...
mask = ones(3);
mask(5) = 0;
img_dil = imdilate(img,mask);
lm = img > img_dil;
% Find the neighboring pixels of the local maxima...
img_size = size(img);
img_h = img_size(1);
img_w = img_size(2);
res = cell(sum(sum(lm)),3);
res_off = 1;
for i = 1:img_h
for j = 1:img_w
if (~lm(i,j))
continue;
end
value = img(i,j);
value_thr = value * 0.85;
% Retrieve the neighboring column and row offsets...
c = bsxfun(#plus,j,[-1 0 1 -1 1 -1 0 1]);
r = bsxfun(#plus,i,[-1 -1 -1 0 0 1 1 1]);
% Filter the invalid positions...
idx = (c > 0) & (c <= img_w) & (r > 0) & (r <= img_h);
% Transform the valid positions into linear indices...
idx = (((idx .* c) - 1) .* img_h) + (idx .* r);
idx = reshape(idx.',1,numel(idx));
idx = idx(idx > 0);
% Retrieve the neighbors and filter them based on te threshold...
neighbors = img(idx);
neighbors = neighbors(neighbors > value_thr);
% Update the final result...
res(res_off,:) = {sub2ind(img_size,i,j) value neighbors};
res_off = res_off + 1;
end
end
res = sortrows(res,1);
The variable res will be a cell matrix with three columns: the first one contain the linear indices to the local maxima of the image, the second one contains the values of the local maxima and the third one a vector with the pixels around the local maxima that fall within the specified threshold.
So I have this code to rotate and skew an image. it works well for the rotation, and the image will fit exactly in the canvas. However if I apply skewing the image doesn't fit anymore. Can someone explain how to calculate the proper array dimension for the resulting image rotated and skewed by specific angles? In particular, I'm using this 2 lines for the rotated image (and it works although I don't fully understand them). How should I modify them such as even when skewed, the final image will fit? Thanks!
rows_new = ceil(rows_init_img * abs(cos(rads)) + cols_init_img * abs(sin(rads)));
cols_new = ceil(rows_init_img * abs(sin(rads)) + cols_init_img * abs(cos(rads)));
full code
clc;
clear;
%% init values
%loading initial image
init_img = imread('name2.png');
% define rows/cols dimension of original image pixel matrix
[rows_init_img, cols_init_img,z]= size(init_img);
% skew angle in radians
sk_angle = 50;
sk_rads = 2*pi*sk_angle/360;
% rotation angle in radians
angle = 20;
rads = 2*pi*angle/360;
%% calculate size of final_image
orig_corners = [ 1, 1; 1, rows_init_img; 1, cols_init_img; rows_init_img, cols_init_img];
new_corners = uint8(zeros(size(orig_corners)));
for i = 1:size(orig_corners, 1)
for j = 1:size(orig_corners, 2)
% translate
a = i - final_origin_x;
b = j - final_origin_y;
% rotate
x = a * cos(rads) - b * sin(rads);
y = a * sin(rads) + b * cos(rads);
% skew along x axis (AFTER rotation)
x = x + sk_rads * y;
% translate
x = x + init_origin_x;
y = y + init_origin_y;
% round to turn values to positive integers
x = round(x);
y = round(y);
if (x >= 1 && y >= 1 && x <= size(orig_corners, 1) && y <= size(orig_corners, 2) )
new_corners(i, j) = init_img(x, y);
end
end
end
% calculating array dimesions such that rotated image gets fit in it exactly.
% rows_new = ceil(rows_init_img * abs(cos(rads)) + cols_init_img * abs(sin(rads)));
% cols_new = ceil(rows_init_img * abs(sin(rads)) + cols_init_img * abs(cos(rads)));
% define an array with calculated dimensions and fill the array with zeros ie.,black
% uint8 is important. without it will show noise WHY?
final_img = uint8(zeros([rows_new cols_new 3 ]));
%calculating center of original image
init_origin_x = ceil(rows_init_img/2);
init_origin_y = ceil(cols_init_img/2);
%calculating center of final image
final_origin_x = ceil( size(final_img, 1)/2 );
final_origin_y = ceil( size(final_img, 2)/2 );
%% main loop
% apply transformation to each pixel of the image
for i = 1:size(final_img ,1)
for j = 1:size(final_img, 2)
% translate
a = i - final_origin_x;
b = j - final_origin_y;
% rotate
x = a * cos(rads) - b * sin(rads);
y = a * sin(rads) + b * cos(rads);
% skew along x axis
x = x + sk_rads * y;
% translate
x = x + init_origin_x;
y = y + init_origin_y;
% round to turn values to positive integers
x = round(x);
y = round(y);
% make sure values exists (are part of the initial image) and copy
% them in the final image matrix
if (x >= 1 && y >= 1 && x <= size(init_img, 1) && y <= size(init_img, 2) )
final_img(i, j, :) = init_img(x, y, :);
end
end
end
%% display images
% original image
% figure('name','Original Image','numbertitle','off');
% imshow(init_img);
% result image
figure('name','Manipulated Image','numbertitle','off');
imshow(final_img);
updated code
clc;
clear;
%% init values
%loading initial image
init_img = imread('name2.png');
% define rows/cols dimension of original image pixel matrix
[rows_init_img, cols_init_img, z]= size(init_img);
% skew angle in radians
sk_angle = 50;
sk_rads = 2*pi*sk_angle/360;
% rotation angle in radians
angle = 20;
rads = 2*pi*angle/360;
%calculating center of original image
init_origin_x = ceil(rows_init_img/2);
init_origin_y = ceil(cols_init_img/2);
%% calculate size of final_image
orig_corners = [ 1, 1; 1, rows_init_img; 1, cols_init_img; rows_init_img, cols_init_img];
new_corners = uint8(zeros(size(orig_corners)));
for i = 1:size(orig_corners, 1)
for j = 1:size(orig_corners, 2)
% translate
a = i - final_origin_x; %at this point I don't have this variable because I can't create it yet
b = j - final_origin_y;
% rotate
x = a * cos(rads) - b * sin(rads);
y = a * sin(rads) + b * cos(rads);
% skew along x axis (AFTER rotation)
x = x + sk_rads * y;
% translate
x = x + init_origin_x;
y = y + init_origin_y;
% round to turn values to positive integers
x = round(x);
y = round(y);
if (x >= 1 && y >= 1 && x <= size(orig_corners, 1) && y <= size(orig_corners, 2) )
new_corners(i, j) = init_img(x, y);
end
end
end
% calculating array dimesions such that rotated image gets fit in it exactly.
rows_new = abs(max(new_corners(1, :)) - min(new_corners(1, :)));
cols_new = abs(max(new_corners(2, :)) - min(new_corners(2, :)));
% define an array with calculated dimensions and fill the array with zeros ie.,black
final_img = uint8(zeros([rows_new cols_new 3 ]));
%calculating center of final image
final_origin_x = ceil( size(final_img, 1)/2 );
final_origin_y = ceil( size(final_img, 2)/2 );
%% main loop
% apply transformation to each pixel of the image
for i = 1:size(final_img ,1)
for j = 1:size(final_img, 2)
% translate
a = i - final_origin_x;
b = j - final_origin_y;
% skew along x axis (BEFORE rotation)
a = a + sk_rads * b;
% rotate
x = a * cos(rads) - b * sin(rads);
y = a * sin(rads) + b * cos(rads);
% skew along x axis (AFTER rotation)
%x = x + sk_rads * y;
% translate
x = x + init_origin_x;
y = y + init_origin_y;
% round to turn values to positive integers
x = round(x);
y = round(y);
% make sure values exists (are part of the initial image) and copy
% them in the final image matrix
if (x >= 1 && y >= 1 && x <= size(init_img, 1) && y <= size(init_img, 2) )
final_img(i, j, :) = init_img(x, y, :);
end
end
end
%% display images
% original image
% figure('name','Original Image','numbertitle','off');
% imshow(init_img);
% result image
figure('name','Manipulated Image','numbertitle','off');
imshow(final_img);
I have used the following code from the matlab central website in my project to perform seeded region growing. This works perfectly but I am struggling to understand exactly what the code is doing in some places. I have contacted the author but have had no reply. Would anyone be able to provide me with some explanations ?
function Phi = segCroissRegion(tolerance,Igray,x,y)
if(x == 0 || y == 0)
imshow(Igray,[0 255]);
[x,y] = ginput(1);
end
Phi = false(size(Igray,1),size(Igray,2));
ref = true(size(Igray,1),size(Igray,2));
PhiOld = Phi;
Phi(uint8(x),uint8(y)) = 1;
while(sum(Phi(:)) ~= sum(PhiOld(:)))
PhiOld = Phi;
segm_val = Igray(Phi);
meanSeg = mean(segm_val);
posVoisinsPhi = imdilate(Phi,strel('disk',1,0)) - Phi;
voisins = find(posVoisinsPhi);
valeursVoisins = Igray(voisins);
Phi(voisins(valeursVoisins > meanSeg - tolerance & valeursVoisins < meanSeg + tolerance)) = 1;
end
Thanks
I've added some comments in your code :
function Phi = segCroissRegion(tolerance,Igray,x,y)
% If there's no point, select one from image
if(x == 0 || y == 0)
imshow(Igray,[0 255]);
[x,y] = ginput(1);
end
%Create seed with by adding point in black image
Phi = false(size(Igray,1),size(Igray,2));
ref = true(size(Igray,1),size(Igray,2));
PhiOld = Phi;
Phi(uint8(x),uint8(y)) = 1;
while(sum(Phi(:)) ~= sum(PhiOld(:)))
PhiOld = Phi;
% Evaluate image intensity at seed/line points
segm_val = Igray(Phi);
% Calculate mean intensity at seed/line points
meanSeg = mean(segm_val);
% Grow seed 1 pixel, and remove previous seed (so you'll get only new pixel perimeter)
posVoisinsPhi = imdilate(Phi,strel('disk',1,0)) - Phi;
% Evaluate image intensity over the new perimeter
voisins = find(posVoisinsPhi);
valeursVoisins = Igray(voisins);
% If image intensity over new perimeter is greater than the mean intensity of previous perimeter (minus tolerance), than this perimeter is part of the segmented object
Phi(voisins(valeursVoisins > meanSeg - tolerance & valeursVoisins < meanSeg + tolerance)) = 1;
% Repeat while there's new pixel in seed, stop if no new pixel were added
end