假设我们有以下图片,其中包含 PCB 缺陷(称为缺孔缺陷):
我的项目中需要识别的缺陷列表是:
为此,我需要提取与缺陷类别相关的颜色。
我知道使用 R ,我们可以做到:
library(colorfindr)
img_path="C:/Users/Rayane_2/Desktop/Data/PCB1/PCB/images/Mouse_bite/01_mouse_bite_04.jpg"
colorfindr::get_colors(img_path,top_n=20)
# A tibble: 20 × 3
col_hex col_freq col_share
<chr> <int> <dbl>
1 #005B0C 31106 0.00646
2 #005B0E 29117 0.00605
3 #01590B 27768 0.00577
4 #005A0B 24135 0.00502
5 #015C0D 23771 0.00494
6 #00580A 22397 0.00465
7 #005B0B 21529 0.00447
8 #00560F 21476 0.00446
9 #005A0D 21324 0.00443
10 #025A0C 21191 0.00440
11 #01590D 21026 0.00437
12 #005709 20009 0.00416
13 #00580E 19063 0.00396
14 #005909 18666 0.00388
15 #015C0F 18450 0.00383
16 #025A0E 17979 0.00374
17 #015710 16621 0.00345
18 #01590F 16619 0.00345
19 #00580C 16546 0.00344
20 #005A0A 15614 0.00324
从缺陷类型图片中,我看到有 3 种颜色可以区分这些缺陷。
我需要识别这 3 个并从 tibble 数据集中提取。
这个问题很有趣,我们可以尝试不同的特征,从手动、手工制作(从简单到复杂的特征和不同的机器学习模型)到自动提取的特征(例如,使用深度学习深度神经网络模型)。
让我们尝试一个非常简单的仅基于颜色的功能。
我们首先使用
k
聚类算法将图像RGB颜色值聚类为k=3
组(例如kmeans
),并使用函数k
获得get.color.clusters()
颜色聚类中心,如下所示(我们需要从十六进制颜色值中提取红色、绿色、蓝色值)。
然后我们将使用
kmeans
模型来预测图像的每个像素所属的颜色簇,然后计算图像中属于颜色簇的像素的比例作为特征(因此我们将具有 k
特征)。因此,对于 k=3
集群,我们的数据框将如下所示:
cluster1 cluster2 cluster3 class (label)
image1 0.6 0.3 0.1 missing holes
这意味着对于缺失的孔图像1,我们分别有 60%、30% 和 10% 的像素属于簇 1、2 和 3。
现在,该数据集将用于训练(二元)分类器,如果我们假设同一缺陷类别的颜色簇比例具有相似的模式,则分类器将执行下降工作。
这是我们仅用于 2 个类别的两组图像:
现在,让我们提取颜色簇比例特征,并尝试使用 RBF 核的 SVM 分类器来对缺陷类别进行分类和预测。
find_cluster_kmeans <- function(cl, x) { # predict the color cluster a pixel belongs to
return (which.min(apply(cl$centers, 1, function(y) sum((y-x)^2))))
}
extract.color.features <- function(img_path, cl) {
col_df <- colorfindr::get_colors(img_path, top_n=20)
cols <- as.data.frame(t(do.call(rbind, lapply(col_df['col_hex'], col2rgb))))
col_cluster <- apply(cols, 1, function(x) find_cluster_kmeans(cl, x))
col_df <- cbind(col_df, cols, col_cluster=col_cluster)
col_df <- col_df[c('col_cluster', 'col_share')]
df_feat <- aggregate(col_df$col_share, list(col_df$col_cluster), FUN=sum) # group by color clusters and sum proportions
names(df_feat) <- c('col_clust', 'prop')
for (i in 1:(nrow(cl$centers))) { # ensure that all color clusters are present
if (nrow(df_feat[df_feat$col_clust == i,]) == 0) {
df_feat <- rbind(df_feat, data.frame(col_clust=i, prop=0))
}
}
df_feat$prop <- df_feat$prop / sum(df_feat$prop) # normalize
return(df_feat)
}
get.color.clusters <- function(k=3, top_n=50) {
col_df <- NULL
for (folder in c('missing_hole', 'Mouse_bite')) {
img_path <- list.files(folder,".png", full.names = T)
cdf <- do.call(rbind, lapply(img_path, function(p) colorfindr::get_colors(p,top_n=top_n)))
col_df <- rbind(col_df, cdf)
}
cols <- as.data.frame(t(do.call(rbind, lapply(col_df['col_hex'], col2rgb))))
cl <- kmeans(cols, k)
print(cl$center)
return (cl)
}
library(colorfindr)
set.seed(12)
k <- 3 # 3 color clusters
cl <- get.color.clusters(k)
df <- NULL
for (cls in c('missing_hole', 'Mouse_bite')) {
img_path <- list.files(cls,".png", full.names = T)
df_feat <- NULL
for (img in img_path) {
#print(img)
df_feat <- rbind(df_feat, extract.color.features(img, cl)$prop)
}
df_feat <- as.data.frame(df_feat)
df_feat$class <- cls
df <- rbind(df, df_feat)
}
names(df)[1:k] <- paste0('cluster', 1:k)
df$class <- as.factor(df$class)
df # each row corrspeonds to an image and each column to a color cluster
# cluster1 cluster2 cluster3 class
#1 0.318473896 0.68152610 0.00000000 missing_hole
#2 0.984514797 0.01548520 0.00000000 missing_hole
#3 0.967479675 0.03252033 0.00000000 missing_hole
#4 0.010911326 0.80282772 0.18626095 Mouse_bite
#5 0.008364049 0.96257443 0.02906153 Mouse_bite
#6 0.446066380 0.55393362 0.00000000 Mouse_bite
library(e1071)
svmfit = svm(class ~ ., data = df, kernel = "radial", cost = 1, scale = FALSE, type='C')
print(svmfit)
plot(svmfit, df, cluster1 ~ cluster2, fill=TRUE, alpha=0.2)
df$prdicted <- predict(svmfit, df)
df
# cluster1 cluster2 cluster3 class prdicted
#1 0.318473896 0.68152610 0.00000000 missing_hole Mouse_bite
#2 0.984514797 0.01548520 0.00000000 missing_hole missing_hole
#3 0.967479675 0.03252033 0.00000000 missing_hole missing_hole
#4 0.010911326 0.80282772 0.18626095 Mouse_bite Mouse_bite
#5 0.008364049 0.96257443 0.02906153 Mouse_bite Mouse_bite
#6 0.446066380 0.55393362 0.00000000 Mouse_bite Mouse_bite
理想情况下,我们应该在一定比例的数据集上进行训练,并在保留的数据集上评估分类器以实现通用性。
现在颜色簇比例特征非常幼稚,并且可能不会很好地执行,那么您可以尝试提取 HOG、SIFT、SURF、BRISK、BRIEF 等特征,并使用相应的描述符作为 ML 分类器的特征向量。
最后,为了获得最佳性能,我们可以使用深度神经网络在不同层实现自动特征生成,但在这种情况下,我们需要有相当大量的训练图像(通过数据增强增加训练数据集大小)或使用在一些标准的再训练网络(例如 Vgg-15)之上进行迁移学习。