gusucode.com > vision工具箱matlab源码程序 > vision/insertMarker.m
function RGB = insertMarker(I, position, varargin) %insertMarker Insert markers in image or video stream. % This function marks points in images with a specified marker. The % markers are drawn by overwriting pixel values. You can use it with % either a grayscale or truecolor image input. % % RGB = insertMarker(I, POSITION) returns a truecolor image with inserted % plus markers. The input image, I, can be either a truecolor or grayscale % image. The input POSITION can be either an M-by-2 matrix of M number of % [x y] pairs or a cornerPoints object. The center positions for the % markers are defined by either the [x y] pairs of the matrix or by the % POSITION.Location property of the cornerPoints object. % % RGB = insertMarker(I, POSITION, MARKER) returns a truecolor image % marked with MARKER. MARKER is a string that specifies marker type. It % can be full text or corresponding symbol as shown in parentheses: % 'circle' (or 'o'), 'x-mark' (or 'x'), 'plus' (or '+'), 'star' (or '*'), % 'square' (or 's') % Default marker: 'plus' % % RGB = insertMarker(...,'Name',Value,...) specifies additional name-value % pair arguments described below: % % 'Size' Specifies the size of the marker, in pixels. It's a % scalar with value greater than or equal to 1. % % Default: 3 % % 'Color' Defines marker's color. It can be specified as: % - a 'color' string or an [R, G, B] vector defining a % color for all markers, or % - a cell array of M strings or an M-by-3 matrix of % RGB values for each marker % % RGB values must be in the range of the image data type. % % Supported color strings are: 'blue', 'green', 'red', % 'cyan', 'magenta', 'yellow', 'black', 'white' % % Default: 'green' % % Class Support % ------------- % The class of input I can be uint8, uint16, int16, double, single. Output % RGB matches the class of I. % % Example: % -------- % I = imread('peppers.png'); % % % draw plus('+') % RGB = insertMarker(I, [147 279]); % % % draw four x-marks % pos = [120 248;195 246;195 312;120 312]; % color = {'red', 'white', 'green', 'magenta'}; % RGB = insertMarker(RGB, pos, 'x', 'color', color, 'size', 10); % % % show output % imshow(RGB); % % See also insertShape, insertObjectAnnotation, insertText, cornerPoints %#codegen %#ok<*EMCLS> %#ok<*EMCA> %% == Parse inputs and validate == checkNumArgin(I, position, varargin{:}); [tmpRGB, position, markerIdx, markerSize, color, isEmpty]= ... validateAndParseInputs(I, position, varargin{:}); % handle empty I or empty position if isEmpty RGB = tmpRGB; return; end %% == Setup System Objects == dtClass = coder.internal.const(class(I)); h_MarkerInserter = getSystemObjects(markerIdx, dtClass, markerSize, ... tmpRGB, position,color); %% == Output == % insert marker tuneMarkersize(h_MarkerInserter, markerSize); RGB = h_MarkerInserter.step(tmpRGB, position, color); %========================================================================== function checkNumArgin(varargin) if (isSimMode()) narginchk(2,7); else eml_lib_assert(nargin >= 2 && nargin <= 7, ... 'vision:insertMarker:NotEnoughArgs', 'Not enough input arguments.'); end %========================================================================== function flag = isSimMode() flag = isempty(coder.target); %========================================================================== % Parse inputs and validate %========================================================================== function [RGB, position, markerIdx, markerSize, color, isEmpty] = ... validateAndParseInputs(I, position, varargin) %--input image-- checkImage(I); RGB = convert2RGB(I); inpClass = coder.internal.const(class(I)); %--position-- % position data type does not depend on input data type % (input numeric or a cornerPoints object, output int32) if isa(position,'cornerPoints'); errIf0(~isSimMode(), 'vision:insertMarker:NoCodegenForCP'); position = position.Location; end validateattributes(position, {'numeric'}, ... {'real','nonsparse', '2d', 'finite', 'size', [NaN 2]}, ... 'insertMarker','POSITION', 2); position = int32(position); numRowsPos = size(position, 1); %--isEmpty-- isEmpty = anyEmpty(I, position); if isEmpty markerIdx = IDX_PLUS(); markerSize = 3; % not used color = ones(1,3, inpClass); % not used else %--other optional parameters-- [markerIdx, markerSize, tmpColor] = ... validateAndParseOptInputs(inpClass,varargin{:}); crossCheckInputs(numRowsPos, tmpColor); color = getColorMatrix(inpClass, numRowsPos, tmpColor); end %========================================================================== function isAnyEmpty = anyEmpty(I, position) % for fixS, check max size % for varS, check run-time size if isSimMode() isAnyEmpty = isempty(I) || isempty(position); else isAnyEmpty = false; end %========================================================================== function [markerIdx, markerSize, color] = ... validateAndParseOptInputs(inpClass,varargin) % Validate and parse optional inputs defaults = getDefaultParameters(inpClass); if nargin>1 % varargin{:} is non-empty if isSimMode() [markerIdx, markerSize, color] = ... validateAndParseOptInputs_sim(defaults,varargin{:}); else [markerIdx, markerSize, color] = ... validateAndParseOptInputs_cg(defaults,varargin{:}); end else % varargin{:} is empty (no name-value pair) markerIdx = defaults.MarkerIdx; markerSize = defaults.Size; color = defaults.Color; end %========================================================================== function [markerIdx, markerSize, color] = ... validateAndParseOptInputs_sim(defaults,varargin) % varargin must be non-empty parser = inputParser; parser.CaseSensitive = false; parser.FunctionName = 'insertMarker'; parser.addOptional('Marker', defaults.Marker, @checkMarker);% not a pv pair parser.addParameter('Size', defaults.Size, @checkMarkerSize); parser.addParameter('Color', defaults.Color); %Parse input parser.parse(varargin{:}); marker = checkAndReturnMarker(parser.Results.Marker); markerIdx = getMarkerIdx(marker); markerSize = double(parser.Results.Size); color = checkColor(parser.Results.Color, 'Color'); %========================================================================== function [markerIdx, markerSize, color] = ... validateAndParseOptInputs_cg(defaults,varargin) % varargin must be non-empty defaultsNoVal = getDefaultParametersNoVal(); properties = getEmlParserProperties(); % varargin may contain optional param (marker) and PV pair len = length(varargin); % check if varargin{1} is marker if (len==1) ||(len==3) || (len==5) % 1st_arg = marker firstArg = varargin{1}; % make sure that marker is constant (e.g. coder.Constant('Plus')) eml_invariant(eml_is_const(firstArg),... eml_message('vision:insertMarker:markerNonConst')); tmpMarker = checkAndReturnMarker(firstArg); markerIdx = getMarkerIdx(tmpMarker); pvPairStartIdx = 2; % varargin{2:end} must be PV pair else % len is expected to be even numbered; if odd numbered, it will be a % bad inputs arg and will be caught using numarg check or in the % following parsing stage markerIdx = IDX_PLUS(); pvPairStartIdx = 1; end optarg = eml_parse_parameter_inputs(defaultsNoVal, properties, ... varargin{pvPairStartIdx:end}); % opacity and smoothEdges (i.e., useAntiAliasing) are input mask params % (not from port); that's why convert these to eml_const at parsing stage markerSize = tolower(eml_get_parameter_value( ... optarg.Size, defaults.Size, varargin{pvPairStartIdx:end})); color = tolower(eml_get_parameter_value(optarg.Color, ... defaults.Color, varargin{pvPairStartIdx:end})); checkMarkerSize(markerSize); color = checkColor(color, 'Color'); %========================================================================== function str = tolower(str) % convert a string to lower case if isSimMode() str = lower(str); else str = eml_tolower(str); end %========================================================================== function checkImage(I) % Validate input image validateattributes(I,{'uint8', 'uint16', 'int16', 'double', 'single'}, ... {'real','nonsparse'}, 'insertMarker', 'I', 1) % input image must be 2d or 3d (with 3 planes) errCond = (ndims(I) > 3) || ((size(I,3) ~= 1) && (size(I,3) ~= 3)); errIf0(errCond, 'vision:dims:imageNot2DorRGB'); %========================================================================== function tf = checkMarker(marker) % Validate 'MARKER' checkAndReturnMarker(marker); tf = true; %========================================================================== function markerOut = checkAndReturnMarker(marker) % Validate 'MARKER' and output markerOut = validatestring(marker,{'circle','o', ... 'x-mark','x' ... 'plus','+', ... 'star','*', ... 'square','s'},'insertMarker','MARKER'); %========================================================================== function tf = checkMarkerSize(markerSize) % Validate 'MarkerSize' validateattributes(markerSize, {'numeric'}, ... {'nonsparse', 'integer', 'scalar', 'real', 'positive'}, ... 'insertMarker', 'Size'); tf = true; %========================================================================== function crossCheckInputs(numRowsPos, color) % Cross validate inputs numColors = getNumColors(color); errCond = (numColors ~= 1) && (numRowsPos ~= numColors); errIf0(errCond, 'vision:insertMarker:invalidNumPosNumColor'); %========================================================================== function colorOut = getColorMatrix(inpClass, numMarkers, color) colorRGB = colorRGBValue(color, inpClass); if (size(colorRGB, 1)==1) colorOut = repmat(colorRGB, [numMarkers 1]); else colorOut = colorRGB; end %========================================================================== function numColors = getNumColors(color) % Get number of colors numColors = 1; if isnumeric(color) numColors = size(color,1); elseif iscell(color) % if color='red', color is converted to cell earlier numColors = length(color); end %========================================================================== function defaults = getDefaultParameters(inpClass) % Get default values for optional parameters % default color 'green' switch inpClass case {'double', 'single'} green = [0 1 0]; case 'uint8' green = [0 255 0]; case 'uint16' green = [0 65535 0]; case 'int16' green = [-32768 32767 -32768]; end defaults = struct(... 'Marker', 'Plus', ... 'MarkerIdx', IDX_PLUS(), ... 'Size', 3, ... 'Color', green); %========================================================================== function defaultsNoVal = getDefaultParametersNoVal() defaultsNoVal = struct(... 'Marker', uint32(0), ... 'Size', uint32(0), ... 'Color', uint32(0)); %========================================================================== function properties = getEmlParserProperties() properties = struct( ... 'CaseSensitivity', false, ... 'StructExpand', true, ... 'PartialMatching', false); %========================================================================== function colorOut = checkColor(color, paramName) % Validate 'Color' % Validate color if isnumeric(color) % must have 6 columns validateattributes(color, ... {'uint8','uint16','int16','double','single'},... {'real','nonsparse','nonnan', 'finite', '2d', 'size', [NaN 3]}, ... 'insertMarker', paramName); colorOut = color; else if ~isSimMode() % codegen does not support cell array errIf0(~isnumeric(color), 'vision:insertMarker:colorNotNumeric'); colorOut = color; else if ischar(color) colorCell = {color}; else validateattributes(color, {'cell'}, {}, 'insertMarker', 'Color'); colorCell = color; end supportedColorStr = {'blue','green','red','cyan','magenta', ... 'yellow','black','white'}; numCells = length(colorCell); colorOut = cell(1, numCells); for ii=1:numCells colorOut{ii} = validatestring(colorCell{ii}, ... supportedColorStr, 'insertMarker', paramName); end end end %========================================================================== function sizeOfCache = getCacheSizeForMarkerInserter() % Marker inserter object needs to be created for the following % parameters: % input data type: double,single,uint8,uint16,int16 % marker: circle,x-mark,plus,star,square numInDTypes = 5; numMarkers = 5; sizeOfCache = [numInDTypes numMarkers]; %========================================================================== function inRGB = convert2RGB(I) if ismatrix(I) inRGB = cat(3, I , I, I); else inRGB = I; end %========================================================================== function outColor = colorRGBValue(inColor, inpClass) if isnumeric(inColor) outColor = cast(inColor, inpClass); else if iscell(inColor) colorCell = inColor; else colorCell = {inColor}; end numColors = length(colorCell); outColor = zeros(numColors, 3, inpClass); for ii=1:numColors supportedColorStr = {'blue','green','red','cyan','magenta','yellow',... 'black','white'}; % http://www.mathworks.com/help/techdoc/ref/colorspec.html colorValuesFloat = [0 0 1;0 1 0;1 0 0;0 1 1;1 0 1;1 1 0;0 0 0;1 1 1]; idx = strcmp(colorCell{ii}, supportedColorStr); switch inpClass case {'double', 'single'} outColor(ii, :) = colorValuesFloat(idx, :); case {'uint8', 'uint16'} colorValuesUint = colorValuesFloat*double(intmax(inpClass)); outColor(ii, :) = colorValuesUint(idx, :); case 'int16' colorValuesInt16 = im2int16(colorValuesFloat); outColor(ii, :) = colorValuesInt16(idx, :); end end end %========================================================================== % Setup System Objects %========================================================================== function h_MarkerInserter = getSystemObjects(markerIdx,inpClass, markerSize, ... rgb, position, color) if isSimMode() h_MarkerInserter = getSystemObjects_sim(markerIdx,inpClass, markerSize); else h_MarkerInserter = getSystemObjects_cg(markerIdx,inpClass, ... rgb, position, color); end %========================================================================== function h_MarkerInserter = getSystemObjects_sim(markerIdx,inpClass,markerSize) persistent cache % cache for storing System Objects if isempty(cache) cache.markerInserterObjects = cell(getCacheSizeForMarkerInserter()); end inDTypeIdx = getDTypeIdx(inpClass); if isempty(cache.markerInserterObjects{inDTypeIdx,markerIdx}) marker = getMarkerNameFromIdx(markerIdx); h_MarkerInserter = vision.MarkerInserter('Shape', marker, ... 'BorderColorSource','Input port', 'Size', markerSize); % cache the MarkerInserter object in cell array cache.markerInserterObjects{inDTypeIdx,markerIdx}= h_MarkerInserter; else % point to the existing object h_MarkerInserter = cache.markerInserterObjects{inDTypeIdx,markerIdx}; end %========================================================================== function h_MarkerInserter = getSystemObjects_cg(markerIdx,inpClass, ... rgb, position, color) inDTypeIdx = coder.internal.const(getDTypeIdx(inpClass)); h_MarkerInserter = vision.internal.textngraphics.createMarkerInserter_cg ... (inDTypeIdx, markerIdx, rgb, position, color); %========================================================================== function dtIdx = getDTypeIdx(dtClass) switch dtClass case 'double', dtIdx = 1; case 'single', dtIdx = 2; case 'uint8', dtIdx = 3; case 'uint16', dtIdx = 4; case 'int16', dtIdx = 5; end %========================================================================== function marker = getMarkerNameFromIdx(markerIdx) marker = 'Plus'; switch (markerIdx) case 1 % 'circle' marker = 'Circle'; case 2 % 'x-mark' marker = 'X-mark'; case 3 % 'plus' marker = 'Plus'; case 4 % 'star' marker = 'Star'; case 5 % 'square' marker = 'Square'; end %========================================================================== function markerIdx = getMarkerIdx(marker) % marker is always in lower-case letters (from validatestring(marker, ...)) markerIdx = IDX_PLUS(); if (strcmp(marker,'circle') || strcmp(marker,'o')) markerIdx = IDX_CIRCLE(); elseif (strcmp(marker,'x-mark') || strcmp(marker,'x')) markerIdx = IDX_XMARK(); elseif (strcmp(marker,'plus') || strcmp(marker,'+')) markerIdx = IDX_PLUS(); elseif (strcmp(marker,'star') || strcmp(marker,'*')) markerIdx = IDX_STAR(); elseif (strcmp(marker,'square') || strcmp(marker,'s')) markerIdx = IDX_SQUARE(); end coder.internal.prefer_const(markerIdx); %========================================================================== function markerIdx = IDX_CIRCLE() coder.inline('always'); markerIdx = int8(1); %========================================================================== function markerIdx = IDX_XMARK() coder.inline('always'); markerIdx = int8(2); %========================================================================== function markerIdx = IDX_PLUS() coder.inline('always'); markerIdx = int8(3); %========================================================================== function markerIdx = IDX_STAR() coder.inline('always'); markerIdx = int8(4); %========================================================================== function markerIdx = IDX_SQUARE() coder.inline('always'); markerIdx = int8(5); %========================================================================== function tuneMarkersize(h_MarkerInserter, markerSize) if (markerSize ~= h_MarkerInserter.Size) h_MarkerInserter.Size = markerSize; end %========================================================================== function errIf0(condition, msgID) coder.internal.errorIf(condition, msgID);