【OpenCV】73 二值图像分析—缺陷检测二

73 二值图像分析—缺陷检测二

代码

import cv2 as cv
import numpy as np

# 冒泡排序,比较前后两个候选框的y值
def sort_boxes(rois):
    for i in range(0, len(rois)-1, 1):
        for j in range(i, len(rois), 1):
            x, y, w, h = rois[j]
            if y < rois[i][1]:
                bx, by, bw, bh = rois[i]
                rois[i] = [x, y, w, h]
                rois[j] = [bx, by, bw, bh]
    return rois;

# 在binary图上获取template
def get_template(binary, boxes):
    x, y, w, h = boxes[0]
    roi = binary[y:y+h, x:x+w]
    return roi

# 缺陷检测,分别传入binary,候选框,模板
def detect_defect(binary, boxes, tpl):
    height, width = tpl.shape
    index = 1
    defect_rois = []
    # 发现缺失
    for x, y, w, h in boxes:
        roi = binary[y:y + h, x:x + w]
        roi = cv.resize(roi, (width, height))
        mask = cv.subtract(tpl, roi)
        se = cv.getStructuringElement(cv.MORPH_RECT, (5, 5), (-1, -1))
        mask = cv.morphologyEx(mask, cv.MORPH_OPEN, se)
        ret, mask = cv.threshold(mask, 0, 255, cv.THRESH_BINARY)
        count = 0
        # 发现与模板有不一致的区域,统计像素值,若大于0,index+1
        for row in range(height):
            for col in range(width):
                pv = mask[row, col]
                if pv == 255:
                    count += 1
        if count > 0:
            defect_rois.append([x, y, w, h])
        cv.imwrite("D:/mask%d.png"%index, mask)
        index += 1
    return defect_rois

src = cv.imread("../images/ce_02.jpg")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)

# 图像二值化
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)

# 开操作。扩大图像缺口
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, se)
cv.imshow("binary", binary)

# 轮廓提取
contours, hierarchy = cv.findContours(binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
height, width = src.shape[:2]
rects = []
for c in range(len(contours)):
    x, y, w, h = cv.boundingRect(contours[c])
    area = cv.contourArea(contours[c])
    if h > (height//2):
        continue
    if area < 150:
        continue
    rects.append([x, y, w, h])

# 排序轮廓
rects = sort_boxes(rects)
print(rects)
template = get_template(binary, rects);

# 填充边缘
for c in range(len(contours)):
    x, y, w, h = cv.boundingRect(contours[c])
    area = cv.contourArea(contours[c])
    if h > (height//2):
        continue
    if area < 150:
        continue
    cv.drawContours(binary, contours, c, (0), 2, 8)
cv.imshow("template", template)

# 检测缺陷
defect_boxes = detect_defect(binary, rects, template)
for dx, dy, dw, dh in defect_boxes:
    cv.rectangle(src, (dx, dy), (dx + dw, dy + dh), (0, 0, 255), 1, 8, 0)
    cv.putText(src, "bad", (dx, dy), cv.FONT_HERSHEY_PLAIN, 1.0, (0, 255, 0), 2)

index = 1
for dx, dy, dw, dh in rects:
    cv.putText(src, "num:%d"%index, (dx-40, dy+15), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0), 1)
    index += 1

cv.imshow("result", src)
cv.waitKey(0)
cv.destroyAllWindows()

实验结果

在这里插入图片描述

解释

对于得到的刀片外接矩形,首先需要通过排序,确定他们的编号,然后根据模板进行相减得到与模板不同的区域,对这些区域进行形态学操作,去掉边缘细微差异,最终就得到了可以检出的缺陷或者划痕刀片。具体实现见代码。


所有内容均来源于贾志刚老师的知识星球——OpenCV研习社,本文为个人整理学习,已获得贾老师授权,有兴趣、有能力的可以加入贾老师的知识星球进行深入学习。
在这里插入图片描述

发布了111 篇原创文章 · 获赞 0 · 访问量 1677

猜你喜欢

转载自blog.csdn.net/liu_taiting/article/details/104961271
今日推荐