I have recently found an interesting article regarding image rectification for two stereo image pairs. I liked the algorithm because it was very compact and from what the article suggested it did the right thing. After I implemented the matlab version on two images, I didn't get a correct rectified image. I got an image that was pitch black apart from the left and down line which had pixels. In the image there also were some gray pixels from the original image but just a hand full. I posted below the matlab code, and the link to the article and also an example of the result I got for one image (for the other image it was the same)
This is the link to the article A compact algorithm for rectification of stereo pairs.
A screen shot with the initial images and the results is bellow:
The initial images are the following two(such that you do not have to search for another stereo pair) :
function [T1,T2,Pn1,Pn2] = rectify(Po1,Po2)
% RECTIFY: compute rectification matrices
% factorize old PPMs
[A1,R1,t1] = art(Po1);
[A2,R2,t2] = art(Po2);
% optical centers (unchanged)
c1 = - inv(Po1(:,1:3))*Po1(:,4);
c2 = - inv(Po2(:,1:3))*Po2(:,4);
% new x axis (= direction of the baseline)
v1 = (c1-c2);
% new y axes (orthogonal to new x and old z)
v2 = cross(R1(3,:)',v1);
% new z axes (orthogonal to baseline and y)
v3 = cross(v1,v2);
% new extrinsic parameters
R = [v1'/norm(v1)
v2'/norm(v2)
v3'/norm(v3)];
% translation is left unchanged
% new intrinsic parameters (arbitrary)
A = (A1 + A2)./2;
A(1,2)=0; % no skew
A(1,3) = A(1,3) + 160;
% new projection matrices
Pn1 = A * [R -R*c1 ];
Pn2 = A * [R -R*c2 ];
% rectifying image transformation
T1 = Pn1(1:3,1:3)* inv(Po1(1:3,1:3));
T2 = Pn2(1:3,1:3)* inv(Po2(1:3,1:3));
function [A,R,t] = art(P)
% ART: factorize a PPM as P=A*[R;t]
Q = inv(P(1:3, 1:3));
[U,B] = qr(Q);
R = inv(U);
t = B*P(1:3,4);
A = inv(B);
A = A ./A(3,3);
This is the "main" code from which I call my rectify function
img1 = imread('D:\imag1.png');
img2 = imread('D:\imag2.png');
im1 = rgb2gray(img1);
im2 = rgb2gray(img2);
im1 = im2double(im1);
im2 = im2double(im2);
figure; imshow(im1, 'border', 'tight')
figure; imshow(im2, 'border', 'tight')
%pair projection matrices obtained after the calibration P01,P02
a = double(9.765*(10^2))
b = double(5.790*(10^-1))
format bank;
Po1 = double([a 5.382*10 -2.398*(10^2) 3.875*(10^5);
9.849*10 9.333*(10^2) 1.574*(10^2) 2.428*(10^5);
b 1.108*(10^(-1)) 8.077*(10^(-1)) 1.118*(10^3)]);
Po2 = [9.767*(10^2) 5.376*10 -2.400*(10^2) 4.003*(10^4);
9.868*10 9.310*(10^2) 1.567*(10^2) 2.517*(10^5);
5.766*(10^(-1)) 1.141*(10^(-1)) 8.089*(10^(-1)) 1.174*(10^3)];
[T1, T2, Pn1, Pn2] = rectify(Po1, Po2);
imnoua = conv2(im1, T1);
imnoua2 = conv2(im2, T2);
fprintf('Imaginea noua e \n');
figure; imshow(imnoua, 'border', 'tight')
figure; imshow(imnoua2, 'border', 'tight')
Thank you for your time!
As Shai says, T1 and T2 are projective transformation matrices, not filter kernels. You should be using imwarp, rather than conv2:
imnoua = imwarp(im1, projective2d(T1));
imnoua2 = imwarp(im2, projective2d(T2));
Better yet, use rectifyStereoImages from the Computer Vision System Toolbox. Check out this example.
Related
When calibrating a fisheye camera using Matlab, I get the fisheye intrinsics parameters:
% Calibrate the camera using fisheye parameters
[cameraParams, imagesUsed, estimationErrors] = estimateFisheyeParameters(imagePoints, worldPoints, ...
[mrows, ncols], ...
'EstimateAlignment', true, ...
'WorldUnits', 'millimeters');
The output of this function are the Scaramuzza parameters, in a shape very different from the classical 3x3 intrinsics matrix.
From this intrinsic parameters, I would like to estimate the pose of one my calibration pattern. So far I found two solutions but I do not know which one is more accurate.
First, I found I can directly feed the extrinsics function with the current intrinsics :
% Extract intrinsics parameters
intrinsics = cameraParams.Intrinsics;
% Compute Rt matrix
[R,t] = extrinsics(imagePoints,worldPoints,intrinsics);
Looking inside the function, I can see this method uses the homography but kind of process by magic the Scaramuzza's intrinsics parameters. It is the same function used for both fisheye and non-fisheye models. Any idea the Scaramuzza parameters are processed here ?
Second solution is to use the function estimateWorldCameraPose which uses P3P and a RANSAC underneath. This function does not accept the raw fisheye parameters. One solution I found (https://fr.mathworks.com/matlabcentral/answers/548787-function-estimateworldcamerapose-or-extrinsics-for-fisheyeparameters-is-missing-is-it-possible?s_tid=answers_rc1-2_p2_MLT) uses the function undistortFisheyeImage as a workaround to extract the 3x3 intrinsic parameters :
[J,camIntrinsics] = undistortFisheyeImage(I,intrinsics)
Then I can feed the new intrinsics in the estimateWorldCameraPose.
Is this solution better ? How realiable this new intrinsics matrix is ?
In all calibration methods (either a normal lens or fisheye lens), the extrinsic estimation uses the undistorted image points. So, the matlab function "extrinsics" should have the undistortion part(undistortion using Scaramuzza's lens distortion model) as well.
Looking at the code "extrinsics", I see it is seperately handling the intrinsic when it is fisheye model.
if ~isa(cameraParams, 'fisheyeIntrinsics')
if isa(cameraParams, 'cameraParameters')
intrinsicParams = cameraParams;
else
intrinsicParams = cameraParams.CameraParameters;
end
intrinsics = intrinsicParams.IntrinsicMatrix;
[rotationMatrix, translationVector] = vision.internal.calibration.extrinsicsPlanar(...
imagePoints, worldPoints, intrinsics);
else
That is the only solution and only way to do that.
extrinsics function both accept fisheye and non-fisheye models,if accept fisheye model,the input argument imagePoints is distort points,while pin-hole(non-fisheye) model, it must accept undistort image points. it's internal implementation is both vision.internal.calibration.extrinsicsPlanar.m function.
function [R,T] = extrinsicsPlanar(imagePoints, worldPoints, intrinsics)
A = intrinsics';
% Compute homography.
H = fitgeotrans(worldPoints, imagePoints, 'projective');
H = H.T';
h1 = H(:, 1);
h2 = H(:, 2);
h3 = H(:, 3);
lambda = 1 / norm(A \ h1);
% Compute rotation
r1 = A \ (lambda * h1);
r2 = A \ (lambda * h2);
r3 = cross(r1, r2);
R = [r1'; r2'; r3'];
% R may not be a true rotation matrix because of noise in the data.
% Find the best rotation matrix to approximate R using SVD.
[U, ~, V] = svd(R);
R = U * V';
% Compute translation vector.
T = (A \ (lambda * h3))';
EXTRINSICS Compute camera extrinsics from a planar calibration pattern,so this function is suit for you.
Pixel point de-aliasing was performed using the hidden method in the fisheyeIntrinsics class before processing the fisheye pixel points(before extrinsicsPlanar function).
%------------------------------------------------------------------
% Determine the normalized 3D vector on the unit sphere
%------------------------------------------------------------------
function worldPoints = imageToNormalizedVector(this, imagePoints)
%imageToNormalizedVector Determine the normalized 3D vector on
%the unit sphere.
% worldPoints = imageToNormalizedWorld(intrinsics,imagePoints)
% maps image points to the normalized 3D vector emanating from
% the single effective viewpoint on the unit sphere.
%
% Inputs:
% -------
% intrinsics - fisheyeIntrinsics object.
%
% imagePoints - M-by-2 matrix containing [x, y]
% coordinates of image points. M is the
% number of points.
%
% Output:
% -------
% worldPoints - M-by-3 matrix containing corresponding
% [X,Y,Z] coordinates on the unit sphere.
points = vision.internal.inputValidation.checkAndConvertPoints(...
imagePoints, 'fisheyeIntrinsics', 'imagePoints');
if isa(points, 'single')
points = double(points);
end
center = double(this.DistortionCenter);
stretch = double(this.StretchMatrix);
coeffs = double(this.MappingCoeffsInternal);
% Convert image points to sensor coordinates
points(:, 1) = points(:, 1) - center(1);
points(:, 2) = points(:, 2) - center(2);
points = stretch \ points';
rho = sqrt(points(1, :).^2 + points(2, :).^2);
f = polyval(coeffs(end:-1:1), rho);
% Note, points could be invalid if f < 0
worldPoints = [points; f]';
nw = sqrt(sum(worldPoints.^2, 2));
nw(nw == 0) = eps;
worldPoints = worldPoints ./ horzcat(nw,nw, nw);
worldPoints = cast(worldPoints, class(imagePoints));
end
estimateWorldCameraPose function input argument worldPoints accept 3 columns positions. but you use coplaner coordinates, z=0,may be this function return status is 1 or 2. So your later solution may not better.
I have a synthetic image. I want to do eigenvalue decomposition of local structure tensor (LST) of it for some edge detection purposes. I used the eigenvaluesl1 , l2 and eigenvectors e1 ,e2 of LST to generate an adaptive ellipse for each pixel of image. Unfortunately I get unequal eigenvalues l1 , l2 and so unequal semi-axes length of ellipse for homogeneous regions of my figure:
However I get good response for a simple test image:
I don't know what is wrong in my code:
function [H,e1,e2,l1,l2] = LST_eig(I,sigma1,rw)
% LST_eig - compute the structure tensor and its eigen
% value decomposition
%
% H = LST_eig(I,sigma1,rw);
%
% sigma1 is pre smoothing width (in pixels).
% rw is filter bandwidth radius for tensor smoothing (in pixels).
%
n = size(I,1);
m = size(I,2);
if nargin<2
sigma1 = 0.5;
end
if nargin<3
rw = 0.001;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% pre smoothing
J = imgaussfilt(I,sigma1);
% compute gradient using Sobel operator
Sch = [-3 0 3;-10 0 10;-3 0 3];
%h = fspecial('sobel');
gx = imfilter(J,Sch,'replicate');
gy = imfilter(J,Sch','replicate');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% compute tensors
gx2 = gx.^2;
gy2 = gy.^2;
gxy = gx.*gy;
% smooth
gx2_sm = imgaussfilt(gx2,rw); %rw/sqrt(2*log(2))
gy2_sm = imgaussfilt(gy2,rw);
gxy_sm = imgaussfilt(gxy,rw);
H = zeros(n,m,2,2);
H(:,:,1,1) = gx2_sm;
H(:,:,2,2) = gy2_sm;
H(:,:,1,2) = gxy_sm;
H(:,:,2,1) = gxy_sm;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% eigen decomposition
l1 = zeros(n,m);
l2 = zeros(n,m);
e1 = zeros(n,m,2);
e2 = zeros(n,m,2);
for i = 1:n
for j = 1:m
Hmat = zeros(2);
Hmat(:,:) = H(i,j,:,:);
[V,D] = eigs(Hmat);
D = abs(D);
l1(i,j) = D(1,1); % eigen values
l2(i,j) = D(2,2);
e1(i,j,:) = V(:,1); % eigen vectors
e2(i,j,:) = V(:,2);
end
end
Any help is appreciated.
This is my ellipse drawing code:
% determining ellipse parameteres from eigen value decomposition of LST
M = input('Enter the maximum allowed semi-major axes length: ');
I = input('Enter the input data: ');
row = size(I,1);
col = size(I,2);
a = zeros(row,col);
b = zeros(row,col);
cos_phi = zeros(row,col);
sin_phi = zeros(row,col);
for m = 1:row
for n = 1:col
a(m,n) = (l2(m,n)+eps)/(l1(m,n)+l2(m,n)+2*eps)*M;
b(m,n) = (l1(m,n)+eps)/(l1(m,n)+l2(m,n)+2*eps)*M;
cos_phi1 = e1(m,n,1);
sin_phi1 = e1(m,n,2);
len = hypot(cos_phi1,sin_phi1);
cos_phi(m,n) = cos_phi1/len;
sin_phi(m,n) = sin_phi1/len;
end
end
%% plot elliptic structuring elements using parametric equation and superimpose on the image
figure; imagesc(I); colorbar; hold on
t = linspace(0,2*pi,50);
for i = 10:10:row-10
for j = 10:10:col-10
x0 = j;
y0 = i;
x = a(i,j)/2*cos(t)*cos_phi(i,j)-b(i,j)/2*sin(t)*sin_phi(i,j)+x0;
y = a(i,j)/2*cos(t)*sin_phi(i,j)+b(i,j)/2*sin(t)*cos_phi(i,j)+y0;
plot(x,y,'r','linewidth',1);
hold on
end
end
This my new result with the Gaussian derivative kernel:
This is the new plot with axis equal:
I created a test image similar to yours (probably less complicated) as follows:
pos = yy([400,500]) + 100 * sin(xx(400)/400*2*pi);
img = gaussianlineclip(pos+50,7) + gaussianlineclip(pos-50,7);
I = double(stretch(img));
(This requires DIPimage to run)
Then ran your LST_eig on it (sigma1=1 and rw=3) and your code to draw ellipses (no change to either, except adding axis equal), and got this result:
I suspect some non-uniformity in some of the blue areas of your image, which cause very small gradients to appear. The problem with the definition of the ellipses as you use them is that, for sufficiently oriented patterns, you'll get a line even if that pattern is imperceptible. You can get around this by defining your ellipse axes lengths as follows:
a = repmat(M,size(l2)); % longest axis is always the same
b = M ./ (l2+1); % shortest axis is shorter the more important the largest eigenvalue is
The smallest eigenvalue l1 is high in regions with strong gradients but no clear direction. The above does not take this into account. One option could be to make a depend on both energy and anisotropy measures, and b depend only on energy:
T = 1000; % some threshold
r = M ./ max(l1+l2-T,1); % circle radius, smaller for higher energy
d = (l2-l1) ./ (l1+l2+eps); % anisotropy measure in range [0,1]
a = M*d + r.*(1-d); % use `M` length for high anisotropy, use `r` length for high isotropy (circle)
b = r; % use `r` width always
This way, the whole ellipse shrinks if there are strong gradients but no clear direction, whereas it stays large and circular when there are only weak or no gradients. The threshold T depends on image intensities, adjust as needed.
You should probably also consider taking the square root of the eigenvalues, as they correspond to the variance.
Some suggestions:
You can write
a = (l2+eps)./(l1+l2+2*eps) * M;
b = (l1+eps)./(l1+l2+2*eps) * M;
cos_phi = e1(:,:,1);
sin_phi = e1(:,:,2);
without a loop. Note that e1 is normalized by definition, there is no need to normalize it again.
Use Gaussian gradients instead of Gaussian smoothing followed by Sobel or Schaar filters. See here for some MATLAB implementation details.
Use eig, not eigs, when you need all eigenvalues. Especially for such a small matrix, there is no advantage to using eigs. eig seems to produce more consistent results. There is no need to take the absolute value of the eigenvalues (D = abs(D)), as they are non-negative by definition.
Your default value of rw = 0.001 is way too small, a sigma of that size has no effect on the image. The goal of this smoothing is to average gradients in a local neighborhood. I used rw=3 with good results.
Use DIPimage. There is a structuretensor function, Gaussian gradients, and a lot more useful stuff. The 3.0 version (still in development) is a major rewrite that improves significantly on dealing with vector- and matrix-valued images. I can write all of your LST_eig as follows:
I = dip_image(I);
g = gradient(I, sigma1);
H = gaussf(g*g.', rw);
[e,l] = eig(H);
% Equivalences with your outputs:
l1 = l{2};
l2 = l{1};
e1 = e{2,:};
e2 = e{1,:};
I'm a beginner in image processing and I'm using MATLAB to extract HOG features from the images to train SVM classifier. The size of the training images is 480*640 pixels and I'm getting 167796 features with the default settings for the built-in MATLAB extractHOGFeatures function. However, when I test the model it gives me less features (216 features only!) knowing that the testing images have the same size of the training images. I get this error in MATLAB "The number of columns in TEST and training data must be equal".
Do you have any clue how to solve this problem and get feature vector with the same size for the training and testing sets?
Here is the code,
[fpos,fneg] = featuress(pathPos, pathNeg);
%train SVM
HOG_featV = loadingV(fpos,fneg); % loading and labeling each training example
%% Detection
tSize = [24 32];
testImPath = '.\face_detection\dataset\bikes_and_persons2\';
imlist = dir([testImPath '*.bmp']);
for j = 1:length(imlist)
disp ('inside for loop');
img = imread([testImPath imlist(j).name]);
axis equal; axis tight; axis off;
imshow(img); hold on;
detect(img,model,tSize);
%% training
function [fpos, fneg] = featuress(pathPos,pathNeg)
% extract features for positive examples
imlist = dir([pathPos '*.bmp']);
for i = 1:length(imlist)
im = imread([pathPos imlist(i).name]);
fpos{i} = extractHOGFeatures(double(im));
end
% extract features for negative examples
imlist = dir([pathNeg '*.bmp']);
for i = 1:length(imlist)
im = imread([pathNeg imlist(i).name]);
fneg{i} = extractHOGFeatures(double(im));
end
end
%% testing function
function detect(im,model,wSize)
topLeftRow = 1;
topLeftCol = 1;
[bottomRightCol bottomRightRow d] = size(im);
fcount = 1;
for y = topLeftCol:bottomRightCol-wSize(2)
for x = topLeftRow:bottomRightRow-wSize(1)
p1 = [x,y];
p2 = [x+(wSize(1)-1), y+(wSize(2)-1)];
po = [p1; p2];
img = imcut(po,im);
featureVector{fcount} = extractHOGFeatures(double(img));
boxPoint{fcount} = [x,y];
fcount = fcount+1;
x = x+1;
end
end
lebel = ones(length(featureVector),1);
P = cell2mat(featureVector');
% each row of P' correspond to a window
[ predictions] = svmclassify(model, P); % classifying each window
[a, indx]= max(predictions);
bBox = cell2mat(boxPoint(indx));
rectangle('Position',[bBox(1),bBox(2),24,32],'LineWidth',1, 'EdgeColor','r');
end
Thanks in advance.
What's the size of P? Is it 167796 x 216? If so then, you should not transpose featureVector when you call cell2mat. Or you should transpose P before you use it. You can also make featureVector a matrix rather than a cell array. Since you know that the length of the HOG vector is 167796 and you know how many images you have, you can pre-allocate it up front, and fill in the rows.
I wanna explain my problem with MATLAB. My objective is to obtain a free liquid surface in a tank from a photo and to do this I have used this algorithm:
A = 'C:\foto\img3.bmp';
B = imread(A, 'bmp');
figure(1), imshow(B);
C = rgb2gray(B);
level = graythresh(C);
bw = im2bw(C,level);
bw = bwareaopen(bw, 50);
figure, imshow(bw);
BW1 = edge(bw,'canny');
figure(2), imshow(BW1);
imwrite(BW1, 'C:\foto\im1_edge.bmp', 'bmp')
Now I have the surface edge in white, with the background in black.
Next I have also detected the position of only white pixels:
I= imread('C:\foto\img3_edge.bmp');
imshow(I);
[r c] =size(I);
for j=1:c
for i=1:r
if(I(i,j)==1)
[i j]
end
end
end
At this point, how can I report (with a macro, automatically possibly) each couple of coordinates on a cartesian (x,y) plane? My objective is to obtain from the edge, so reconstructed, a function of the type "y = f(x)".
I have tried with another edge and have modified with paint the image to delete all useless pixels, the example is this one:
with the code:
I = im2bw(I);
it returns me an error "Warning: The input image is already binary." Next using the code:
[r c] = find(I), output = [r c];
plot(r,c,'.')
I obtained this one:
Moreover, when I try to insert r as xdata and c as ydata in cftool, I obtain the same problem and when I use "Interpolant" fitting, it returns an error. Why?
I don't know what type of fit you want to apply to your data. The following code will fit a 3rd order polynomial on your data.
I = imread('20jh1g2.jpg');
I = im2bw(I);
imshow(I);
[r, c] = find(I);
figure;
plot(c,r,'.');
hold on;
f = fit(c, r, 'poly3');
plot((min(c):max(c)),f(min(c):max(c)), 'red', 'LineWidth', 3);
Which will produce:
The rotation can be explained by how the axis are defined. In your image the Y axis goes from 0 at the top to 374 at the bottom. You can transform the result of your fit back into a binary image with the following code;
x = (min(c):max(c))';
y = round(f(x));
I = zeros(size(I));
I(y +((x-1)*size(I,1))) = 1;
figure
imshow(I);
Which will produce:
The result of the fit, f is stored in a cfit object. You can evaluate this function by feeding it values for x, as shown above. The function coefficients can be found by printing the fields of the cfit object in the command window;
f =
Linear model Poly3:
f(x) = p1*x^3 + p2*x^2 + p3*x + p4
Coefficients (with 95% confidence bounds):
p1 = -6.252e-06 (-6.542e-06, -5.963e-06)
p2 = 0.001753 (0.001588, 0.001918)
p3 = -0.3667 (-0.3932, -0.3401)
p4 = 290.4 (289.3, 291.6)
To flip the function inside your reference frame and compute the centroid you can use this;
I = imread('20jh1g2.jpg');
I = im2bw(I);
[r, c] = find(I);
r = -r + size(I,1);
f = polyfit(c, r, 3);
plot((min(c):max(c)),polyval(f,(min(c):max(c))), 'red', 'LineWidth', 3);
hold on;
xf = [f 0];
fx2 = sym2poly(poly2sym(f)^2);
centroid = 1/polyval(polyint(f),size(I,2)) * [polyval(polyint(xf),size(I,2)) 1/2 * polyval(polyint(fx2),size(I,2))];
plot(centroid(1),centroid(2),'X');
Which will produce:
I have an image of a product on a solid background that I would like to crop as close as possible to the product.
I brighten it and find the edges with the following code:
limits = stretchlim(original, 0.01);
img1 = imadjust(original, limits, []);
img = rgb2gray(img1);
BW = edge(img,'canny',0.2);
[B,L,N,A] = bwboundaries(BW);
figure; imshow(BW); hold on;
for k=1:length(B),
if(~sum(A(k,:)))
boundary = B{k};
plot(boundary(:,2),boundary(:,1),'r','LineWidth',2);hold on;
end
end
Which give me the following image:
The following code gives me rectangles on every blob/line detected:
blobMeasurements = regionprops(logical(BW), 'BoundingBox');
numberOfBlobs = size(blobMeasurements, 1);
rectCollection = [];
for k = 1 : numberOfBlobs % Loop through all blobs.
rects = blobMeasurements(k).BoundingBox; % Get list ofpixels in current blob.
x1 = rects(1);
y1 = rects(2);
x2 = x1 + rects(3);
y2 = y1 + rects(4);
x = [x1 x2 x2 x1 x1];
y = [y1 y1 y2 y2 y1];
rectCollection(k,:,:,:) = [x1; y1; x2; y2];
end
I'm able to then draw a bounding rectangle and crop with all these points collected with the following code:
% get min max
xmin=min(rectCollection(:,1))-1;
ymin=min(rectCollection(:,2))-1;
xmax=max(rectCollection(:,3))+1;
ymax=max(rectCollection(:,4))+1;
% define outer rect:
outer_rect=[xmin ymin xmax-xmin ymax-ymin];
crop = imcrop(original,outer_rect);
Which gives me the following result:
My question is how can I get a polygon as close as possible to the product and crop it with the polygon or, alternatively, just crop as close as possible to the product and its cap?
If you don't want to get a bounding box but a polygon, I think you need to generate a mask - a matrix with the same size of your image, value 1 if the pixel in on your object, 0 if not.
I heard about an algorithm (sorry I can't find the name, I'll edit this post if I find it) which works with a lasso :
step 0 : your lasso is your bounding box.
step i : segment the lasso and for each part, you retract it if the color (or any other) gradient in the image is less than a fixed value.
step n (last) : you cannot retract any part of the lasso, it is finished. Inside your lasso : your object. Outside : the background.
As I remember there is a lot of work with this method : the definition of the lasso, the retractation step, the solidity of your lasso (to avoid too much deformation of the lasso).
Beside the lasso method you can search about the watershed transform, it can also work with your problem.
Finally, if you generate the pictures, take shots with a plained background (green, pink, blue, etc) and use a simple chromakey.
Using active contours also looks like a good approach but getting a nice mask is troublesome.
original = imread('1.jpg');
level = graythresh(original);
img = rgb2gray(original);
mask = im2bw(img,level+0.1);
mask = imfill(~mask,'holes');
bw = activecontour(img,mask);
rows = numel(original(:,1,1));
columns = numel(original(1,:,1));
for i = 1:rows
for j = 1:columns
if ( bw(i,j,1) == 0 )
original(i,j,:) = 255;
end
end
end
imshow(original);