直接上代码,数据预处理很重要,其它没啥了
%第一部分:读取图像
% 定义树叶种类和每种树叶的图片数量
%%
leafTypes = {'Quercussuber', 'Salixatrocinerea', 'Populusnigra', 'Alnussp', 'Quercusrobur', 'Crataegusmonogyna', 'Ilexaquifolium', 'Neriumoleander'};
numImagesPerType =8;%每种树叶选取8张导入数据集
pi=3.14;
% 初始化数据集
dataset = struct();%原始图像
%data2bw=struct();%二值图像
%datargbgray = struct();%灰度图像
%datargbhsi = struct();%HSI图像
% 通过for循环读取图片并添加到数据集中
for i = 1:length(leafTypes)
for j = 1:numImagesPerType
imagePath = ['C:\Users\灰太狼\OneDrive\桌面\图片训练集\', leafTypes{i}, '\iPAD2_C0_EX0', num2str(j), '.jpg'];
imageData = imread(imagePath);
dataset.(leafTypes{i}){j} = imageData;
%datargbgray.(leafTypes{i}){j}=imageData;
%datargbhsi.(leafTypes{i}){j}=imageData;
%data2bw.(leafTypes{i}){j}=imageData;
%figure;
%imshow(imageData);%显示原始图像
end
end
%
%for leafType = fieldnames(dataset)'
%for imageIndex = 1:numImagesPerType
% imageData = dataset.(leafType{1}){imageIndex};
%
%imagegray=im2gray(imageData);
%imagegrayopen=imopen(imagegray,se);
%imagegray=imagegrayopen+imagegray;
%datargbgray.(leafTypes{i}){j}=imagegray;
%figure;
%imshow(imagegray);
%
%imagehsv=rgb2hsv(imageData);
%images=imagehsv(:,:,2);
%imagetransit=im2bw(imageData);
%imagehsv=images.*imagetransit;
%datargbhsi.(leafTypes{i}){j}=imagehsv;
%figure;
%imshow(imagehsv);
% end
%end
%imshow(data2bw.three{5});
%第二部分:特征提取
featuredataset=struct();%建立特征数据集
pi=3.14159;
for leafType = fieldnames(dataset)' %建立循环预处理图像,并在图像处理完成后提取特征储存
for imageIndex = 1:numImagesPerType
imageDatas = dataset.(leafType{1}){imageIndex};
%二值化预处理,对RGB图像进行调整,提亮绿色,减少黑色
r = imageDatas(:,:,1);
g = imageDatas(:,:,2);
%%
b = imageDatas(:,:,3);
% 减少黑色分量(降低蓝色和红色通道的值)
r = r * 0.8;
b = b * 0.8;
% 增加绿色分量
g = g * 1.2;
%处理棕色部分,即绿叶枯萎那部分
brown_threshold = 125; % 比如红色和绿色分量都小于 125 可视为棕色
% 对棕色像素进行处理
brown_pixels = (r < brown_threshold) & (g < brown_threshold);
g(brown_pixels) = g(brown_pixels) + 80; % 增加绿色分量
new_img = cat(3, r, g, b);% 组合修改后的通道
hsv = rgb2hsv(new_img);%将RGB模型转为HSI模型
% 提取 V 通道(亮度),调整亮度
v_channel = hsv(:,:,3);
threshold = 1;% 设定一个阈值,低于该阈值的认为是较黑部分
v_channel(v_channel < threshold) = v_channel(v_channel < threshold) + 1; % 将较黑部分的 V 通道值增加一些以变亮一点
hsv(:,:,3) = v_channel;% 根据调整后的 V 通道更新 HSV
adjusted_img = hsv2rgb(hsv); % 将 HSV 转换回 RGB
%figure;
%imshow(adjusted_img);
%运用超绿指数提取树叶的二值图像
image = im2double(adjusted_img); %图像运算不能用uint8类型,会发生溢出现象,要转成double类型
R = image(:,:,1);
G = image(:,:,2);
B = image(:,:,3);
ExG = 2*G-R-B;
[m,n] = size(ExG);
T = graythresh(ExG);
greenpicture = ExG;
for i = 1:m
for j= 1:n
if greenpicture(i,j) >= T
greenpicture(i,j)=255;
else
greenpicture(i,j)=0;
end
end
end
se=strel('square',25);
setest=strel('square',15);
greenpicture=imopen(greenpicture,setest);%开运算
greenpicture=imclose(greenpicture,se);%闭运算
%figure;
%imshow(greenpicture);
%运用超绿指数对图像进行灰度预处理
% 获取图像的三个通道
red = imageDatas(:,:,1);
green = imageDatas(:,:,2);
blue = imageDatas(:,:,3);
% 减少黑色分量(降低蓝色和红色通道的值)
red = red * 0.8;
blue = blue * 0.8;
% 增加绿色分量
green = green * 1.15;
%处理棕色部分
brown_thresholdgray = 80; % 比如红色和绿色分量都小于 80 可视为棕色
% 对棕色像素进行处理
brown_pixelsgray = (red < brown_thresholdgray) & (green < brown_thresholdgray);
green(brown_pixelsgray) = green(brown_pixelsgray) +10; % 增加绿色分量
new_imggray = cat(3, red, green, blue); % 组合修改后的通道
hsvgray = rgb2hsv(new_imggray);
% 提取 V 通道(亮度)
v_channelgray = hsvgray(:,:,3);
thresholdgray = 0.05;% 设定一个阈值,低于该阈值的认为是较黑部分
v_channelgray(v_channelgray < thresholdgray) = v_channelgray(v_channelgray < thresholdgray) + 0.3;% 将较黑部分的 V 通道值增加一些以变亮一点
hsvgray(:,:,3) = v_channelgray;% 根据调整后的 V 通道更新 HSV
adjusted_imggray = hsv2rgb(hsvgray);% 将 HSV 转换回 RGB
imagegraypicture = im2double(adjusted_imggray); %图像运算不能用uint8类型,会发生溢出现象,要转成double类型
Red = imagegraypicture(:,:,1);
Green = imagegraypicture(:,:,2);
Blue = imagegraypicture(:,:,3);
ExGgray = 2*Green-Red-Blue;
%特征提取部分
area=sum(greenpicture(:)>0);%面积
glcm = graycomatrix(ExGgray,'Offset',[2 0]);%灰度共生矩阵
statsglcm = graycoprops(glcm);
Contrast=statsglcm.Contrast;
Correlation=statsglcm.Correlation;
Energy=statsglcm.Energy;
Homogeneity=statsglcm.Homogeneity;
% 计算叶片区域的长宽比和矩形度
statebox = regionprops(greenpicture, 'BoundingBox');
boundingBox = cat(1, statebox(255).BoundingBox);
aspectRatio = boundingBox(:,3) ./ boundingBox(:,4);%长宽比
rectangleAreas = boundingBox(:,3) .* boundingBox(:,4);%矩形度
rectangularities = area ./ rectangleAreas;
stateper = regionprops(greenpicture, 'Perimeter');
perimeter=stateper(255).Perimeter;%周长
statecon = regionprops(greenpicture, 'ConvexArea');%凸包面积
circularity = (4.*pi.*area./(perimeter^2))*(1-0.5./(perimeter/(2*pi) + 0.5))^2;%圆形度
sphericity = (pi^(1/3) * (6 * area).^(2/3)) ./ perimeter;%球状度
convexArea = [statecon(255).ConvexArea];
stateecc=regionprops(greenpicture,'Eccentricity');%偏心率
ecc=stateecc(255).Eccentricity;
statesolid=regionprops(greenpicture,'Solidity');%实度
solid=statesolid(255).Solidity;
statepd=regionprops(greenpicture,'MajorAxisLength');%周长直径比
majorAxisLengths=statepd(255).MajorAxisLength;
pd=perimeter./majorAxisLengths;
moments=imagejui(ExGgray);%不变矩
moments1=moments(1);
moments2=moments(2);
moments3=moments(3);
moments4=moments(4);
moments5=moments(5);
moments6=moments(6);
moments7=moments(7);
area=area/100000;%归一化面积
% 将特征存储在特征数据集,共提取了19个特征
featuredataset.(leafType{1}){imageIndex} = {perimeter,aspectRatio,circularity,ecc,convexArea,solid,pd,rectangularities,moments1,moments2,moments3,moments4,moments5,moments6,moments7,Contrast,Correlation,Energy,Homogeneity};
%figure;
%imshow(greenpicture);
end
end
%第三部分:特征训练及分类
% 准备特征矩阵和标签向量
numFeatures =19; % 特征数量
numSamples = length(leafTypes) * numImagesPerType; % 样本数量
featureMatrix = zeros(numSamples, numFeatures);
labels = zeros(numSamples, 1);
% 填充特征矩阵和标签向量
index = 1;
for i = 1:length(leafTypes)
for j = 1:numImagesPerType
features = cell2mat(featuredataset.(leafTypes{i}){j});
featureMatrix(index, :) = features;
labels(index) = i; % 第 i 类叶片的标签
index = index + 1;
end
end
% 划分训练集和测试集
rng(9); % 设置随机数种子以确保结果可重复
cv = cvpartition(labels, 'Holdout', 0.2); % 划分 80% 训练集和 20% 测试集
idxTrain = training(cv);
idxTest = test(cv);
XTrain = featureMatrix(idxTrain, :);
YTrain = labels(idxTrain);
XTest = featureMatrix(idxTest, :);
YTest = labels(idxTest);
% 构建和训练 BP 神经网络
hiddenLayerSize = 12; % 隐藏层神经元数量
net = patternnet(hiddenLayerSize);
net.trainParam.showWindow = true; % 显示训练过程窗口
net = train(net, XTrain', ind2vec(YTrain'));
% 测试神经网络并计算准确率
YTestPredicted = vec2ind(net(XTest'))';
accuracy = sum(YTestPredicted == YTest) / length(YTest);
disp(['Accuracy: ', num2str(accuracy * 100), '%']);
%第四部分:新图片输入与分类结果输出
% 新输入图片的特征提取
newImage = imread('C:\Users\灰太狼\OneDrive\桌面\图片训练集\Quercussuber\iPAD2_C0_EX01.JPG');
newr = newImage(:,:,1);
newg = newImage(:,:,2);
newb = newImage(:,:,3);
% 减少黑色分量(降低蓝色和红色通道的值)
newr = newr * 0.8;
newb = newb * 0.8;
% 增加绿色分量
newg = newg * 1.2;
%处理棕色部分
newbrown_threshold = 125; % 比如红色和绿色分量都小于 80 可视为棕色
% 对棕色像素进行处理
newbrown_pixels = (newr < newbrown_threshold) & (newg < newbrown_threshold);
newg(newbrown_pixels) = newg(newbrown_pixels) + 80; % 增加绿色分量
% 组合修改后的通道
new_image = cat(3, newr, newg, newb);
newhsv = rgb2hsv(new_image);
% 提取 V 通道(亮度)
newv_channel = newhsv(:,:,3);
% 设定一个阈值,低于该阈值的认为是较黑部分
newthreshold = 1;
% 将较黑部分的 V 通道值增加一些以变亮一点
newv_channel(newv_channel < newthreshold) = newv_channel(newv_channel < newthreshold) + 1;
% 根据调整后的 V 通道更新 HSV
newhsv(:,:,3) = newv_channel;
% 将 HSV 转换回 RGB
newadjusted_img = hsv2rgb(newhsv);
newimage = im2double(newadjusted_img); %图像运算不能用uint8类型,会发生溢出现象,要转成double类型
newR = newimage(:,:,1);
newG = newimage(:,:,2);
newB = newimage(:,:,3);
newExG = 2*newG-newR-newB;
[newm,newn] = size(newExG);
newT = graythresh(newExG);
newgreenpicture = newExG;
for i = 1:newm
for j= 1:newn
if newgreenpicture(i,j) >= newT
newgreenpicture(i,j)=255;
else
newgreenpicture(i,j)=0;
end
end
end
newse=strel('square',25);
newsetest=strel('square',15);
newgreenpicture=imopen(newgreenpicture,newsetest);
newgreenpicture=imclose(newgreenpicture,newse);
%灰度图像预处理
% 获取图像的三个通道
newred = newImage(:,:,1);
newgreen = newImage(:,:,2);
newblue = newImage(:,:,3);
% 减少黑色分量(降低蓝色和红色通道的值)
newred = newred * 0.85;
newblue = newblue * 0.85;
% 增加绿色分量
newgreen = newgreen * 1.1;
%处理棕色部分
newbrown_thresholdgray = 80; % 比如红色和绿色分量都小于 80 可视为棕色
% 对棕色像素进行处理
newbrown_pixelsgray = (newred < newbrown_thresholdgray) & (newgreen < newbrown_thresholdgray);
newgreen(newbrown_pixelsgray) = newgreen(newbrown_pixelsgray) +10; % 增加绿色分量
% 组合修改后的通道
newnew_imggray = cat(3, newred, newgreen, newblue);
newhsvgray = rgb2hsv(newnew_imggray);
% 提取 V 通道(亮度)
newv_channelgray = newhsvgray(:,:,3);
% 设定一个阈值,低于该阈值的认为是较黑部分
newthresholdgray = 0.05;
% 将较黑部分的 V 通道值增加一些以变亮一点
newv_channelgray(newv_channelgray < newthresholdgray) = newv_channelgray(newv_channelgray < newthresholdgray) + 0.3;
% 根据调整后的 V 通道更新 HSV
newhsvgray(:,:,3) = newv_channelgray;
% 将 HSV 转换回 RGB
newadjusted_imggray = hsv2rgb(newhsvgray);
newimagegraypicture = im2double(newadjusted_imggray); %图像运算不能用uint8类型,会发生溢出现象,要转成double类型
newRed = newimagegraypicture(:,:,1);
newGreen = newimagegraypicture(:,:,2);
newBlue = newimagegraypicture(:,:,3);
newExGgray = 2*newGreen-newRed-newBlue;
%特征提取部分
newarea=sum(newgreenpicture(:)>0);
newglcm = graycomatrix(newExGgray,'Offset',[2 0]);%灰度共生矩阵
newstatsglcm = graycoprops(newglcm);
newContrast=newstatsglcm.Contrast;
newCorrelation=newstatsglcm.Correlation;
newEnergy=newstatsglcm.Energy;
newHomogeneity=newstatsglcm.Homogeneity;
% 计算叶片区域的长宽比
newstatebox = regionprops(newgreenpicture, 'BoundingBox');
newboundingBox = cat(1, newstatebox(255).BoundingBox);
newaspectRatio = newboundingBox(:,3) ./ newboundingBox(:,4);%长宽比
newrectangleAreas = newboundingBox(:,3) .* newboundingBox(:,4);%矩形度
newrectangularities = newarea ./ newrectangleAreas;
newstateper = regionprops(newgreenpicture, 'Perimeter');
newperimeter=newstateper(255).Perimeter;%周长
newstatecon = regionprops(newgreenpicture, 'ConvexArea');
newcircularity = (4.*pi.*newarea./(newperimeter^2))*(1-0.5./(newperimeter/(2*pi) + 0.5))^2;%圆形度
newsphericity = (pi^(1/3) * (6 * newarea).^(2/3)) ./ newperimeter;%球状度
newconvexArea = [newstatecon(255).ConvexArea];
newstateecc=regionprops(newgreenpicture,'Eccentricity');%偏心率
newecc=newstateecc(255).Eccentricity;
newstatesolid=regionprops(newgreenpicture,'Solidity');
newsolid=newstatesolid(255).Solidity;%实度
newstatepd=regionprops(newgreenpicture,'MajorAxisLength');
newmajorAxisLengths=newstatepd(255).MajorAxisLength;
newpd=newperimeter./newmajorAxisLengths;%周长直径比
newmoments=imagejui(newExGgray);%不变矩
newmoments1=newmoments(1);
newmoments2=newmoments(2);
newmoments3=newmoments(3);
newmoments4=newmoments(4);
newmoments5=newmoments(5);
newmoments6=newmoments(6);
newmoments7=newmoments(7);
newarea=newarea/100000;
newImageFeatures = [newperimeter,newaspectRatio,newcircularity,newecc,newconvexArea,newsolid,newpd,newrectangularities,newmoments1,newmoments2,newmoments3,newmoments4,newmoments5,newmoments6,newmoments7,newContrast,newCorrelation,newEnergy,newHomogeneity];
predictedLabel = vec2ind(net(newImageFeatures'))';
% 打印预测结果
predictedLeafType = leafTypes{predictedLabel};
disp(['Predicted leaf type: ', predictedLeafType]);
imshow(newImage);显示图片并标注预测类别
txt = predictedLeafType;
text(250,250,txt)
子函数不变距代码,这个是网上找到的。
function y=imagejui(bw) %图像的不变矩
global x_average y_average
myI=double(bw);[y,x]=size(myI);
m00=sum(sum(myI));m10=0;m01=0;
for i=1:y
for j=1:x
m10=m10+j*myI(i,j); m01=m01+i*myI(i,j);%求一阶矩
end
end
x_average=m10/m00;y_average=m01/m00;
m20=myf(myI,2,0);m02=myf(myI,0,2);
m11=myf(myI,1,1);
m30=myf(myI,3,0);m03=myf(myI,0,3);
m12=myf(myI,1,2);m21=myf(myI,2,1);
m1=m20+m02;%按定义求七个不变矩
m2=(m20-m02)^2+4*m11^2;
m3=(m30-3*m12)^2+(3*m21-m03)^2;
m4=(m30+m12)^2+(m21+m03)^2;
m5=(m30-3*m12)*(m30+m12)*((m30+m12)^2-3*(m12+m03)^2) ...
+(m03-3*m21)*(m03+m12)*((m03+m21)^2-3*(m12+m03)^2);
m6=(m20-m02)*((m30+m12)^2-(m21+m03)^2)+4*m11*(m30+m12)*(m03+m21);
m7=(3*m21-m03)*(m30+m12)*((m30+m12)^2-3*(m21+m03)^2)...
+(m30-3*m12)*(m03+m21)*((3*m30+m12)^2-(m21+m03)^2);
y=[m1;m2;m3;m4;m5;m6;m7];
y=abs(log10(abs(y)));%利用对数的方法进行数据压缩,并给出正值
end
function m=myf(myI,p,q)%子函数,用于求和
global x_average y_average
[y,x]=size(myI);m00=sum(sum(myI));
m=0;
for i=1:y
for j=1:x
m=m+(i-y_average)^q*(j-x_average)^p*myI(i,j); %求和
end
end
m=m/m00^((p+q)/2+1);%归一化
end