【图像分割】图像检测(分割、特征提取)、各种特征(面积等)的测量和过滤(Matlab代码实现)

news2024/11/26 23:39:22

 💥💥💞💞欢迎来到本博客❤️❤️💥💥

🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。

⛳️座右铭:行百里者,半于九十。

📋📋📋本文目录如下:🎁🎁🎁

目录

💥1 概述

📚2 运行结果

🎉3 参考文献

🌈4 Matlab代码实现


💥1 概述

【图像分割】图像检测(分割、特征提取)、各种特征(面积等)的测量和过滤

本文提供了一个适合初学者的教程,旨在演示图像检测(分割、特征提取)以及各种特征(如面积)的测量和过滤(只提取某些对象)。

首先,该教程介绍了如何找到图像中的所有对象(硬币),然后根据指定的直径过滤结果,筛选出特定直径的对象。通过一个简单的示例,展示了阈值处理、标记和区域属性的基本概念。

对于那些刚开始接触 MATLAB 图像处理功能的同学来说,这个教程是一个很好的起点。在他们深入学习更复杂的算法之前,可以通过这个教程加深对基本概念和技术的理解。

为了完成这个教程,需要安装图像处理工具箱,因为它演示了该工具箱提供的某些功能。同时,教程使用了工具箱自带的一个名为“硬币”的示例图像作为演示对象。

该教程的优点在于,它提供了一种直观和实用的方法,帮助初学者理解如何使用 MATLAB 对图像进行处理和分析。通过学习如何进行图像分割、特征提取和过滤,读者将受益于这些基本概念,并能够应用它们解决更为复杂的图像处理问题。这个教程对于那些有兴趣进一步探索图像处理领域的学生、研究人员和工程师来说,都是一个很好的起点。

📚2 运行结果

部分代码:

% Read in a standard MATLAB demo image of coins (US nickles and dimes, which are 5 cent and 10 cent coins).  This image ships with MATLAB.
baseFileName = 'coins.png';
folder = fileparts(which(baseFileName)); % Determine where demo folder is (works with all versions).
fullFileName = fullfile(folder, baseFileName);
fprintf('Full File Name = "%s".\n', fullFileName);
if ~exist(fullFileName, 'file')
	% It doesn't exist in the current folder.
	% Look on the search path.
	if ~exist(baseFileName, 'file')
		% It doesn't exist on the search path either.
		% Alert user that we can't find the image.
		warningMessage = sprintf('Error: the input image file\n%s\nwas not found.\nClick OK to exit the demo.', fullFileName);
		uiwait(warndlg(warningMessage));
		fprintf(1, 'Finished running BlobsDemo.m.\n');
		return;
	end
	% Found it on the search path.  Construct the file name.
	fullFileName = baseFileName; % Note: don't prepend the folder.
end
% If we get here, we should have found the image file.
originalImage = imread(fullFileName);
% Check to make sure that it is grayscale, just in case the user substituted their own image.
[rows, columns, numberOfColorChannels] = size(originalImage);
if numberOfColorChannels > 1
	promptMessage = sprintf('Your image file has %d color channels.\nThis demo was designed for grayscale images.\nDo you want me to convert it to grayscale for you so you can continue?', numberOfColorChannels);
	button = questdlg(promptMessage, 'Continue', 'Convert and Continue', 'Cancel', 'Convert and Continue');
	if strcmp(button, 'Cancel')
		fprintf(1, 'Finished running BlobsDemo.m.\n');
		return;
	end
	% Do the conversion using standard book formula
	originalImage = rgb2gray(originalImage);
end

% Display the grayscale image.
subplot(3, 3, 1);
imshow(originalImage);
% Maximize the figure window.
hFig1 = gcf;
hFig1.Units = 'normalized';
hFig1.WindowState = 'maximized'; % Go to full screen.
hFig1.NumberTitle = 'off'; % Get rid of "Figure 1"
hFig1.Name = 'Demo by Image Analyst'; % Put this into title bar.
% Force it to display RIGHT NOW (otherwise it might not display until it's all done, unless you've stopped at a breakpoint.)
drawnow;
caption = sprintf('Original "coins" image showing\n6 nickels (the larger coins) and 4 dimes (the smaller coins).');
title(caption, 'FontSize', captionFontSize);
axis('on', 'image'); % Make sure image is not artificially stretched because of screen's aspect ratio.

% Just for fun, let's get its histogram and display it.
[pixelCount, grayLevels] = imhist(originalImage);
subplot(3, 3, 2);
bar(pixelCount);
title('Histogram of original image', 'FontSize', captionFontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
grid on;

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Threshold the image to get a binary image (only 0's and 1's) of class "logical."
% Method #1: using im2bw()
%   normalizedThresholdValue = 0.4; % In range 0 to 1.
%   thresholdValue = normalizedThresholdValue * max(max(originalImage)); % Gray Levels.
%   binaryImage = im2bw(originalImage, normalizedThresholdValue);       % One way to threshold to binary
% Method #2: using a logical operation.
thresholdValue = 100;
binaryImage = originalImage > thresholdValue; % Bright objects will be chosen if you use >.
% ========== IMPORTANT OPTION ============================================================
% Use < if you want to find dark objects instead of bright objects.
%   binaryImage = originalImage < thresholdValue; % Dark objects will be chosen if you use <.

% Do a "hole fill" to get rid of any background pixels or "holes" inside the blobs.
binaryImage = imfill(binaryImage, 'holes');

% Show the threshold as a vertical red bar on the histogram.
hold on;
maxYValue = ylim;
line([thresholdValue, thresholdValue], maxYValue, 'Color', 'r');
% Place a text label on the bar chart showing the threshold.
annotationText = sprintf('Thresholded at %d gray levels', thresholdValue);
% For text(), the x and y need to be of the data class "double" so let's cast both to double.
text(double(thresholdValue + 5), double(0.5 * maxYValue(2)), annotationText, 'FontSize', 10, 'Color', [0 .5 0]);
text(double(thresholdValue - 70), double(0.94 * maxYValue(2)), 'Background', 'FontSize', 10, 'Color', [0 0 .5]);
text(double(thresholdValue + 50), double(0.94 * maxYValue(2)), 'Foreground', 'FontSize', 10, 'Color', [0 0 .5]);

% Display the binary image.
subplot(3, 3, 3);
imshow(binaryImage);
title('Binary Image, obtained by thresholding', 'FontSize', captionFontSize);

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Identify individual blobs by seeing which pixels are connected to each other.  This is called "Connected Components Labeling".
% Each group of connected pixels will be given a label, a number, to identify it and distinguish it from the other blobs.
% Do connected components labeling with either bwlabel() or bwconncomp().
[labeledImage, numberOfBlobs] = bwlabel(binaryImage, 8);     % Label each blob so we can make measurements of it
% labeledImage is an integer-valued image where all pixels in the blobs have values of 1, or 2, or 3, or ... etc.
subplot(3, 3, 4);
imshow(labeledImage, []);  % Show the gray scale image.
title('Labeled Image, from bwlabel()', 'FontSize', captionFontSize);
drawnow;

% Let's assign each blob a different color to visually show the user the distinct blobs.
coloredLabels = label2rgb (labeledImage, 'hsv', 'k', 'shuffle'); % pseudo random color labels
% coloredLabels is an RGB image.  We could have applied a colormap instead (but only with R2014b and later)
subplot(3, 3, 5);
imshow(coloredLabels);
axis image; % Make sure image is not artificially stretched because of screen's aspect ratio.
caption = sprintf('Pseudo colored labels, from label2rgb().\nBlobs are numbered from top to bottom, then from left to right.');
title(caption, 'FontSize', captionFontSize);

%======================================================================================================================================================
% MAIN PART IS RIGHT HERE!!!
% Get all the blob properties.
props = regionprops(labeledImage, originalImage, 'all');
% Or, if you want, you can ask for only a few specific measurements.  This will be faster since we don't have to compute everything.
% props = regionprops(labeledImage, originalImage, 'MeanIntensity', 'Area', 'Perimeter', 'Centroid', 'EquivDiameter');
numberOfBlobs = numel(props); % Will be the same as we got earlier from bwlabel().
%======================================================================================================================================================

%------------------------------------------------------------------------------------------------------------------------------------------------------
% PLOT BOUNDARIES.
% Plot the borders of all the coins on the original grayscale image using the coordinates returned by bwboundaries().
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
subplot(3, 3, 6);
imshow(originalImage);
title('Outlines, from bwboundaries()', 'FontSize', captionFontSize);
axis('on', 'image'); % Make sure image is not artificially stretched because of screen's aspect ratio.
% Here is where we actually get the boundaries for each blob.
boundaries = bwboundaries(binaryImage); % Note: this is a cell array with several boundaries -- one boundary per cell.
% boundaries is a cell array - one cell for each blob.
% In each cell is an N-by-2 list of coordinates in a (row, column) format.  Note: NOT (x,y).
% Column 1 is rows, or y.    Column 2 is columns, or x.
numberOfBoundaries = size(boundaries, 1); % Count the boundaries so we can use it in our for loop
% Here is where we actually plot the boundaries of each blob in the overlay.
hold on; % Don't let boundaries blow away the displayed image.
for k = 1 : numberOfBoundaries
	thisBoundary = boundaries{k}; % Get boundary for this specific blob.
	x = thisBoundary(:,2); % Column 2 is the columns, which is x.
	y = thisBoundary(:,1); % Column 1 is the rows, which is x.
	plot(x, y, 'r-', 'LineWidth', 2); % Plot boundary in red.
end
hold off;

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Print out the measurements to the command window, and display blob numbers on the image.
textFontSize = 14;	% Used to control size of "blob number" labels put atop the image.
% Print header line in the command window.
fprintf(1,'Blob #      Mean Intensity  Area   Perimeter    Centroid       Diameter\n');
% Extract all the mean diameters into an array.
% The "diameter" is the "Equivalent Circular Diameter", which is the diameter of a circle with the same number of pixels as the blob.
% Enclosing in brackets is a nice trick to concatenate all the values from all the structure fields (every structure in the props structure array).
blobECD = [props.EquivDiameter];
% Loop over all blobs printing their measurements to the command window.
for k = 1 : numberOfBlobs           % Loop through all blobs.
	% Find the individual measurements of each blob.  They are field of each structure in the props strucutre array.
	% You could use the bracket trick (like with blobECD above) OR you can get the value from the field of this particular structure.
	% I'm showing you both ways and you can use the way you like best.
	meanGL = props(k).MeanIntensity;		% Get average intensity.
	blobArea = props(k).Area;				% Get area.
	blobPerimeter = props(k).Perimeter;		% Get perimeter.
	blobCentroid = props(k).Centroid;		% Get centroid one at a time

	% Now do the printing of this blob's measurements to the command window.
	fprintf(1,'#%2d %17.1f %11.1f %8.1f %8.1f %8.1f % 8.1f\n', k, meanGL, blobArea, blobPerimeter, blobCentroid, blobECD(k));
	% Put the "blob number" labels on the grayscale image that is showing the red boundaries on it.
	text(blobCentroid(1), blobCentroid(2), num2str(k), 'FontSize', textFontSize, 'FontWeight', 'Bold', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');
end

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Now, I'll show you a way to get centroids into an N -by-2 array directly from props,
% rather than accessing them as a field of the props strcuture array.
% We can get the centroids of ALL the blobs into 2 arrays,
% one for the centroid x values and one for the centroid y values.
allBlobCentroids = vertcat(props.Centroid);		% A 10 row by 2 column array of (x,y) centroid coordinates.
centroidsX = allBlobCentroids(:, 1);			% Extract out the centroid x values into their own vector.
centroidsY = allBlobCentroids(:, 2);			% Extract out the centroid y values into their own vector.
% Put the labels on the rgb labeled image also.
subplot(3, 3, 5);
for k = 1 : numberOfBlobs           % Loop through all blobs.
	% Place the blob label number at the centroid of the blob.
	text(centroidsX(k), centroidsY(k), num2str(k), 'FontSize', textFontSize, 'FontWeight', 'Bold', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');
end

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Now I'll demonstrate how to select certain blobs based using the ismember() function and extract them into new subimages.
% Let's say that we wanted to find only those blobs
% with an intensity between 150 and 220 and an area less than 2000 pixels.
% This would give us the three brightest dimes (the smaller coin type).
allBlobIntensities = [props.MeanIntensity];
allBlobAreas = [props.Area];
subplot(3, 3, 7);
histogram(allBlobAreas);
% Get a list of the blobs that meet our criteria and we need to keep.
% These will be logical indices - lists of true or false depending on whether the feature meets the criteria or not.
% for example [1, 0, 0, 1, 1, 0, 1, .....].  Elements 1, 4, 5, 7, ... are true, others are false.
allowableIntensityIndexes = (allBlobIntensities > 150) & (allBlobIntensities < 220);
allowableAreaIndexes = allBlobAreas < 2000; % Take the small objects.
% Now let's get actual indexes, rather than logical indexes, of the  features that meet the criteria.
% for example [1, 4, 5, 7, .....] to continue using the example from above.
keeperIndexes = find(allowableIntensityIndexes & allowableAreaIndexes);
% Extract only those blobs that meet our criteria, and
% eliminate those blobs that don't meet our criteria.
% Note how we use ismember() to do this.  Result will be an image - the same as labeledImage but with only the blobs listed in keeperIndexes in it.
keeperBlobsImage = ismember(labeledImage, keeperIndexes);
% Re-label with only the keeper blobs kept.
labeledDimeImage = bwlabel(keeperBlobsImage, 8);     % Label each blob so we can make measurements of it
% Now we're done.  We have a labeled image of blobs that meet our specified criteria.
subplot(3, 3, 7);
imshow(labeledDimeImage, []);
axis image;
title('"Keeper" blobs (3 brightest dimes in a re-labeled image)', 'FontSize', captionFontSize);
elapsedTime = toc;
fprintf('Blob detection and measurement took %.3f seconds.\n', elapsedTime)

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Plot the centroids in the overlay above the original image in the upper left axes.
% Dimes will have a red cross, nickels will have a blue X.
message = sprintf('Now I will plot the centroids over the original image in the upper left.\nPlease look at the upper left image.');
reply = questdlg(message, 'Plot Centroids?', 'OK', 'Cancel', 'Cancel');
% Note: reply will = '' for Upper right X, 'OK' for OK, and 'Cancel' for Cancel.
if strcmpi(reply, 'Cancel')
	return;
end
subplot(3, 3, 1);
hold on; % Don't blow away image.
for k = 1 : numberOfBlobs           % Loop through all keeper blobs.
	% Identify if blob #k is a dime or nickel.
	itsADime = allBlobAreas(k) < 2200; % Dimes are small.
	if itsADime
		% Plot dimes with a red +.
		plot(centroidsX(k), centroidsY(k), 'r+', 'MarkerSize', 15, 'LineWidth', 2);
	else
		% Plot nickels with a blue x.
		plot(centroidsX(k), centroidsY(k), 'bx', 'MarkerSize', 15, 'LineWidth', 2);
	end
end

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Now use the keeper blobs as a mask on the original image so we will get a masked gray level image.
% This will keep the regions in the mask as original but erase (blacken) everything else (outside of the mask regions).
% This will let us display the original image in the regions of the keeper blobs.
maskedImageDime = originalImage; % Simply a copy at first.
maskedImageDime(~keeperBlobsImage) = 0;	% Set all non-keeper pixels to zero.
subplot(3, 3, 8);
imshow(maskedImageDime);
axis image;
title('Only the 3 brightest dimes from the original image', 'FontSize', captionFontSize);

%------------------------------------------------------------------------------------------------------------------------------------------------------
% Now let's get the nickels (the larger coin type).
keeperIndexes = find(allBlobAreas > 2000);  % Take the larger objects.
% Note how we use ismember to select the blobs that meet our criteria.  Get a binary image with only nickel regions present.
nickelBinaryImage = ismember(labeledImage, keeperIndexes);
% Let's get the nickels from the original grayscale image, with the other non-nickel pixels blackened.
% In other words, we will create a "masked" image.
maskedImageNickel = originalImage; % Simply a copy at first.
maskedImageNickel(~nickelBinaryImage) = 0;  % Set all non-nickel pixels to zero.
subplot(3, 3, 9);
imshow(maskedImageNickel, []);
axis image;
title('Only the nickels from the original image', 'FontSize', captionFontSize);

%------------------------------------------------------------------------------------------------------------------------------------------------------
% WE'RE BASICALLY DONE WITH THE DEMO NOW.
elapsedTime = toc;
% Alert user that the demo is done and give them the option to save an image.
message = sprintf('Done making measurements of the features.\n\nElapsed time = %.2f seconds.', elapsedTime);
message = sprintf('%s\n\nCheck out the figure window for the images.\nCheck out the command window for the numerical results.', message);
message = sprintf('%s\n\nDo you want to save the pseudo-colored image?', message);
reply = questdlg(message, 'Save image?', 'Yes', 'No', 'No');
% Note: reply will = '' for Upper right X, 'Yes' for Yes, and 'No' for No.
if strcmpi(reply, 'Yes')
	% Ask user for a filename.
	FilterSpec = {'*.PNG', 'PNG Images (*.png)'; '*.tif', 'TIFF images (*.tif)'; '*.*', 'All Files (*.*)'};
	DialogTitle = 'Save image file name';
	% Get the default filename.  Make sure it's in the folder where this m-file lives.
	% (If they run this file but the cd is another folder then pwd will show that folder, not this one.
	thisFile = mfilename('fullpath');
	[thisFolder, baseFileName, ext] = fileparts(thisFile);
	DefaultName = sprintf('%s/%s.tif', thisFolder, baseFileName);
	[fileName, specifiedFolder] = uiputfile(FilterSpec, DialogTitle, DefaultName);
	if fileName ~= 0
		% Parse what they actually specified.
		[folder, baseFileName, ext] = fileparts(fileName);
		% Create the full filename, making sure it has a tif filename.
		fullImageFileName = fullfile(specifiedFolder, [baseFileName '.tif']);
		% Save the labeled image as a tif image.
		imwrite(uint8(coloredLabels), fullImageFileName);
		% Just for fun, read image back into the imtool utility to demonstrate that tool.
		tifimage = imread(fullImageFileName);
		imtool(tifimage, []);
	end
end

%------------------------------------------------------------------------------------------------------------------------------------------------------
% OPTIONAL : CROP EACH COIN OUT TO A SEPARATE SUB-IMAGE ON A NEW FIGURE.
message = sprintf('Would you like to crop out each coin to individual images?');
reply = questdlg(message, 'Extract Individual Images?', 'Yes', 'No', 'Yes');
% Note: reply will = '' for Upper right X, 'Yes' for Yes, and 'No' for No.
if strcmpi(reply, 'Yes')
	% Maximize the figure window.
	hFig2 = figure;	% Create a new figure window.
	hFig2.Units = 'normalized';
	hFig2.WindowState = 'maximized'; % Go to full screen.
	hFig2.NumberTitle = 'off'; % Get rid of "Figure 1"
	hFig2.Name = 'Demo by Image Analyst'; % Put this into title bar.

	for k = 1 : numberOfBlobs		% Loop through all blobs.
		% Find the bounding box of each blob.
		thisBlobsBoundingBox = props(k).BoundingBox;  % Get list of pixels in current blob.
		% Extract out this coin into it's own image.
		subImage = imcrop(originalImage, thisBlobsBoundingBox);
		% Determine if it's a dime (small) or a nickel (large coin).
		if props(k).Area > 2200
			coinType = 'nickel';
		else
			coinType = 'dime';
		end
		% Display the image with informative caption.
		subplot(3, 4, k);
		imshow(subImage);
		caption = sprintf('Coin #%d is a %s.\nDiameter = %.1f pixels\nArea = %d pixels', ...
			k, coinType, blobECD(k), props(k).Area);
		title(caption, 'FontSize', textFontSize);
	end

	%------------------------------------------------------------------------------------------------------------------------------------------------------
	% Display the MATLAB "peaks" logo.
	logoSubplot = subplot(3, 4, 11:12);
	caption = sprintf('A MATLAB Tutorial by ImageAnalyst');
	text(0.5,1.15, caption, 'Color','r', 'FontSize', 18, 'FontWeight','b', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle') ;
	positionOfLowerRightPlot = get(logoSubplot, 'position');
	L = 40*membrane(1,25);
	logoax = axes('CameraPosition', [-193.4013, -265.1546, 220.4819],...
		'Box', 'off', ...
		'CameraTarget',[26, 26, 10], ...
		'CameraUpVector',[0, 0, 1], ...
		'CameraViewAngle',9.5, ...
		'DataAspectRatio', [1, 1, .9],...
		'Position', positionOfLowerRightPlot, ...
		'Visible','off', ...
		'XLim',[1, 51], ...
		'YLim',[1, 51], ...
		'ZLim',[-13, 40], ...
		'parent', gcf);
	axis(logoSubplot, 'off');
	s = surface(L, ...
		'EdgeColor','none', ...
		'FaceColor',[0.9, 0.2, 0.2], ...
		'FaceLighting','phong', ...
		'AmbientStrength',0.3, ...
		'DiffuseStrength',0.6, ...
		'Clipping','off',...
		'BackFaceLighting','lit', ...
		'SpecularStrength',1, ...
		'SpecularColorReflectance',1, ...
		'SpecularExponent',7, ...
		'Tag','TheMathWorksLogo', ...
		'parent',logoax);
	l1 = light('Position',[40, 100, 20], ...

% OPTIONAL : CROP EACH COIN OUT TO A SEPARATE SUB-IMAGE ON A NEW FIGURE.
message = sprintf('Would you like to crop out each coin to individual images?');
reply = questdlg(message, 'Extract Individual Images?', 'Yes', 'No', 'Yes');
% Note: reply will = '' for Upper right X, 'Yes' for Yes, and 'No' for No.
if strcmpi(reply, 'Yes')
    % Maximize the figure window.
    hFig2 = figure;    % Create a new figure window.
    hFig2.Units = 'normalized';
    hFig2.WindowState = 'maximized'; % Go to full screen.
    hFig2.NumberTitle = 'off'; % Get rid of "Figure 1"
    hFig2.Name = 'Demo by Image Analyst'; % Put this into title bar.

    for k = 1 : numberOfBlobs        % Loop through all blobs.
        % Find the bounding box of each blob.
        thisBlobsBoundingBox = props(k).BoundingBox;  % Get list of pixels in current blob.
        % Extract out this coin into it's own image.
        subImage = imcrop(originalImage, thisBlobsBoundingBox);
        % Determine if it's a dime (small) or a nickel (large coin).
        if props(k).Area > 2200
            coinType = 'nickel';
        else
            coinType = 'dime';
        end
        % Display the image with informative caption.
        subplot(3, 4, k);
        imshow(subImage);
        caption = sprintf('Coin #%d is a %s.\nDiameter = %.1f pixels\nArea = %d pixels', ...
            k, coinType, blobECD(k), props(k).Area);
        title(caption, 'FontSize', textFontSize);
    end

    %------------------------------------------------------------------------------------------------------------------------------------------------------
    % Display the MATLAB "peaks" logo.
    logoSubplot = subplot(3, 4, 11:12);
    caption = sprintf('A MATLAB Tutorial by ImageAnalyst');
    text(0.5,1.15, caption, 'Color','r', 'FontSize', 18, 'FontWeight','b', 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle') ;
    positionOfLowerRightPlot = get(logoSubplot, 'position');
    L = 40*membrane(1,25);
    logoax = axes('CameraPosition', [-193.4013, -265.1546, 220.4819],...
        'Box', 'off', ...
        'CameraTarget',[26, 26, 10], ...
        'CameraUpVector',[0, 0, 1], ...
        'CameraViewAngle',9.5, ...
        'DataAspectRatio', [1, 1, .9],...
        'Position', positionOfLowerRightPlot, ...
 

🎉3 参考文献

文章中一些内容引自网络,会注明出处或引用为参考文献,难免有未尽之处,如有不妥,请随时联系删除。

[1]马寅.基于CCD的图像特征提取与识别[D].东北大学,2012.DOI:10.7666/d.J0120301.

[2]王妞,康辉英.基于图像检测的船舶特征分割与提取优化算法[J].舰船科学技术, 2018(4X):3.DOI:CNKI:SUN:JCKX.0.2018-08-049.

[3]尹聪.彩色图像人脸检测与特征提取认证[J].信息技术与信息化, 2009.DOI:JournalArticle/5af35bd8c095d718d80b8d86.

[4]罗文辉,王三武.基于面积和结构特征的水表图像二步分割方法[J].武汉理工大学学报:信息与管理工程版, 2006, 28(5):4.DOI:10.3963/j.issn.1007-144X.2006.05.014.

🌈4 Matlab代码实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1053111.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于SSM+Vue的医院住院综合服务管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

前端最新支持四级及以下结构仿企查查、天眼查关联投资机构 股权结构 tree树形结构 控股结构

随着技术的发展&#xff0c;开发的复杂度也越来越高&#xff0c;传统开发方式将一个系统做成了整块应用&#xff0c;经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改&#xff0c;造成牵一发而动全身。通过组件化开发&#xff0c;可以有效实现单…

数据结构——堆(C语言)

本篇会解决一下几个问题&#xff1a; 1.堆是什么&#xff1f; 2.如何形成一个堆&#xff1f; 3.堆的应用场景 堆是什么&#xff1f; 堆总是一颗完全二叉树堆的某个节点总是不大于或不小于父亲节点 如图&#xff0c;在小堆中&#xff0c;父亲节点总是小于孩子节点的。 如图&a…

外包干了3个月,整个人都萎靡不振了。。。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

基于Java的美容院管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

Android 内存泄漏分析思路和案例剖析

分析思路 内存泄漏是指 Android 进程中&#xff0c;某些对象已经不再使用&#xff0c;但被一些生命周期更长的对象引用&#xff0c;导致其占用的内存资源无法被GC回收&#xff0c;内存占用不断增加的一种现象&#xff1b;内存泄漏是导致我们应用性能下降、卡顿的一种常见因素&…

ROS2 中的轻量级、自动化、受控回放

一、说明 这篇文章描述了一种在 ROS2 中实现受控重播器的轻量级方法。用以测试中将现象重新播放一遍&#xff0c;以实现调参或故障定位的目的。所有源代码都可以在这里找到。该帖子也可在此处获得。 二、问题&#xff1a;不同步重播 任何曾经认真开发过 ROS2 的人都会知道这个问…

microsoft excel 公式 计算本金 利息 月供 和总利息

//可使用 Excel 公式指导算出贷款的月还款额。 PMT(rate, nper, pv, [fv], [type])//返回根据定期固定付款和固定利率而定的投资在已知期间内的本金偿付额。 PPMT(rate, per, nper, pv, [fv], [type])//基于固定利率及等额分期付款方式&#xff0c;返回给定期数内对投资的利息…

C++ Primer----1.5类简介 章节练习

头文件 Sales_item.h #ifndef SALESITEM_H #define SALESITEM_H #include <iostream> #include <string>class Sales_item{ public:Sales_item(const std::string &book):isbn(book),units_sold(0),revenue(0.0){}Sales_item(std::istream &is){ is >&…

在macOS上从源代码构建编译Aseprite到组装成App应用(macOS上如何不开着终端窗口)

这里记录一下自己构建 Aseprite 流程。关于如何构建可能已经有很多文章写了&#xff0c;但是都没有提到一点&#xff1a;启动的时候需要点击可执行程序&#xff0c;这样是需要终端窗口一直开着的的&#xff08;如下图&#xff09;&#xff0c;关闭终端就会退出程序&#xff0c;…

MEIS —— 前端部分基本配置

项目基本配置 这篇文章我们随着上一篇文章继续往下叙述&#xff0c;主要是将element和windicss等开发配置进项目中&#xff0c;以及基本的一些页面和组件给他完成。 1. 安装element plus 运行&#xff1a; npm install element-plus --save 这里我们是按需引入(自动)&#x…

JavaSE学习--数据类型和运算符

&#x1f495;"哪里有人喜欢孤独&#xff0c;只不过更不喜欢失望。"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;JJavaSE学习--数据类型和运算符 Java程序是如何运行的&#xff1f; 一.数据类型 整型&#xff1a; 注意事项&#xff1a; 1.整型…

Android 使用Kotlin封装RecyclerView

文章目录 1.概述2.运行效果图3.代码实现3.1 扩展RecyclerView 3.2 扩展Adapter3.3 RecyclerView装饰绘制3.3.1 以图片实现分割线3.3.2 画网格线3.3.3空白的分割线3.3.4 不同方向上的分割线 3.4 使用方法 1.概述 在一个开源项目上看到了一个Android Kotlin版的RecyclerView封装…

Linux 网络编程

套接字&#xff08;Socket&#xff09;&#xff1a; 通过网络实现跨机通信 作用&#xff1a;一种文件描述符传输层的文件描述符 整个编程中&#xff0c;需要着重注意htonl/htons、ntohl/ntohs、inet_addr等 TCP的C/S实现 循环服务器模型 TCP服务器实现过程 1.创建套接字&a…

Web 中间件怎么玩?

本次主要是聊聊关于 web 中间件&#xff0c; 分为如下四个方面 什么是 web 框架中间件 为什么要使用 web 中间件 如何使用及其原理 哪些场景需要使用中间件 开门见山 web 中间件是啥 Web 框架中的中间件主要指的是在 web 请求到具体路由之前或者之后&#xff0c;会经过一个或…

MyBatis 映射文件(Mapper XML):配置与使用

MyBatis 映射文件&#xff08;Mapper XML&#xff09;&#xff1a;配置与使用 MyBatis是一个强大的Java持久化框架&#xff0c;它允许您将SQL查询、插入、更新和删除等操作与Java方法进行映射。这种映射是通过MyBatis的映射文件&#xff0c;通常称为Mapper XML文件来实现的。本…

正点原子lwIP学习笔记——MQTT协议

1. MQTT简介 MQTT是一种基于客户端服务端架构的发布/订阅模式的消息传输协议。他的设计思想是轻巧、开放、简单、规范&#xff0c;易于实现。这些特点使得他对很多场景来说都是很好的选择&#xff0c;尤其是对于受限的环境如机器与机器的通信&#xff08;M2M&#xff09;以及物…

python根据命令行参数动态导入模块或文件

需求 在命令行运行一个 python 文件&#xff0c;同时传入自定义参数&#xff1a; $ python main.py --nodeTable --actioncreate --data"{name: test2, is_sys_obj: False, encoding: UTF8,datconnlimit: -1, variables: []"希望 main.py 接收命令行参数&#xff0…

1.6.C++项目:仿mudou库实现并发服务器之channel模块的设计

项目完整版在&#xff1a; 文章目录 一、channel模块&#xff1a;事件管理Channel类实现二、提供的功能三、实现思想&#xff08;一&#xff09;功能&#xff08;二&#xff09;意义&#xff08;三&#xff09;功能设计 四、代码&#xff08;一&#xff09;框架&#xff08;二…

快速上手 Docker Swarm:构建分布式容器集群、轻松管理节点和服务

什么是Docker Swarm Docker Swarm 是 Docker 的内置编排工具&#xff0c;它允许将多个 Docker 主机组成一个集群&#xff0c;并以统一的方式管理和部署容器化应用程序。Swarm 提供了高可用性、伸缩性和容错能力&#xff0c;使得应用程序能够在集群中弹性地运行和扩展。 Docke…