以下是代码展示部分,但代码实现仅仅只从颜色这一个角度进行,原本我想做一个颜色头盔检测计数系统的。如果是想要实现是否佩戴头盔的检测,可以只从形状检测这一角度进行思考即可
function detectHelmetWithUI()
% 创建一个图形窗口
fig = uifigure('Name', 'Helmet Detection');
% 创建一个按钮用于选择图像文件
btn = uibutton(fig, 'push', 'Text', '选择图像', 'Position', [10 10 100 22], 'ButtonPushedFcn', @(btn,event)selectImage());
function selectImage()
% 显示文件选择对话框
[file, path] = uigetfile({'*.jpg;*.png;*.bmp', '图像文件 (*.jpg, *.png, *.bmp)'}, '选择图像文件');
% 如果用户取消选择,则返回
if isequal(file, 0)
return;
end
% 读取选定的图像文件
imagePath = fullfile(path, file);
% 调用检测头盔的函数
detectHelmet(imagePath);
end
function histValues = myImhist(grayImg)
% 获取图像的尺寸
[height, width] = size(grayImg);
% 初始化直方图
histValues = zeros(256, 1);
% 计算直方图
for i = 1:height
for j = 1:width
% 获取当前像素的灰度值
grayVal = grayImg(i, j) + 1; % 加一是为了将像素值从 0-255 映射到 1-256
% 更新直方图统计
histValues(grayVal) = histValues(grayVal) + 1;
end
end
end
function enhancedImg = myHisteq(img)
% 将彩色图像转换为灰度图像
grayImg = myRgb2Gray(img);
% 计算输入图像的直方图
histValues = myImhist(grayImg);
% 计算累积直方图
cdf = cumsum(histValues) / numel(grayImg);
% 对原始图像进行像素值映射
enhancedImg = uint8(255 * cdf(double(grayImg) + 1));
end
function grayImg = myRgb2Gray(img)
% 获取图像的尺寸和通道数
[height, width, numChannels] = size(img);
% 初始化灰度图像
grayImg = zeros(height, width, 'uint8');
% 对于每个像素,计算出其灰度值
for i = 1:height
for j = 1:width
% 获取当前像素的 RGB 分量
R = double(img(i, j, 1));
G = double(img(i, j, 2));
B = double(img(i, j, 3));
% 计算灰度值
grayVal = 0.2989 * R + 0.5870 * G + 0.1140 * B;
% 将灰度值保存到灰度图像中
grayImg(i, j) = uint8(grayVal);
end
end
end
function threshold = myGraythresh(enhancedImg)
% 获取图像的尺寸
[height, width] = size(enhancedImg);
% 统计图像中每个灰度级别的像素个数
pixelCounts = imhist(enhancedImg);
% 计算每个灰度级别的概率密度
probabilities = pixelCounts / (height * width);
% 初始化类间方差和最佳阈值
maxVariance = 0;
threshold = 0;
% 遍历灰度级别,计算类间方差
for i = 2:256
% 分割前景和背景
foregroundProb = sum(probabilities(1:i));
backgroundProb = sum(probabilities(i+1:end));
% 计算类间方差
variance = foregroundProb * backgroundProb * ((mean(enhancedImg(1:i)) - mean(enhancedImg(i+1:end)))^2);
% 更新最大类间方差和阈值
if variance > maxVariance
maxVariance = variance;
threshold = i - 1; % 减一是为了将像素值从 1-256 映射到 0-255
end
end
end
function binaryImg = myImbinarize(enhancedImg, threshold)
% 创建与输入图像同样大小的二值化图像
binaryImg = zeros(size(enhancedImg));
% 遍历输入图像的每个像素,根据阈值进行二值化
for i = 1:size(enhancedImg, 1)
for j = 1:size(enhancedImg, 2)
if enhancedImg(i, j) >= threshold
binaryImg(i, j) = 1;
end
end
end
end
function outputImg = myBwareaopen(binaryImg, minArea)
% 标记连通区域
labeledImg = bwlabel(binaryImg);
% 获取每个连通区域的面积
stats = regionprops(labeledImg, 'Area');
% 创建同样大小的输出图像
outputImg = zeros(size(binaryImg));
% 根据面积阈值进行过滤
for i = 1:numel(stats)
if stats(i).Area >= minArea
% 将满足条件的连通区域添加到输出图像中
outputImg = outputImg | (labeledImg == i);
end
end
end
function detectHelmet(imagePath)
% 读取图像
img = imread(imagePath);
% 图像预处理:直方图增强
enhancedImg = myHisteq(img);
% 图像分割
threshold = myGraythresh(enhancedImg);
binaryImg = myImbinarize(enhancedImg, threshold);
% 过滤微小连通域
filteredImg = myBwareaopen(binaryImg, 100);
% 颜色识别
hsvImg = rgb2hsv(img);
mask = (hsvImg(:,:,1) >= 0.95 | hsvImg(:,:,1) <= 0.05) &...
hsvImg(:,:,2) >= 0.5 &...
hsvImg(:,:,3) >= 0.5;
% 结果显示
figure;
subplot(1, 3, 1);
imshow(img);
title('Original Image');
subplot(1, 3, 2);
imshow(filteredImg);
title('Segmented Image');
subplot(1, 3, 3);
imshow(mask);
title('Color Mask');
% 检测结果判断
helmetDetected = any(mask(:));
if helmetDetected
disp('此人佩戴头盔');
else
disp('此人未佩戴头盔');
end
end
end
这是对图像进行的预处理
之后就是从颜色阈值进行判定 先说明 代码这样子判定其实并不是很准确
以下是项目GUI展示界面
最后在matlab控制台输出是否佩戴头盔的判别结果
我觉得本项目,应该起到一个抛砖引玉的效果,基本框架都有,实现头盔检测的思路其实也已经八九不离十。如果是有想法的话,可以在这个基础上进行进一步的完善。