复习opencv:螺丝螺纹缺陷检测

news2024/11/25 6:49:42

螺牙缺陷检测

  • 简述
  • 去噪
    • 椒盐噪声
    • 高斯噪声
  • 小波变换
  • 引导滤波
  • 求最大凸包
  • 判断曲直
  • 全部代码

简述

  • 今天收到了一个检测螺牙缺陷的问题,当复习opencv练个手,记录一下基础知识。
  • 这里的代码是检测弯曲的,其他缺陷用yolo处理。
  • 东家给的图片有的是有干扰的(红框标识),所以要求一下最大凸包。
    在这里插入图片描述
  • 里面很多知识是复习用,最终代码在最后一行,给的101张图片,有2个弯曲度超过0.25,来到了0.33以上
  • 有个小技巧可以提高弯直的区分度,这里就不介绍了,需要的私信。

去噪

椒盐噪声

import cv2

img = cv2.imread('image.jpg')
median = cv2.medianBlur(img, 5)
cv2.imshow('Median filter', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

高斯噪声

import cv2

img = cv2.imread('image.jpg')
gaussian = cv2.GaussianBlur(img, (5,5), 0)
cv2.imshow('Gaussian filter', gaussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

小波变换

import cv2
import pywt

img = cv2.imread('image.jpg', 0)
coeffs = pywt.dwt2(img, 'haar')
cA, (cH, cV, cD) = coeffs
cv2.imshow('Wavelet denoising', pywt.idwt2((cA, (None, None, None)), 'haar'))
cv2.waitKey(0)
cv2.destroyAllWindows()

引导滤波

import numpy as np
import cv2

main_path="D:/Handletiling/NG_org_20230602103406819.bmp"

def guideFilter(I, p, winSize, eps):

    mean_I = cv2.blur(I, winSize)    
    mean_p = cv2.blur(p, winSize)       

    mean_II = cv2.blur(I * I, winSize)  
    mean_Ip = cv2.blur(I * p, winSize) 

    var_I = mean_II - mean_I * mean_I  
    cov_Ip = mean_Ip - mean_I * mean_p  

    a = cov_Ip / (var_I + eps)        
    b = mean_p - a * mean_I          

    mean_a = cv2.blur(a, winSize)     
    mean_b = cv2.blur(b, winSize)     

    q = mean_a * I + mean_b
    return q


if __name__ == '__main__':
    eps = 0.01
    winSize = (5,5)
    image = cv2.imread(main_path, cv2.IMREAD_ANYCOLOR)
    image = cv2.resize(image, None,fx=0.7, fy=0.7, interpolation=cv2.INTER_CUBIC)
    I = image/255.0        #将图像归一化
    p =I
    guideFilter_img = guideFilter(I, p, winSize, eps)

    # 保存导向滤波结果
    guideFilter_img  = guideFilter_img  * 255
    guideFilter_img [guideFilter_img  > 255] = 255
    guideFilter_img  = np.round(guideFilter_img )
    guideFilter_img  = guideFilter_img.astype(np.uint8)
    cv2.imshow("image",image)
    cv2.imshow("winSize_5", guideFilter_img )
    cv2.waitKey(0)
    cv2.destroyAllWindows()

求最大凸包

import cv2
import os
import numpy as np
from skimage.measure import label

main_path="D:\Handletiling\luoya/NG/NG_org_20230602103407364.bmp"

##method1 --opencv
def get_lagrest_connect_component1(img):

    # rgb->gray
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # gaussian filter
    img_gray = cv2.GaussianBlur(img_gray, (5, 5), 0)
    # binary exp-threshold=0
    _, img_gray = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV)  # ret==threshold
    # find contour
    contours, _ = cv2.findContours(img_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # cv2.drawContours(img_gray, contours, -1, 255, 3)

    # find the area_max region
    area = []
    for i in range(len(contours)):
        area.append(cv2.contourArea(contours[i]))
    if len(area) >= 1:
        max_idx = np.argmax(area)
        max_contour_area = area[max_idx]

        for k in range(len(contours)):
            if k != max_idx:
                cv2.fillPoly(img_gray, [contours[k]], 0)
    else:
        max_contour_area = 0

    return max_contour_area, img_gray

if __name__ == '__main__':
    img = cv2.imread(main_path)
    max_area, img_gray = get_lagrest_connect_component1(img)
    print(max_area)
    cv2.imwrite('img_gray.jpg', img_gray)

判断曲直

1.查找轮廓,提取凸包
2.获得点集
3.计算导数方差
4.比较阈值

def calccurl(str,thresh):
    img = cv2.imread(str)
    # cv2.imshow('src',img)
    #提取凸包
    max_area, img_gray =get_lagrest_connect_component1(img)

    gray = img_gray
    #阈值处理
    ret,binary = cv2.threshold(gray,127,255,0)
    #查找轮廓,提取凸包
    contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    hull = cv2.convexHull(contours[0])
    cv2.polylines(img_gray,[hull],True,(255,255,0),2)
    min_x=min(hull[:,0,0])
    max_x=max(hull[:,0,0])
    topList=[]
    bottomList=[]
    thresh_left=220
    thresh_right=30
    count=hull.shape[0]
    isthesame=False
    for i in range(hull.shape[0]):
        point = tuple(hull[i][0]) #  
        # cv2.circle(img, point, 1, (0, 255, 0) , 12)
        if point[0]<(max_x-thresh_right) and point[0]>(min_x+thresh_left):
            length=binary.shape[0]
            x1 = np.linspace(start=0, stop=length-1, num=length)
            temp=x1 * (binary[:, point[0]] / 255)
            n = np.sum(temp > 0)
            index=temp.sum()/(n*1.)
            # if i in[0,count-1]:
            #     if not isthesame:
            #         isthesame=True
            #     else:
            #         continue
            if point[1]>index:
                bottomList.append(point)
                # cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)
                # print(str(i) + ":", point)

            else:
                topList.append(point)
                # cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)
                # print(str(i) + ":", point)


    space = np.linspace(start=min_x+thresh_left, stop=max_x-thresh_right, num=15)
    space= np.ceil(space)
    length = img_gray.shape[0]
    x1 = np.linspace(start=0, stop=length - 1, num=length)
    tempM = (img_gray / 255.)* x1[:,None]

    if len(topList) >len(bottomList):
        topList.clear()
        for x in space:
            temp=tempM[:, int(x)]
            temp = temp[temp != 0]
            topList.append([x,temp.min()])
            # cv2.circle(img, (int(x),int(temp.min())), 1, (0, 255, 0), 12)
            # cv2.putText(img, str(x), (int(x),int(temp.min())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)

        line = np.array(topList, dtype=float)

    else:
        bottomList.clear()
        for x in space:
            temp = tempM[:, int(x)]
            temp = temp[temp != 0]
            bottomList.append([x, temp.max()])
            # cv2.circle(img, (int(x), int(temp.max())), 1, (0, 255, 0), 12)
            # cv2.putText(img, str(x), (int(x),int(temp.max())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)

        line = np.array(bottomList, dtype=float)
       if line.size > 0:
        #method1
        slopend=(line[-1,1]-line[0,1])/(line[-1,0]-line[0,0])
        slop=(line[1:,1]-line[:-1,1])/((line[1:,0]-line[:-1,0])+0.0001)
        dis=slop-slopend
        std = np.std(dis)
        if std>thresh:
            return 0,std

    return 1,0
        # method2
        # std= np.std(slop)


if __name__ == '__main__':
    filesPath = os.listdir(main_path)
    threshstd=0.025

    files = tqdm(filesPath)
    for file in files:
        absolute_file_path = os.path.join(main_path, file)
        if '.bmp' in absolute_file_path.lower():
            result,std=calccurl(absolute_file_path,threshstd)
            if result:
                print(absolute_file_path+":", std)

在这里插入图片描述

结果
--------------------
std: 0.037498851806574245

全部代码

import cv2
import numpy as np

import os
from tqdm import tqdm
import shutil

#需要检测弯曲的图片的文件夹地址
main_path="D:\Handletiling\src"

def get_lagrest_connect_component1(img):

    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    img_gray = cv2.GaussianBlur(img_gray, (5, 5), 0)

    _, img_gray = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY_INV)  # ret==threshold

    contours, _ = cv2.findContours(img_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    area = []
    for i in range(len(contours)):
        area.append(cv2.contourArea(contours[i]))
    if len(area) >= 1:
        max_idx = np.argmax(area)
        max_contour_area = area[max_idx]

        for k in range(len(contours)):
            if k != max_idx:
                cv2.fillPoly(img_gray, [contours[k]], 0)
    else:
        max_contour_area = 0

    return max_contour_area, img_gray

def calccurl(str,thresh):
    img = cv2.imread(str)

    #提取凸包
    max_area, img_gray =get_lagrest_connect_component1(img)

    gray = img_gray
    #阈值处理
    ret,binary = cv2.threshold(gray,127,255,0)
    #查找轮廓
    contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    hull = cv2.convexHull(contours[0])
    cv2.polylines(img_gray,[hull],True,(255,255,0),2)
    min_x=min(hull[:,0,0])
    max_x=max(hull[:,0,0])
    topList=[]
    bottomList=[]
    thresh_left=220
    thresh_right=30
    count=hull.shape[0]
    isthesame=False
    for i in range(hull.shape[0]):
        point = tuple(hull[i][0]) #
        # cv2.circle(img, point, 1, (0, 255, 0) , 12)
        if point[0]<(max_x-thresh_right) and point[0]>(min_x+thresh_left):
            length=binary.shape[0]
            x1 = np.linspace(start=0, stop=length-1, num=length)
            temp=x1 * (binary[:, point[0]] / 255)
            n = np.sum(temp > 0)
            index=temp.sum()/(n*1.)
            # if i in[0,count-1]:
            #     if not isthesame:
            #         isthesame=True
            #     else:
            #         continue
            if point[1]>index:
                bottomList.append(point)
                # cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)
                # print(str(i) + ":", point)

            else:
                topList.append(point)
                # cv2.putText(img, str(i), point, cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)
                # print(str(i) + ":", point)


    space = np.linspace(start=min_x+thresh_left, stop=max_x-thresh_right, num=15)
    space= np.ceil(space)
    length = img_gray.shape[0]
    x1 = np.linspace(start=0, stop=length - 1, num=length)
    tempM = (img_gray / 255.)* x1[:,None]

    if len(topList) >len(bottomList):
        topList.clear()
        for x in space:
            temp=tempM[:, int(x)]
            temp = temp[temp != 0]
            topList.append([x,temp.min()])
            # cv2.circle(img, (int(x),int(temp.min())), 1, (0, 255, 0), 12)
            # cv2.putText(img, str(x), (int(x),int(temp.min())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)

        line = np.array(topList, dtype=float)

    else:
        bottomList.clear()
        for x in space:
            temp = tempM[:, int(x)]
            temp = temp[temp != 0]
            bottomList.append([x, temp.max()])
            # cv2.circle(img, (int(x), int(temp.max())), 1, (0, 255, 0), 12)
            # cv2.putText(img, str(x), (int(x),int(temp.max())), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 3)

        line = np.array(bottomList, dtype=float)
    if line.size > 0:
        #method1
        slopend=(line[-1,1]-line[0,1])/(line[-1,0]-line[0,0])
        slop=(line[1:,1]-line[:-1,1])/((line[1:,0]-line[:-1,0])+0.0001)
        dis=slop-slopend
        std = np.std(dis)
        if std>thresh:
            return 0,std

    return 1,0
        # method2
        # std= np.std(slop)

  

if __name__ == '__main__':
    filesPath = os.listdir(main_path)
    threshstd=0.025

    files = tqdm(filesPath)
    for file in files:
        absolute_file_path = os.path.join(main_path, file)
        if '.bmp' in absolute_file_path.lower():
            result,std=calccurl(absolute_file_path,threshstd)
            if not result:
                print(absolute_file_path+"-图片弯曲:", std)
#结果
[00:00<00:01, 44.18it/s]D:\Handletiling\src\NG_org_20230602103409544.bmp-图片弯曲: 0.0334415572613885
[00:00<00:01, 44.24it/s]D:\Handletiling\src\NG_org_20230602103410530.bmp-图片弯曲: 0.037498851806574245

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

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

相关文章

激活函数》

一. 常用激活函数 1. Sigmoid函数 优点与不足之处 对应pytorch的代码 import torch import torch.nn as nn# Sigmoid函数 print(**25"Sigmoid函数""*"*25) m nn.Sigmoid() input torch.randn(2) print("原&#xff1a;",input) print("结…

RabbitMQ ---- Work Queues

RabbitMQ ---- Work Queues 1. 轮训分发消息1.1 抽取工具类1.2 启动两个工作线程1.3 启动一个发送线程1.4 结果展示 2. 消息应答2.1 概念2.2 自动应答2.3 消息应答的方法2.4 Multiple 的解释2.5 消息自动重新入队2.6 消息手动应答代码2.7 手动应答效果演示 3. RabbitMQ 持久化3…

RT-Thread 互补滤波器 (STM32 + 6 轴 IMU)

作者&#xff1a;wuhanstudio 原文链接&#xff1a;https://zhuanlan.zhihu.com/p/611568999 最近在看无人驾驶的 Prediction 部分&#xff0c;可以利用 EKF (Extended Kalman Filter) 融合不同传感器的数据&#xff0c;例如 IMU, Lidar 和 GNSS&#xff0c;从而给出更加准确的…

Go——基础语法

目录 Hello World&#xff01; 变量和常量 变量交换 匿名变量 常量 iota——特殊常量 基本数据类型 数据类型转换 运算符 算数运算符 关系运算符 逻辑运算符 位运算符号 ​编辑 赋值运算符 输入输出方法 流程控制 函数 可变参数类型 值传递和引用传递 Hello Wor…

性能测试 jmeter 的 beanshell 脚本的 2 个常用例子

目录 前言&#xff1a; Bean Shell 内置变量大全 例子 1 例子 2 技巧 前言&#xff1a; JMeter是一个功能强大的性能测试工具&#xff0c;而Beanshell是JMeter中用于编写脚本的一种语言。 在利用 jmeter 进行接口测试或者性能测试的时候&#xff0c;我们需要处理一些复杂…

使用GithubAction自动构建部署项目

GitHub Actions 是一种持续集成和持续交付(CI/CD) 平台&#xff0c;可用于自动执行生成、测试和部署管道。 您可以创建工作流程来构建和测试存储库的每个拉取请求&#xff0c;或将合并的拉取请求部署到生产环境。 GitHub Actions 不仅仅是DevOps&#xff0c;还允许您在存储库中…

基于linux下的高并发服务器开发(第一章)-GCC(2)1.3

04 / gcc 和 g的区别 gcc 和 g都是GNU&#xff08;组织&#xff09;的一个编译器 【误区一】&#xff1a;gcc只能编译 C 代码&#xff0c;g 只能编译 c 代码。两者都可以&#xff0c;请注意&#xff1a; 后缀为 .c 的&#xff0c;gcc 把它当做是 C 程序&#xff0c;而 g 当做是…

Debezium系列之:prometheus采集debezium的jmx数据,grafana通过dashboard展示debezium的jmx数据

Debezium系列之:prometheus采集debezium的jmx数据,grafana通过dashboard展示debezium的jmx数据 一、需求背景二、实现的效果三、导出debezium jmx四、debezium jmx重要指标五、部署prometheus和grafana六、Debezium MySQL Connector的dashboard七、debezium-dashboard.json八…

二叉树(上)——“数据结构与算法”

各位CSDN的uu们好呀&#xff0c;好久没有更新我的数据结构与算法专栏啦&#xff0c;今天&#xff0c;小雅兰继续来更新二叉树的内容&#xff0c;下面&#xff0c;让我们进入链式二叉树的世界吧&#xff01;&#xff01;&#xff01; 二叉树链式结构的实现 二叉树链式结构的实现…

性能测试工具 Jmeter 测试 Dubbo 接口脚本编写

目录 前言&#xff1a; 1、背景 2、工具准备 3、创建一个 maven 项目&#xff0c;此处可以创建一个 quickstart&#xff0c;参考截图 4、以上配置完毕后&#xff0c;开始撸代码 5、上面那个类是不需要从 jmeter 中获取参数&#xff0c;如果要从 jmeter 中获取相关的参数&…

低代码在边缘计算工业软件中的应用

近年来&#xff0c;边缘计算给工业现场带来了许多新的变化。由于计算、储存能力的大幅提升&#xff0c;边缘计算时代的新设备往往能够胜任多个复杂任务。另外&#xff0c;随着网络能力的提升&#xff0c;边缘设备与设备之间、边缘设备与工业互联网云平台之间的通讯延迟与带宽都…

Flowable边界事件-信号边界事件

信号边界事件 信号边界事件一、定义1. 图形标记2. 设置信号 选择信号3. XML标记 二、测试用例2.1 定时边界事件xml文件2.2 信号边界事件测试用例 总结 信号边界事件 一、定义 接收到信号触发事件 1. 图形标记 2. 设置信号 选择信号 3. XML标记 定时边界事件的XML <signal…

JMeter进行WebSocket压力测试

背景 之前两篇内容介绍了一下 WebSocket 和 SocketIO 的基础内容。之后用 Netty-SocketIO 开发了一个简单的服务端&#xff0c;支持服务端主动向客户端发送消息&#xff0c;同时也支持客户端请求&#xff0c;服务端响应方式。本文主要想了解一下服务端的性能怎么样&#xff0c;…

驱动开发-day9

驱动代码&#xff1a; #include <linux/cdev.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linu…

Hystrix熔断器

雪崩 当山坡积雪内部的内聚力抗拒不了它所受到的重力拉引时&#xff0c;积雪便向下滑动&#xff0c;引起⼤量雪体崩塌&#xff0c;人们把这种自然现象称作雪崩 微服务中&#xff0c;一个请求可能需要多个微服务接口才能实现&#xff0c;会形成复杂的调用链路 …

在Linux下通过MySQL二进制包安装MySQL5.7

在Linux下通过通用压缩包安装MySQL5.7 卸载MySQL 如果是第一次安装MySQL&#xff0c;在安装MySQL前&#xff0c;知道如何卸载MySQL是很有必要的。因为在安装过程中可能会 遇到各种各样的问题&#xff0c;自己玩的话 卸载重装即可。 1. find / -name mysql 查看MySQL相关包…

Layui之动态树 左侧树形菜单栏 详细全面

⭐ฅʕ•̫͡•ʔฅ本期看点&#xff1a;该篇是运用Layui框架来编写后台树形菜单栏&#xff0c;并且结合MySql来编写完成 目录 一.效果图 二.具体步骤 2.1 数据库 2.2 树形导航栏 第一个类&#xff1a;Treevo 第二个类&#xff1a;BuildTree&#xff1a; 2.3 Dao方法 2.3.…

【自我提升】Spring Data JPA之Specification动态查询详解

写在前面&#xff1a;刷完Spring Data JPA的课后&#xff0c;发现Specification动态查询还挺有意思的&#xff0c;还应用到了规约设计模式&#xff0c;在此记录下学习过程和见解。 目录 一、应用场景 二、源码解析 三、规约模式 四、实际应用 一、应用场景 1. 简介 有时我…

Linux中安装Tomcat

前提条件&#xff1a; 虚拟机中已经提前安装好jdk1.8。 安装步骤&#xff1a; 1.下载安装包 首先去Apache官网下载&#xff08;Apache Tomcat - Apache Tomcat 9 Software Downloads&#xff09; 2.上传到 linux 中&#xff0c;我这里上传的目录是&#xff1a; /opt 3. 解压…

element-plus坑总结

reactive和ref对比 // 定义变量 import { reactive } from vue; const person reactive({name: "John",age: 25, });// 赋值修改 person.name "Tom"; person.age 26;// 使用变量 <div>{{ person.name }}</div> <button click"perso…