基于python-opencv实现木质工件的污渍和划痕识别和分类

缺陷识别

简介:
这个项目是我的本科毕业设计,主要针对传送带上的木质圆形工件的缺陷识别和分类,并且进行工件的计数和缺陷工件的计数。这里我主要是识别污渍和划痕

缺陷类型

污渍:
在这里插入图片描述
划痕:
在这里插入图片描述

最后的成果

在这里插入图片描述

在这里插入图片描述

  • sum:为工件的总个数
  • scratch_num:为含有划痕工件的总个数
  • blot_num:为含有污渍工件的总个数
  • 黄颜色圈住的缺陷为划痕
  • 蓝颜色圈住的缺陷为污渍

简单思路

  1. 通过边缘检测,得到每个工件的坐标,并计算出工件的中心来标记工件的ID
  2. 通过工件的每一帧位移量来确定是否为同一个工件
  3. 将每一个工件截取出来,进行缺陷的提取
  4. 将提取的缺陷进行直方图计算,通过直方图来值归一化,通过颜色值分布来分类缺陷

缺陷识别和分类

缺陷一:污渍的直方图
提取缺陷
在这里插入图片描述
缺陷处的直方图
在这里插入图片描述
提取缺陷
在这里插入图片描述
缺陷处的直方图
在这里插入图片描述
缺陷二:划痕的直方图
提取缺陷
在这里插入图片描述
缺陷处的直方图
在这里插入图片描述
提取缺陷
在这里插入图片描述
缺陷处的直方图
在这里插入图片描述
由上方缺陷的直方图值分析可得,污渍的颜色值主要分布在50左右,划痕的颜色值主要分布在100左右。因此通过颜色分布即可对对缺陷进行分类,将直方图归一化方便确定颜色的分布,代码如下

ret = img[y:y + h, x: x + w]
# 提取缺陷
gray = cv2.cvtColor(ret, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 135, 250, cv2.THRESH_BINARY_INV)[1]
contours, hierarchy =cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
mask = np.zeros(gray.shape).astype(gray.dtype)
cv2.fillPoly(mask, contours, (255, 255, 255))
result = cv2.bitwise_and(gray, mask)

# 直方图计算
hist = cv2.calcHist([result], [0], None, [255], [1, 256])
s = sum(hist)
# 归一化
for i in range(len(hist)):
	if hist[i] > 0:
		hist[i] = hist[i] / s

# 判断缺陷
hist_sum_scratch = 0
hist_sum_blot = 0
for i in range(90, 135):
	hist_sum_scratch = hist_sum_scratch + hist[i]

for i in range(15, 90):
	hist_sum_blot = hist_sum_blot + hist[i]

if hist_sum_scratch > 0.6:
	d = defects.Defect(1, x, y, w, h)
	self.defects.append(d)
    self.state = 1
    print("此处缺陷划痕")

if hist_sum_blot > 0.6:
    d = defects.Defect(2, x, y, w, h)
    self.defects.append(d)
    self.state = 2
    print("此处缺陷污渍")

全部程序

主程序:

import numpy as np
import cv2
import Products as product

# 加载视频
cap = cv2.VideoCapture("F:/FFOutput/8-1.mp4")

# 变量
font = cv2.FONT_HERSHEY_SIMPLEX
products = []
pid = 1
areaTh = 18000
# 获取图像width, height
width = cap.get(3)
height = cap.get(3)

while cap.isOpened():
    ret, frame = cap.read()

    try:
        # 复制图片,用于绘制
        img = frame.copy()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)[1]

    except:
        print("EOF")
        break

    # 边缘检测,识别工件
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > areaTh:
            M = cv2.moments(cnt)
            cx = int(M['m10'] / M['m00'])
            cy = int(M['m01'] / M['m00'])
            x, y, w, h = cv2.boundingRect(cnt)
            new = True
            if cx > 100:
                for i in products:
                    if abs(cx - i.getX()) <= 25 and abs(cy - i.getY()) <= 25:
                        new = False
                        i.updateCoords(cx, cy, x, y, w, h)
                if new:
                    p = product.Product(pid, cx, cy, x, y, w, h)
                    p.save_pic(frame)
                    products.append(p)
                    product.count = pid
                    defects = p.defect_detect()
                    pid += 1
                cv2.circle(img, (cx, cy), 5, (0, 0, 255), -1)
                img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
    for i in products:
        # 标记ID
        if i.getX() <= 600:
            cv2.putText(img, str(i.getId()), (i.getX(), i.getY()), font, 1.0, i.getRGB(), 1, cv2.LINE_AA)

            # 绘制缺陷
            for j in i.defects:
                if j.getState() == 1:
                    img = cv2.rectangle(img, (i.getBoundX() + j.getX(), i.getBoundY() + j.getY()),
                                        (i.getBoundX() + j.getX() + j.getW() + 5,
                                         i.getBoundY() + j.getY() + j.getH() + 5),
                                        (0, 255, 255),
                                        1)
                elif j.getState() == 2:
                    img = cv2.rectangle(img, (i.getBoundX() + j.getX(), i.getBoundY() + j.getY()),
                                        (i.getBoundX() + j.getX() + j.getW() + 5,
                                         i.getBoundY() + j.getY() + j.getH() + 5),
                                        (255, 255, 0),
                                        1)
        # 绘制sum
        cv2.putText(img, "sum:" + str(product.count), (10, 30), font, 0.7, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(img, "scratch_sum:" + str(product.Product.scratch_sum), (10, 50), font, 0.7, (0, 255, 255), 1,
                    cv2.LINE_AA)
        cv2.putText(img, "blot_sum:" + str(product.Product.blot_sum), (10, 70), font, 0.7, (255, 255, 0), 1,
                    cv2.LINE_AA)
    cv2.imshow("test", img)
    k = cv2.waitKey(10) & 0xff
    if k == 27:
        break
cv2.destroyAllWindows()

工件对象:

from random import randint
import cv2
import numpy as np
import Defects as defects
from matplotlib import pyplot as plt


class Product:
    scratch_sum = 0
    blot_sum = 0
    count = 0

    def __init__(self, p, xi, yi, x, y, w, h):
        # 工件ID
        self.pid = p
        # 中心坐标
        self.centre_x = xi
        self.centre_y = yi
        # 边框
        self.bound_x = x
        self.bound_y = y
        self.bound_w = w
        self.bound_h = h
        # 颜色
        self.R = randint(0, 255)
        self.G = randint(0, 255)
        self.B = randint(0, 255)
        # 运动轨迹
        self.tracks = []
        # 0代表正常,1代表工件存在划痕,2代表工件存在污渍
        self.state = 0
        self.sample = 0
        # 储存缺陷对象
        self.defects = []

    # 获取ID
    def getId(self):
        return self.pid

    def getBoundX(self):
        return self.bound_x

    def getBoundY(self):
        return self.bound_y

    def getBoundW(self):
        return self.bound_w

    def getBoundH(self):
        return self.bound_h

    def getX(self):  # 获取中心x
        return self.centre_x

    def getY(self):  # 获取中心y
        return self.centre_y

    # 更新位置
    def updateCoords(self, xn, yn, x, y, w, h):
        self.centre_x = xn
        self.centre_y = yn
        self.bound_x = x
        self.bound_y = y
        self.bound_w = w
        self.bound_h = h
        # 增加轨迹位置
        self.tracks.append([self.centre_x, self.centre_y])

    # 获取轨迹
    def getTracks(self):
        return self.tracks

    # 获取标记颜色
    def getRGB(self):
        return self.R, self.G, self.B

    # 保存
    def save_pic(self, frame):
        pic = frame[self.bound_y:self.bound_y + self.bound_h, self.bound_x:self.bound_x + self.bound_w]
        self.sample = pic
        # 改变图像大小
        cv2.imwrite("F:/image" + str(self.pid) + ".jpg", pic)

    # 缺陷识别和分类
    def defect_detect(self):
        gray = cv2.cvtColor(self.sample, cv2.COLOR_BGR2GRAY)
        thresh = cv2.threshold(gray, 135, 250, cv2.THRESH_BINARY)[1]
        contour, hierar = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
        img = self.sample.copy()
        for cnt in contour:
            area = cv2.contourArea(cnt)
            if 100 < area <= 15000:
                x, y, w, h = cv2.boundingRect(cnt)
                ret = img[y:y + h, x: x + w]
                # 提取缺陷
                gray = cv2.cvtColor(ret, cv2.COLOR_BGR2GRAY)
                thresh = cv2.threshold(gray, 135, 250, cv2.THRESH_BINARY_INV)[1]
                contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
                mask = np.zeros(gray.shape).astype(gray.dtype)
                cv2.fillPoly(mask, contours, (255, 255, 255))
                result = cv2.bitwise_and(gray, mask)

                # 直方图计算
                hist = cv2.calcHist([result], [0], None, [255], [1, 256])
                s = sum(hist)
                # 判断缺陷
                for i in range(len(hist)):
                    if hist[i] > 0:
                        hist[i] = hist[i] / s

                # 判断缺陷
                hist_sum_scratch = 0
                hist_sum_blot = 0
                for i in range(90, 135):
                    hist_sum_scratch = hist_sum_scratch + hist[i]

                for i in range(15, 90):
                    hist_sum_blot = hist_sum_blot + hist[i]

                if hist_sum_scratch > 0.6:
                    d = defects.Defect(1, x, y, w, h)
                    self.defects.append(d)
                    self.state = 1
                    # print("此处缺陷划痕")

                if hist_sum_blot > 0.6:
                    d = defects.Defect(2, x, y, w, h)
                    self.defects.append(d)
                    self.state = 2
                    # print("此处缺陷污渍")

        if self.state == 1:
            Product.scratch_sum = Product.scratch_sum + 1
        elif self.state == 2:
            Product.blot_sum = Product.blot_sum + 1

        return self.defects

缺陷对象:

class Defect:
    def __init__(self, state, x, y, w, h):
        self.state = state
        self.bound_x = x
        self.bound_y = y
        self.bound_w = w
        self.bound_h = h

    def getX(self):
        return self.bound_x

    def getY(self):
        return self.bound_y

    def getW(self):
        return self.bound_w

    def getH(self):
        return self.bound_h

    def getState(self):
        return self.state


总结

做出这些东西,所有的灵感都是来自csdn上各种关于图像处理的文章。可能做得并不是很好,但是还是想分享出来,也许会帮到更多的人。

猜你喜欢

转载自blog.csdn.net/weixin_44736584/article/details/105737739