gusucode.com > vision工具箱matlab源码程序 > vision/cylinderModel.m
classdef cylinderModel < vision.internal.EnforceScalarHandle %cylinderModel Object for storing a parametric cylinder model. % model = cylinderModel(params) constructs a parametric cylinder model % from a 1-by-7 vector, params. Params has seven parameters [x1, y1, % z1, x2, y2, z2, r] to describe a cylinder, where [x1, y1, z1] and [x2, % y2, z2] are centers of two end caps, respectively. r is the % radius of the cylinder. % % cylinderModel properties (read only): % Parameters - Cylinder model parameters % Center - Center of the cylinder % Orientation - Orientation vector of the cylinder % Height - Height of the cylinder % Radius - Radius of the cylinder % % cylinderModel methods: % plot - plot a cylinder % % See also cylinderModel>plot, pcfitcylinder, pointCloud, surf, % planeModel, sphereModel, pcshow % Copyright 2015 The MathWorks, Inc. properties (GetAccess = public, SetAccess = private) % Parameters is a 1-by-7 vector [x1, y1, z1, x2, y2, z2, r] to % describe a cylinder, where [x1, y1, z1] and [x2, y2, z2] are % centers of two ending surfaces, respectively. r is the radius of % the cylinder. Parameters; end properties(Dependent) % Center is a 1-by-3 vector that specifies the center of the cylinder. Center; % Orientation is a 1-by-3 vector that points from [x1,y1,z1] to % [x2,y2,z2], which are the centers of the cylinder end caps. Orientation; % Height specifies the height of the cylinder. Height; % Radius specifies the radius of the cylinder. Radius; end methods %================================================================== % Constructor %================================================================== % model = cylinderModel(params); function this = cylinderModel(params) % Validate the inputs validateattributes(params, {'single', 'double'}, ... {'real', 'nonsparse', 'finite', 'vector', 'numel', 7}, mfilename, 'params'); validateattributes(params(7), {'single', 'double'}, ... {'scalar','positive'}, mfilename, 'Radius, params(7),'); this.Parameters = params; end %================================================================== % Dependent properties %================================================================== function center = get.Center(this) center = (this.Parameters(1:3)+this.Parameters(4:6))/2; end function orientation = get.Orientation(this) orientation = this.Parameters(4:6)-this.Parameters(1:3); end function height = get.Height(this) p1 = this.Parameters(1:3); p2 = this.Parameters(4:6); height = norm(p1 - p2); end function radius = get.Radius(this) radius = this.Parameters(7); end %================================================================== % Plot a cylinder %================================================================== function H = plot(this, varargin) %plot plot a cylinder in a figure window. % H = plot(model) plots a cylinder and returns a handle to % <a href="matlab:doc('surf')">surface plot object</a>. % % H = plot(..., 'Parent', ax) additionally allows you to % specify an output axes. By default, ax is set to gca. % % Example: Detect a cylinder in a point cloud % ------------------------------------------- % load('object3d.mat'); % % figure % pcshow(ptCloud) % xlabel('X(m)') % ylabel('Y(m)') % zlabel('Z(m)') % title('Detect a cylinder in a point cloud') % % % Set the maximum point-to-cylinder distance (5mm) for cylinder fitting % maxDistance = 0.005; % % % Set the roi to constrain the search % roi = [0.4, 0.6; -inf, 0.2; 0.1, inf]; % sampleIndices = findPointsInROI(ptCloud, roi); % % % Set the orientation constraint % referenceVector = [0, 0, 1]; % % % Detect the cylinder and extract it from the point cloud % model = pcfitcylinder(ptCloud, maxDistance, referenceVector, 'SampleIndices', sampleIndices); % % % Plot the cylinder % hold on % plot(model) currentAxes = validateAndParseInputs(mfilename, varargin{:}); [X, Y, Z] = cylinder(this.Radius, 30); [X, Y, Z] = this.transformCylinder(X, Y, Z); handle = surf(currentAxes, X, Y, Z); if nargout > 0 H = handle; end end end methods (Access = protected) %================================================================== % helper function to transform the data %================================================================== function [X, Y, Z] = transformCylinder(this, X, Y, Z) a = cast([0, 0, 1], 'like', this.Parameters); h = this.Height; % Rescale the height Z(2, :) = Z(2, :) * h; if h == 0 b = [0, 0, 1]; else b = (this.Parameters(4:6) - this.Parameters(1:3)) / h; end % Rotate the points to the desired axis direction v = cross(a, b); s = dot(v, v); if abs(s) > eps(class(s)) Vx = [ 0, -v(3), v(2); ... v(3), 0, -v(1); ... -v(2), v(1), 0]; R = transpose(eye(3) + Vx + Vx*Vx*(1-dot(a, b))/s); T = this.Parameters(1:3); if iscolumn(T) T = T'; end XYZ = bsxfun(@plus, [X(:), Y(:), Z(:)] * R, T); X = reshape(XYZ(:, 1), 2, []); Y = reshape(XYZ(:, 2), 2, []); Z = reshape(XYZ(:, 3), 2, []); end end end end %========================================================================== function ax = validateAndParseInputs(filename, varargin) % Parse the PV-pairs % Setup parser parser = inputParser; parser.CaseSensitive = false; parser.FunctionName = filename; parser.addParameter('Parent', [], ... @vision.internal.inputValidation.validateAxesHandle); parser.parse(varargin{:}); ax = parser.Results.Parent; % Plot to the specified axis, or create a new one if isempty(ax) ax = newplot; end end