如何对图像做分类器训练matlab代码

如何对图像做分类器训练matlab代码,第1张

图像做分类器训练要建立视觉词袋来进行图像分类。该过程生成用来表示图像视觉词的直方图,通过这些直方图来训练图像分类器。下面的步骤描述如何建立图像集,建立视觉词袋,以及训练和运用图像分类器。

第一步:建立图像类别集合

将图像分割成训练子集和测试子集。利用imageDatastore函数来存储训练分类器的图像。可以利用splitEachLabel函数将图像分割成训练数据和测试数据。

读取类别图像和创建图像子集

setDir = fullfile(toolboxdir('vision'),'visiondata','imageSets')

imds = imageDatastore(setDir,'IncludeSubfolders',true,'LabelSource','foldernames')

分割图集成训练和测试子集。下例中,30%作为训练数据,余下的作为测试数据。

[trainingSet,testSet] = splitEachLabel(imds,0.3,'randomize')

第二步:建立特征词袋

通过从每个类别的有代表性的图像中提取特征描述符,创建视老差觉词汇表或特征包。

通过在训练集合中提取出的特征描述符上利用k-means聚类算法,bagOfFeatures对象定义特征,视觉词汇。该算法迭代地将描述符分成k个互斥簇。由此产生的簇是紧密的,并具有相似的特性。每个集群中心代表一个特征,或一个可视词。可以基于特征检测器提取特征,也可以定义一个网格来提取特征描述符。网格方法可能丢失细节信息。因此,对不包含明显特征的图像使用网格,例如海滩等景物的图像。使用Speed up robust features(或SURF)检测器提供更大的尺度不变性。默认情况下,该算法运行“网格”方法。

该算法工隐码作流对图像进行整体分析。图像必须有适当的标签来描述它们所代表的类。例如,一组汽车图像可以被标记为汽车。工作流不依赖于空间信息,也不依赖于标记图像中的特定对象。视觉词袋技术依赖于非局部化的检测技术。

第三步:通过视觉词袋训练图像分类器

trainImageCategoryClassifier函数返回一个图像分类器。该方法使用基于2分类支持向量机(灶含哪SVM)的error-correcting output codes(ECOC)框架来训练一个多分类器。

该方法利用bagOfFeatures对象返回的视觉词袋将图像集中的图像编码成视觉词直方图。然后将视觉词直方图作为训练分类器的正负样本。

1、将训练集中的每幅图像利用bagOfFeature的encode方法进行编码。该函数检测和提取图像中的特征,然后利用最近邻算法构造每个图像的特征直方图。函数将描述符逼近聚类中心来增加直方图各bin的数值。直方图的长度取决于bagOfFeatures对象构造的出来的视觉词的数量。最终将直方图作为图像的特征向量。

2、对训练集中的每幅图像重复步骤1,建立训练数据

3、评价分类器。在测试图像集上使用imagecategoryclassifier的evaluate方法测试分类器。输出混淆矩阵可以分析预测结果。理想的分类结果是对角线上包含一个标准矩阵。不正确的分类导致出现分数值。

第四步:对图像或图像集进行分类

最后使用imageCategoryClassifier 的predeict方法对新图像进行分类来确定其类型。

可以反过来考虑,首先满足条件的数一定是一个平方数(不然就不会汪贺有“所得到的和的平方,等于原来那个数”),N 位数中每一个平方数,都对应了一个大概 N/2 位的平方根,比如两位数中的平方数就只有:

16 = 4^2

25 = 5^2

36 = 6^2

49 = 7^2

64 = 8^2

81 = 9^2

而 N/2 位数的个数显然是比 N 位数少很多的,所以可以考虑枚举所有 N/2 位的平方根,比如当 N = 2 时,就只需要枚举 4,5,6,7,8,9,然后考虑它们的平方即可。

首先对于给定的 N,可以求出平方根的枚举范围,比如说 N = 5 时,5位数的最小值是 10000,最大值是 99999,把这两个值开平方,得到:

√10000 = 100

√99999 = 316.226

这说明,所有5位数的平方根,一定是介于 100 和 316 之间的,所以,只需要枚举 100 到 316 之间这些数。

而每当枚举到一个数时,计算这个数的平方,这个平方必然是一个5位数,然后把这个5位数按照题意拆分成前后两个基喊部分,再看这两个部分之和是否等于当前枚举到的平方根即可:

for (i = 100i <= 316i++) { // 枚举所有5位数的平方根

s = i^2 // 得到当前的5位平方数

A = s / 10^(N/2)// 把这个平方数分成A,B两个部分

B = s % 10^(N/2)

if (A + B == i) { // 如果 A+B == i 那 s 就是一个解

printf("%d\n", s)// 输出 s

}

}

这个算法的时间复杂度是 O(10^(N/2))。即使 N = 8 时,也只需要枚举大概 9000 个数,速度是比较理想的。完整的程序如下:

#include <stdio.h>

#include <math.h>

int p10[8] = {1,10,100,1000,10000,100000,1000000,10000000}

int n

int main() {

int i, lb, ub

scanf("%d"困锋派, &n)

lb = p10[n-1]ub = lb * 10 - 1

lb = ceil(sqrt((double)lb))+1e-8

ub = floor(sqrt((double)ub))+1e-8

for (i = lbi <= ubi++) {

int s = i * i

int A = s / p10[n/2]

int B = s % p10[n/2]

if (A + B == i) {

printf("%d\n", s)

}

}

return 0

}


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12541609.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存