本文针对织布生产过程中,由于断针造成的织布缺陷图像,进行检测,如下图1所示.
1. 图像质量增强
由于织布原图的图像整体偏暗,不利于缺陷部分的检测,考虑改善图像质量,而图像质量增强的算法有很多,本文借鉴Retinex的图像增强算法(SSR, MSR, MSRCR)的实现,效果如图2所示.
参考:https://blog.csdn.net/ajianyingxiaoqinghan/article/details/71435098
2. 低通滤波/边缘检测
观测图像2中增强后的图像,虽然织布瑕疵部分,相对正常区域有明显的细长暗条纹痕迹,但是如果直接使用边缘检测的方式,来定位瑕疵部分的边缘,很难找到明显的边界条纹(受织布正常纹理部分的影响,如图3的对比效果图所示).
这里用低通滤波器,实现对织布纹理背景的过滤,以提供织布瑕疵缺陷的高频细节部分,利于后续的边缘检测效果.
低通滤波算法,参考:https://blog.csdn.net/weixin_40647819/article/details/80600918?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param
边缘检测算法,参考:https://blog.csdn.net/dieju8330/article/details/82814529?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
3. 形态学处理
对边缘检测后的图像,进行形态学的膨胀处理,就可以增大缺陷区域的轮廓,以便于利用opencv中找轮廓的方式,定位瑕疵部分的位置.
4. 定位瑕疵区域
对形态学处理后的图像,利用opencv中的findContours()函数,通过轮廓的宽高、面积大小等条件设置,来定位织布的瑕疵轮廓区域,具体实现参见代码部分:
5. 实现代码部分
MSRCR.h
#pragma once #ifndef _MSRCR_H_ #define _MSRCR_H_ #include "cv.h" #include "highgui.h" #include "opencv2\opencv.hpp" #include <math.h> // 该处使用USE_EXACT_SIGMA,则使用自定义的滤波算法; // 不使用USE_EXACT_SIGMA,则使用OpenCV自带的高斯滤波算法; //#define USE_EXACT_SIGMA using namespace cv; using namespace std; class Msrcr { private: #define pc(image, x, y, c) image->imageData[(image->widthStep * y) + (image->nChannels * x) + c] #define INT_PREC 1024.0 #define INT_PREC_BITS 10 inline double int2double(int x) { return (double)x / INT_PREC; } inline int double2int(double x) { return (int)(x * INT_PREC + 0.5); } inline int int2smallint(int x) { return (x >> INT_PREC_BITS); } inline int int2bigint(int x) { return (x << INT_PREC_BITS); } public: vector<double> CreateKernel(double sigma); vector<int> CreateFastKernel(double sigma); void FilterGaussian(IplImage* img, double sigma); void FilterGaussian(Mat src, Mat &dst, double sigma); void FastFilter(IplImage *img, double sigma); void FastFilter(Mat src, Mat &dst, double sigma); void Retinex(IplImage *img, double sigma, int gain = 128, int offset = 128); void Retinex(Mat src, Mat &dst, double sigma, int gain = 128, int offset = 128); void MultiScaleRetinex(IplImage *img, vector<double> weights, vector<double> sigmas, int gain = 128, int offset = 128); void MultiScaleRetinex(Mat src, Mat &dst, vector<double> weights, vector<double> sigmas, int gain = 128, int offset = 128); void MultiScaleRetinexCR(IplImage *img, vector<double> weights, vector<double> sigmas, int gain = 128, int offset = 128, double restoration_factor = 6, double color_gain = 2); void MultiScaleRetinexCR(Mat src, Mat &dst, vector<double> weights, vector<double> sigmas, int gain = 128, int offset = 128, double restoration_factor = 6, double color_gain = 2); }; #endif