基于Python的工业图像异常检测基础技术详解

news2024/11/28 16:41:10

引言

博文字数7000,建议阅读时间20分钟。

这篇博客对当前几种典型的图像异常检测算法进行了比较,包括Kmeans、Kmeans++以及大津法(OTSU),并给出了相关的代码实现与测试方法。总结的比较结果如下表所示:

方法类型KmeansKmeans++OTSU
推理时间消耗(inference time)1.368s30.726s0.078s

主要结论如下:

  • Kmeans++的中心选择算法当然有较大的优化空间,此处是简单的for循环python代码,仍然存在较大提升空间。
  • 三种算法OTSU相对最快,Kmeans聚类则可以选择聚类数k,而Kmeans++则不受到聚类中心的影响。

基于Python的图像异常检测技术-基础详解

  • 1. 基于K均值聚类(Kmeans)的图像异常检测
    • 1.1 实现代码
    • 1.2 测试效果
  • 2. 基于K均值聚类(Kmeans++)的图像异常检测
    • 2.1 实现代码
    • 2.2 测试效果
  • 3. 基于OTSU的图像异常检测
    • 3.1 实现代码
    • 3.2 测试效果
  • 参考文献资料

1. 基于K均值聚类(Kmeans)的图像异常检测

1.1 实现代码

要识别图片中异常的地方,可以使用计算机视觉中的Image Segmentation(图像分割) 技术。下面是使用 Python 语言和 OpenCV 库实现的一个简单demo,使用 K-Means 算法进行颜色聚类,将相似的像素分为一组,然后使用二值化将其转换为黑白图像,最后使用形态学操作(腐蚀和膨胀)去除噪声并找到异常的区域。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib.colors import ListedColormap
import matplotlib.colors as mcolors

if __name__ == '__main__':
    # Initialize rgb pixel values for each class in kmeans using specific values
    # Generate 10 equidistant colors
    # Define a list of 12 colors
    colors = ["#00008B", "#008B8B", "#FF8C00", "#FF69B4", "#008000", "#0000CD", "#4B0082", "#FF00FF", "#1E90FF",
              "#FFD700", "#FF1493", "#6495ED"]

    # Create the colormap
    selec_bgr = ListedColormap(colors)
    bgr_list = selec_bgr.colors
    # Reading images using matplotlib library
    image = mpimg.imread('./data/Tianchi_metal_defect.png')
    height, width, channel = image.shape
    # show original image
    plt.figure()
    plt.subplot(3, 3, 1)
    plt.axis('off')
    plt.title('Original')
    plt.imshow(image)
    # do kmeans segmentation
    for i, k in enumerate(range(5, 13, 1)):
        # extract bgr features
        features = []
        print(f"正在计算k={k},第{k-4}张聚类图...")
        try:
            for y in range(height):
                for x in range(width):
                    features.append(image[y, x, :] / 255)
            features = np.array(features)
            # initial segments center using random value in features
            kmeans_centers = features[np.random.choice(len(features), k), :]
            kmeans_centers = np.array(kmeans_centers)
        except:
            pass
        # update
        while True:
            # calculate distance matrix
            def euclidean_dist(X, Y):
                Gx = np.matmul(X, X.T)
                Gy = np.matmul(Y, Y.T)
                diag_Gx = np.reshape(np.diag(Gx), (-1, 1))
                diag_Gy = np.reshape(np.diag(Gy), (-1, 1))
                return diag_Gx + diag_Gy.T - 2 * np.matmul(X, Y.T)

            dist_matrix = []
            for start in range(0, len(features), 1000):
                dist_matrix.append(euclidean_dist(features[start:start + 1000, :], kmeans_centers))
            dist_matrix = np.concatenate(dist_matrix, axis=0)
            # dist_matrix = euclidean_dist(features, kmeans_centers)
            # get seg class for each sample
            segs = np.argmin(dist_matrix, axis=1)
            # update new kmeans center
            new_kmeans_centers = []
            for j in range(k):
                new_kmeans_centers.append(np.mean(features[segs == j, :], axis=0))
            new_kmeans_centers = np.array(new_kmeans_centers)
            # calculate whether converge
            if np.mean(abs(kmeans_centers - new_kmeans_centers)) < 0.1:
                break
            else:
                kmeans_centers = new_kmeans_centers
        # assign
        segs = segs.reshape(height, width)
        seg_result = np.zeros((height, width, channel), dtype=np.uint8)
        for y in range(height):
            for x in range(width):
                seg_result[y, x, :] = mcolors.hex2color(bgr_list[segs[y, x]])

        # show kmeans result
        plt.subplot(3, 3, i + 2)
        plt.title('k={}'.format(k))
        plt.axis('off')
        plt.imshow(seg_result)
        plt.savefig('Tianchi_metal_defect_kmeans.jpg')

1.2 测试效果

  • 原图如下,数据是天池铝型材表面缺陷数据集的样例图片
    在这里插入图片描述
  • 检测结果如下
正在计算k=5,第1张聚类图...
正在计算k=6,第2张聚类图...
正在计算k=7,第3张聚类图...
正在计算k=8,第4张聚类图...
正在计算k=9,第5张聚类图...
正在计算k=10,第6张聚类图...
正在计算k=11,第7张聚类图...
正在计算k=12,第8张聚类图...

Process finished with exit code 0

以下是不同聚类数(k)的聚类结果。

在这里插入图片描述

2. 基于K均值聚类(Kmeans++)的图像异常检测

2.1 实现代码

Kmeans++是在Kmeans算法基础上,修订后实现的一种算法,避免了初始点选择所导致的聚类效果差异和偏差。具体来说,原始K-means算法最开始随机选取数据集中K个点作为聚类中心,而K-means++按照如下的思想选取K个聚类中心:假设已经选取了n个初始聚类中心(0<n<K),则在选取第n+1个聚类中心时:距离当前n个聚类中心越远的点会有更高的概率被选为第n+1个聚类中心。在选取第一个聚类中心(n=1)时同样通过随机的方法。可以说这也符合我们的直觉:聚类中心当然是互相离得越远越好。这个改进虽然直观简单,但是却非常得有效。

相比于Kmeans的代码,就是用下述函数,替换了中心的随机化过程:

#######################################################################################################################
# 计算聚类中心辅助函数
def distance_func(point1, point2):
    distance = np.linalg.norm(point1 - point2)
    return distance

def nearest(point, cluster_centers):
    '''
    计算point和cluster_centers之间的最小距离
    :param point: 当前的样本点
    :param cluster_centers: 当前已经初始化的聚类中心
    :return: 返回point与当前聚类中心的最短距离
    '''
    FLOAT_MAX = math.e-3
    min_dist = FLOAT_MAX
    m = np.shape(cluster_centers)[0]  # 当前已经初始化聚类中心的个数
    for i in range(m):
        # 计算point与每个聚类中心之间的距离
        d = distance_func(point, cluster_centers[i, ])
        # 选择最短距离
        if min_dist > d:
            min_dist = d
    return min_dist

# 计算聚类中心的主函数
def get_cent(points, k):
    '''
    kmeans++的初始化聚类中心的方法
    :param points: 样本
    :param k: 聚类中心的个数
    :return: 初始化后的聚类中心
    '''
    m, n = np.shape(points)
    cluster_centers = np.mat(np.zeros((k, n)))

    # 1、随机选择一个样本点作为第一个聚类中心
    index = np.random.randint(0, m)
    cluster_centers[0,] = np.copy(points[index,])  # 复制函数,修改cluster_centers,不会影响points

    # 2、初始化一个距离序列
    d = [0.0 for _ in range(m)]

    for i in range(1, k):
        sum_all = 0
        for j in range(m):
            # 3、对每一个样本找到最近的聚类中心点
            d[j] = nearest(points[j,], cluster_centers[0:i, ])
            # 4、将所有的最短距离相加
            sum_all += d[j]
        # 5、取得sum_all之间的随机值
        sum_all *= random.random()
        # 6、获得距离最远的样本点作为聚类中心点
        for j, di in enumerate(d):  # enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同事列出数据和数据下标一般用在for循环中
            sum_all -= di
            if sum_all > 0:
                continue
            cluster_centers[i] = np.copy(points[j,])
            break
    return cluster_centers
#######################################################################################################################

2.2 测试效果

  • 运行日志如下:
正在计算k=5,第1张聚类图...
第1次聚类计算的时间消耗为:30.726s
正在计算k=6,第2张聚类图...
第2次聚类计算的时间消耗为:44.796s
正在计算k=7,第3张聚类图...
第3次聚类计算的时间消耗为:62.111s
正在计算k=8,第4张聚类图...
第4次聚类计算的时间消耗为:81.526s
正在计算k=9,第5张聚类图...
第5次聚类计算的时间消耗为:102.608s
正在计算k=10,第6张聚类图...

  • 效果如下:
    在这里插入图片描述

3. 基于OTSU的图像异常检测

3.1 实现代码

大津法(OTSU)是一种确定图像二值化分割阈值的算法,其处理通常是在灰度图的基础上,进一步将图像划分为二值图像,因此,其过程也可被称为二值化。由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。
它被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

**基本流程:**先使用预处理算法,比如:直方图规定化的方法对图像做出修正与增强, 再利用中值滤波的方法消除图像孤立的噪声点;Canny算子快速分辨出瑕疵位置, 再利用采用Otsu阈值方法求取自适应阈值自动选择并提取瑕疵。

import cv2
from PIL import Image
#读取彩色图像
color_img = cv2.imread(r'./data/Tianchi_metal_defect.png')
#在窗口中显示图像,该窗口和图像的原始大小自适应
cv2.imshow('original image',color_img)
#cvtColor的第一个参数是处理的图像,第二个是RGB2GRAY
gray_img=cv2.cvtColor(color_img,cv2.COLOR_RGB2GRAY)
#gray_img此时还是二维矩阵表示,所以要实现array到image的转换
gray=Image.fromarray(gray_img)
#将图片保存到当前路径下,参数为保存的文件名
gray.save('Tianchi_metal_defect_OTSU.jpg')
# Apply OTSU thresholding
_, binary_image = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# Display the results
cv2.imshow('Binary Image', binary_image)
cv2.imshow('Gray Image',gray_img)
#如果想让窗口持久停留,需要使用该函数
cv2.waitKey(0)

3.2 测试效果

二值化就是在灰度图的基础上,将像素转换为0、1两种值,呈现为黑、白两种简单色。
在这里插入图片描述

后记

更多关于计算机视觉和图像处理的内容请关注本人主页*,或者直接阅读**专栏-计算机视觉 - Opencv 强化学习等的 趣味小实验**
本博客和专栏将持续更新此方面的相关内容,感谢支持~🌹🌹🌹


参考文献资料

【1】官网-东北大学-钢材表面缺陷数据集
【2】天池-铝型材表面缺陷数据集
【3】综述论文-Machine vision based condition monitoring and fault diagnosis of machine tools using information from machined surface texture: A review

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

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

相关文章

cocosCreator 3.6以上接入腾迅Bugly 捕捉JS错误 Android

cocosCreator3.6以上接入Bugly上报其实很简单&#xff0c;不需要网上那么多弯弯绕&#xff0c;三须三步走。 1. 按照官网方式接入android的bugly 2. android端写一个Bugly上报管理类 3. 修改你工程目录下native\engine\common\Classes\目录下的Game.h, Game.cpp两个文件&…

发电厂主厂房智能照明控制系统的设计和应用

摘要&#xff1a;当前&#xff0c;电厂主厂房的照明规模较大&#xff0c;而且具有许多回路&#xff0c;增加了电厂照明负荷&#xff0c;导致照明过程中的能源消耗较高。对此&#xff0c;电厂需要合理设计智能照明系统&#xff0c;运用智能技术提高电厂照明的运行管理水平&#…

如何在化工行业运用IPD?

化工行业作为国民经济的重要基础性行业&#xff0c;包含数以万计的产品种类&#xff0c;各具有不同的物理化学特性。化工产品的消费同国民经济状况联系非常紧密&#xff0c;主要去向广泛分布于基建、房地产、农业、汽车、服装等国民经济各个领域。按应用领域划分&#xff0c;典…

PCA与SVD

PCA流程&#xff1a; 当数据维度大时&#xff0c;构建协方差矩阵并求其特征值、特征向量会导致计算量大。所以可以利用SVD求解。 PCA算法的优化目标就是: ①降维后同一维度的方差最大。 ②不同维度之间的相关性为0。 根据线性代数&#xff0c;我们可以知道同一元素的协方差就…

Django项目开发快速入门

Django项目开发快速入门 生成Django项目编写module后台管理系统admin自定义管理页面视图函数使用Django模板 生成Django项目 现在cmd中使用命令安装Django框架 pip install django3.2使用命令生成项目 django-admin startproject DjStore使用命令生成应用 python .\manage.…

管道模型--Asp.Net MVC篇 Http请求

管道模型–Asp.Net MVC篇 Http请求 我们自己写的程序,是怎样进行处理的?一个完整的HTTP请求流程: 一. 请求大致流程 拿一个实例了解整个流程的步骤: 用户浏览器输入地址 例如 http://www.csdn.net DNS解析(域名供应商) 将输入的网址解析成IP+端口 请求到达服务器Server I…

ChatGPT的应用场景和局限性,以及发展前景

目录 导语 ChatGPT的应用场景 ChatGPT的局限性 ChatGPT的发展前景 总结 导语 作为一款基于人工智能的自然语言处理(NLP)​​聊天机器人​​程序&#xff0c;ChatGPT通过大量来自互联网的文本进行训练&#xff0c;并使用深度学习和机器学习算法来理解用户的问题并提供回答。…

[RocketMQ] Broker CommitLogDispatcher 异步构建ConsumeQueue和IndexFile源码解析 (十四)

CommitLogDispatcherBuildConsumeQueue: 异步构建ConsumerQueue。CommitLogDispatcherBuildIndex: 异步构建IndexFile。 文章目录 1.CommitLogDispatcherBuildConsumeQueue构建ConsumeQueue1.1 putMessagePositionInfo写入消息位置信息1.2 findConsumeQueue查找ConsumeQueue1.2…

Windows Docker部署springboot微服务

Windows Docker部署springboot微服务 前言 偶然的机会让我能够实操在Windows server 2019版本的服务器上进行springCloud服务的部署 过程中深刻的体会到了为什么Docker要推荐使用Linux系列的系统进行操作 遇到的问题 springboot镜像打包微服务启动后nacos连不上使用的基础…

zabbix企业级监控(监控win10主机)---接小白到大神之路运维第63天

第三阶段基础 zabbix企业级监控监控win10主机 目录 Wind10配置&#xff1a; Web图形操作&#xff1a; Wind10配置&#xff1a; 服务器相关信息&#xff1a; 关闭防火墙、IP地址为192.168.59.128 1.首先在C盘根目录下创建zabbix的文件夹 2.将需要的文件拖到该文件夹内&…

CRM排名前三的的系统有哪些特点?

crm经过多年的发展&#xff0c;不仅可以管理好客户关系还是企业重要的战略武器。让企业的销售、市场营销和客服服务部门建立密切联系&#xff0c;在crm一个平台上处理商机&#xff0c;简化业务流程&#xff0c;为组织降本增效。国内crm系统排名哪些技术商更靠前&#xff1f; 1…

CISCN2023国赛复现

[CISCN 2023 初赛]被加密的生产流量 下载附件打开 他的题目叫modbus modbus是一种协议 在这些流量里都找不到有用信息&#xff0c;但是发现了有tcp的追踪流 打开看看 发现两个一组的这几行数字组合像是base编码 MMYMMX3GNEYMOXZRGAYDA 放到base家族解一下密 最后在base32解…

详解应用层的HTTP协议与HTTPS协议

文章目录 前言HTTP协议1. 理解应用层协议1. 什么是HTTP协议&#xff1f;2. HTTP协议工作流程3. HTTP报文格式3.1 HTTP请求方法3.2 HTTP请求报头3.3 HTTP请求正文3.4 HTTP响应的状态码3.4 HTTP响应的报头3.5 HTTP响应的正文3.6 HTTP请求的URL 4. POST请求与GET请求5. HTTP协议实…

结构型模式 - 装饰者模式

概述 我们先来看一个快餐店的例子。 快餐店有炒面、炒饭这些快餐&#xff0c;可以额外附加鸡蛋、火腿、培根这些配菜&#xff0c;当然加配菜需要额外加钱&#xff0c;每个配菜的价钱通常不太一样&#xff0c;那么计算总价就会显得比较麻烦。 使用继承的方式存在的问题&#x…

5G工业路由器实现AGV远程控制,智联物联无线物联网方案

随着AGV在制造业应用逐渐广泛&#xff0c;在生产车间传统的布线网络下&#xff0c;存在着接口不足、网络不稳定、数据丢失、故障异常的情况&#xff0c;技术人员无法及时观察AGV的数据情况&#xff0c;导致AGV出错率高&#xff0c;维护成本高等问题。 传统的AGV通信方式一般是…

【Python基础函数笔记】获取当前时间并写入日志

1.获取当前时间 import os from datetime import datetime import pytzdef get_cur_time():# 获取当前时间return datetime.strftime(datetime.now(pytz.timezone(Asia/Singapore)), %Y-%m-%d_%H-%M-%S)# 基础目录 basedir a logdir os.path.join(basedir, logs, str(args.n…

S3C2440的串口通信(UART)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、UART二、2440的uart资源2.1.uart配置流程2.2 RS2322.3 RS232接口 三. UART编程实现&#xff08;无缓存&#xff09;四. UART编程实现&#xff08;中断&…

Python多线程 threading 和多进程 multiprocessing

1. 并发 vs 并行 线程是程序执行的最小单位&#xff0c;一个进程可以由一个或多个线程组成&#xff0c;各个线程之间也是交叉执行。 并发&#xff0c;相当于单核CPU&#xff0c;宏观同时执行&#xff0c;微观高速切换 交替执行。多线程、高并发这些词语更多地出现在服务端程序…

机器学习(十七):实操_在Sklearn中的实现CART树的基本流程

全文共8000余字&#xff0c;预计阅读时间约16~27分钟 | 满满干货(附代码)&#xff0c;建议收藏&#xff01; 代码下载点这里 一、介绍 CART&#xff08;Classification and Regression Trees&#xff09;即分类回归树&#xff0c;是一种重要的机器学习算法&#xff0c;既可以…

3.8 Bootstrap 面包屑导航(Breadcrumbs)

文章目录 Bootstrap 面包屑导航&#xff08;Breadcrumbs&#xff09; Bootstrap 面包屑导航&#xff08;Breadcrumbs&#xff09; 面包屑导航&#xff08;Breadcrumbs&#xff09;是一种基于网站层次信息的显示方式。以博客为例&#xff0c;面包屑导航可以显示发布日期、类别或…