gusucode.com > vision工具箱matlab源码程序 > vision/+vision/+internal/+calibration/+tool/BoardSet.m

    % BoardSet Stores all information about checkerboard images
%
%    This class stores the file names from which checkerboards were 
%    extracted as well as checkerboard world points and detected key
%    points.

% Copyright 2012-2013 The MathWorks, Inc.

classdef BoardSet < handle
       
    properties(Access=private, Hidden)
        Version = ver('vision');
    end
    
    properties(GetAccess=public, SetAccess=private)
        
        FullPathNames = {};
        BoardSize = [];
        
        BoardPoints
        WorldPoints
        Units
        SquareSize
        
        BoardLabels % labels displayed in the data browser
        BoardIcons  % icons displayed in the data browser
        
        LastNonDetectedPathNames = {};
        
        NumBoards = 0;
    end
    
    properties(Dependent)
        IsStereo;
    end
    
    methods
        %------------------------------------------------------------------
        function isStereo = get.IsStereo(this)
            isStereo = size(this.FullPathNames, 1) == 2;
        end        
    end
    
    %----------------------------------------------------------------------
    methods (Access=public)
        
        function this = BoardSet(fileNames, squareSize, units)

            % begin by inspecting image size consistency
            this.checkImageSizes(fileNames);
            
            % proceed with adding the boards
            this.FullPathNames = fileNames;
            this.SquareSize    = squareSize;
            this.Units         = units;

            % set board labels by picking the file names without the path
            this.NumBoards = size(fileNames, 2);
            this.BoardLabels = cell(1, this.NumBoards);
            for i = 1:this.NumBoards
                this.BoardLabels{i} = makeLabel(this, fileNames(:, i));
            end
    
            % Detect checkerboard points
            delIdx = this.detectPointsForNewSession();
            this.deleteRejectedBoards(delIdx);
            this.generateIcons();
            
            % Derive the world points from board dimensions
            this.WorldPoints = ...
                generateCheckerboardPoints(this.BoardSize, this.SquareSize);                       
        end

        %------------------------------------------------------------------        
        function numDuplicates = addBoards(this, fileNames)
            
            % check image consistency
            this.checkImageSizes(fileNames);
            
            % proceed with adding images
            numOldImages = this.NumBoards;
            numNewImages = size(fileNames, 2);
            waitBar = ...
                vision.internal.calibration.checkerboard.DetectionProgressBar(numNewImages);
            
            numDuplicates = 0;
            this.LastNonDetectedPathNames = cell(size(fileNames, 1), 0);
            for i = 1:numNewImages
                if waitBar.Canceled
                    rollback(this, numOldImages);
                    error(message('vision:uitools:LoadingCanceledByUser'));
                end
                
                if this.isDuplicateFileName(fileNames(:, i))
                    numDuplicates = numDuplicates + 1;
                    continue;
                end
                
                if this.IsStereo
                    [points, boardSize] = detectCheckerboardPoints(...
                        fileNames{1, i}, fileNames{2, i});
                else
                    [points, boardSize] = detectCheckerboardPoints(fileNames{i});                    
                end
                
                if isequal(boardSize, this.BoardSize)
                    this.addOneBoard(fileNames(:, i), points);
                else
                    this.LastNonDetectedPathNames(:, end+1) = fileNames(:, i);
                end
                waitBar.update();
            end
            
            this.generateIcons();
        end

        %------------------------------------------------------------------
        function board = getBoard(this, boardIndex)
            board.boardSize = this.BoardSize;
            board.fileName = this.FullPathNames(:, boardIndex);
            board.label = this.BoardLabels{boardIndex};
            board.detectedPoints = this.BoardPoints(:,:,boardIndex, :);
        end
            
        %------------------------------------------------------------------
        function removeBoard(this, boardIndex)

            this.BoardLabels(boardIndex)   = [];
            this.BoardIcons(boardIndex)    = [];
            this.FullPathNames(:, boardIndex) = [];
            this.BoardPoints(:,:,boardIndex, :) = [];

            this.NumBoards = this.NumBoards - length(boardIndex);
        end
            
        %------------------------------------------------------------------
        function reset(this)
            this.FullPathNames = [];
            this.LastNonDetectedPathNames = {};
            this.BoardSize = [];
            
            this.BoardPoints = [];
            this.WorldPoints = [];
            
            this.BoardLabels = {};
            this.BoardIcons = [];
            
            this.NumBoards = 0;
        end

        %------------------------------------------------------------------
        % This method should be called after the BoardSet is loaded from a
        % MAT file to check that all the images can be found at their
        % specified locations
        %------------------------------------------------------------------
        function checkImagePaths(this, currentSessionFilePath,...
                atSavingTimeFullSessionFileName)
            
            % verify that all the images are present; adjust path if
            % necessary
            for i=1:numel(this.FullPathNames)
                if ~exist(this.FullPathNames{i},'file')
                    
                    this.FullPathNames{i} = vision.internal.uitools.tryToAdjustPath(...
                        this.FullPathNames{i}, currentSessionFilePath, ...
                        atSavingTimeFullSessionFileName);
                    
                end
            end            
        end
        
    end % public methods
    
    %----------------------------------------------------------------------
    methods (Access=private)

        function label = makeLabel(this, fileNames)
            [~,fname, ext] = fileparts(fileNames{1, 1});
            fileName1 = [fname, ext];
                                      
            if this.IsStereo
                [~,fname, ext] = fileparts(fileNames{2, 1});
                fileName2 = [fname, ext];
                label = [fileName1, ' & ', fileName2];
            else
                label = fileName1;
            end
        end
                     
        %------------------------------------------------------------------
        % checks image size consistency
        function checkImageSizes(this, fileNames)
            
            isBrandNewSession = (this.NumBoards == 0);
            
            % get base image size
            if isBrandNewSession
                % use the very first image
                imInfoBase = imfinfo(fileNames{1});
            else
                % use an already loaded image
                imInfoBase = imfinfo(this.FullPathNames{1});
            end
            
            
            for i=1:numel(fileNames)
                imInfo = imfinfo(fileNames{i});
                
                if (imInfoBase.Width ~= imInfo.Width) || ...
                        (imInfoBase.Height ~= imInfo.Height)
                    % issue an error message
                    error(message('vision:caltool:imageSizeInconsistent'));
                end                
            end
            
        end                
        
        %------------------------------------------------------------------
        function addOneBoard(this, fileName, points)
            % for a single camera fileName is a cell array of 1 element
            % for a stereo camera fileName is a cell array of 2 elements
            this.BoardPoints(:, :, end+1, :) = points;
            this.FullPathNames(:, end+1) = fileName;

            this.BoardLabels{end+1} = makeLabel(this, fileName);
            this.NumBoards = this.NumBoards + 1;
        end
        
        %------------------------------------------------------------------
        function rollback(this, numBoardsToKeep)
            this.FullPathNames = this.FullPathNames(1:numBoardsToKeep);
            this.BoardPoints = this.BoardPoints(:, :, 1:numBoardsToKeep);
            this.BoardLabels = this.BoardLabels(1:numBoardsToKeep);
            this.BoardIcons = this.BoardIcons(1:numBoardsToKeep);
            this.NumBoards = numBoardsToKeep;
        end
        
        %------------------------------------------------------------------
        function tf = isDuplicateFileName(this, fileName)
            tf = false;
            if any(strcmp(fileName{1}, this.FullPathNames(1, :)))
                tf = true;
                return;
            end
            
            if this.IsStereo && any(strcmp(fileName{2}, this.FullPathNames(2, :)))
                tf = true;
                return;
            end
        end
        
        %------------------------------------------------------------------
        function delIdx = detectPointsForNewSession(this)
            if this.IsStereo
                [boardPoints, boardSize, goodBoardIdx, userCanceled] = ...
                    detectCheckerboardPoints(this.FullPathNames(1, :), ...
                    this.FullPathNames(2, :), 'ShowProgressBar', true);
            else
                [boardPoints, boardSize, goodBoardIdx, userCanceled] = ...
                    detectCheckerboardPoints(this.FullPathNames, 'ShowProgressBar', true);
            end
            
            if userCanceled
                error(message('vision:uitools:LoadingCanceledByUser'));
            end
            
            if isempty(boardPoints)
                error(message('vision:caltool:zeroBoards'));
            end
            
            delIdx = ~goodBoardIdx;
            this.BoardPoints = boardPoints;
            this.BoardSize = boardSize;
        end
        
        %------------------------------------------------------------------
        function deleteRejectedBoards(this, delIdx)
            % store file names of the images where boards were not
            % detected; this is used for reporting
            this.LastNonDetectedPathNames = this.FullPathNames(:, delIdx);
            
            this.NumBoards = size(this.BoardPoints, 3);
            this.BoardLabels(delIdx)   = [];
            this.FullPathNames(:, delIdx) = [];
        end
        
        %------------------------------------------------------------------
        function generateIcons(this)
            thumbnailHeight = 72;
            for i = 1:this.NumBoards
                if size(this.FullPathNames, 1) == 1
                    im = imread(this.FullPathNames{i});
                    im = imresize(im, [thumbnailHeight, NaN]);
                else
                    im1 = imread(this.FullPathNames{1, i});
                    im2 = imread(this.FullPathNames{2, i});
                    im = vision.internal.calibration.tool.fuseWithSeparator(...
                        imresize(im1, [thumbnailHeight, NaN]), ...
                        imresize(im2, [thumbnailHeight, NaN]));
                end
                
                javaImage = im2java2d(im);
                icon = javax.swing.ImageIcon(javaImage);
                icon.setDescription(this.BoardLabels(i));
                
                this.BoardIcons{i} = icon;
            end
        end        
        
    end
    
    %----------------------------------------------------------------------
    % saveobj and loadobj are implemented to ensure compatibility across
    % releases even if architecture of BoardSet class changes
    methods (Hidden)
       
        function thisOut = saveobj(this)
            
            thisOut = this;            
        end
        
    end
    
    %----------------------------------------------------------------------
    methods (Static, Hidden)
       
        function thisOut = loadobj(this)

            thisOut = this;            
        end
        
    end % methods(static, hidden)
    
end