opencv 图像雾检测_OpenCV之二值图像分析 – 缺陷检测二

本文介绍了如何使用OpenCV在Python和C++中进行图像雾检测,以及二值图像分析用于缺陷检测。通过对外接矩形进行排序和模板匹配,去除边缘差异,可以有效地识别和检测刀片上的缺陷或划痕。
摘要由CSDN通过智能技术生成

python代码:

import cv2 as cv
import numpy as np


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;


def get_template(binary, boxes):
    x, y, w, h = boxes[0]
    roi = binary[y:y+h, x:x+w]
    return roi


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
        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("./mask%d.png"%index, mask)
        index += 1
    return defect_rois


src = cv.imread("./test.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)

# 轮廓提取
out, 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.imwrite("./binary2.png", src)

cv.waitKey(0)
cv.destroyAllWindows()

cc58be00c8a0229aafc9f263462b3afd.png

C++代码:

#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
using namespace cv;
using namespace std;
void sort_box(vector<Rect> &boxes);
Mat get_template(Mat &binary, vector<Rect> rects);
void detect_defects(Mat &binary, vector<Rect> rects, Mat &tpl, vector<Rect> &defects);
int main(int argc, char** argv)
{
	Mat src = imread("./test.jpg");
	imshow("input", src);

	// ��ֵͼ��
	Mat gray, binary, result;
	cvtColor(src, gray, COLOR_BGR2GRAY);
	threshold(gray, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
	imshow("binary", binary);

	// ����ṹԪ��
	Mat se = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	morphologyEx(binary, binary, MORPH_OPEN, se);

	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	vector<Rect> rects;
	findContours(binary.clone(), contours, hierarchy, RETR_LIST, CHAIN_APPROX_SIMPLE);
	int height = src.rows;
	for (size_t t = 0; t < contours.size(); t++) {
		Rect rect = boundingRect(contours[t]);
		double area = contourArea(contours[t]);
		if (rect.height >(height / 2)) {
			continue;
		}
		if (area < 150)
			continue;
		rects.push_back(rect);
	}
	sort_box(rects);
	Mat tpl = get_template(binary, rects);
	for (size_t t = 0; t < contours.size(); t++) {
		Rect rect = boundingRect(contours[t]);
		double area = contourArea(contours[t]);
		if (rect.height >(height / 2)) {
			continue;
		}
		if (area < 150)
			continue;
		drawContours(binary, contours, t, Scalar(0), 2, 8);
	}
	vector<Rect> defects;
	for (int i = 0; i < rects.size(); i++) {
		putText(src, format("num: %d", (i+1)), Point(rects[i].x-40, rects[i].y+15), FONT_HERSHEY_PLAIN, 1.0, Scalar(255, 0, 0), 1);
	}
	detect_defects(binary, rects, tpl, defects);
	for (int i = 0; i < defects.size(); i++) {
		rectangle(src, defects[i], Scalar(0, 0, 255), 1, 8, 0);
		putText(src, "bad", Point(defects[i].x, defects[i].y), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 2);
	}
	// ��ʾ
	imshow("result", src);
	waitKey(0);
	return 0;
}


void sort_box(vector<Rect> &boxes) {
	int size = boxes.size();
	for (int i = 0; i < size - 1; i++) {
		for (int j = i; j < size; j++) {
			int x = boxes[j].x;
			int y = boxes[j].y;
			int w = boxes[j].width;
			int h = boxes[j].height;
			if (y < boxes[i].y) {
				Rect temp = boxes[i];
				boxes[i] = boxes[j];
				boxes[j] = temp;
			}
		}
	}
}
Mat get_template(Mat &binary, vector<Rect> rects) {
	return binary(rects[0]);
}
void detect_defects(Mat &binary, vector<Rect> rects, Mat &tpl, vector<Rect> &defects) {
	int height = tpl.rows;
	int width = tpl.cols;
	int index = 1;
	int size = rects.size();
	for (int i = 0; i < size; i++) {
		Mat roi = binary(rects[i]);
		resize(roi, roi, tpl.size());
		Mat mask;
		subtract(tpl, roi, mask);
		Mat se = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
		morphologyEx(mask, mask, MORPH_OPEN, se);
		threshold(mask, mask, 0, 255, THRESH_BINARY);
		int count = 0;
		for (int row = 0; row < height; row++) {
			for (int col = 0; col < width; col++) {
				int pv = mask.at<uchar>(row, col);
				if (pv == 255) {
					count++;
				}
			}
		}
		if (count > 0) {
			defects.push_back(rects[i]);
		}
	}
}

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

OpenCV学习笔记代码,欢迎follow:

MachineLP/OpenCV-​github.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值