一描馅、簡介
- 機(jī)器視覺應(yīng)用場景中缺陷檢測的應(yīng)用是非常廣泛的把夸,通常涉及各個行業(yè)、各種缺陷類型铭污。
- 紡織物的缺陷檢測恋日,缺陷類型包含臟污膀篮、油漬、線條破損三種岂膳,這三種缺陷與LCD屏幕檢測的缺陷很相似誓竿,處理方法也可借鑒。
- 使用OpenCV中的FindContours函數(shù)可以 實現(xiàn)紡織物缺陷檢測(臟污谈截、油漬筷屡、線條破損缺陷)。
二簸喂、FindContours函數(shù)
- FindContours函數(shù)
找輪廓
void findContours( InputOutputArray image,
OutputArrayOfArrays contours,
OutputArray hierarchy, int mode,
int method, Point offset = Point());
InputOutputArray image
:輸入圖像是8位單通道的圖像(256級灰度圖)毙死。
其中像素點的非0灰度值被當(dāng)成1(轉(zhuǎn)化后即為255),0值保持0喻鳄,所以輸入圖像被當(dāng)成一個二值圖像對待扼倘。
可以用compare() , inRange() , threshold() , adaptiveThreshold() , Canny()
或者其他方法來從灰度圖或者彩色圖中生成二值圖像。該函數(shù)在提取輪廓的過程中會改變圖像除呵。
如果第4個參數(shù) mode 為 CV_RETR_CCOMP 或者
CV_RETR_FLOODFILL再菊,輸入圖像也可以是32位的整型圖像(CV_32SC1)。OutputArrayOfArrays contours
: 檢測到的輪廓
Each contour is stored as a vector of points. 每個輪廓會被存儲為vector<Point>
所以 contours 的類型是vector<vector<Point>>
颜曾。OutputArray hierarchy
: 可選的輸出向量袄简,包含圖像的拓?fù)湫畔?br> It has as many elements as the number of contours. 元素個數(shù) = 輪廓數(shù)
對于第 i 個輪廓contours[i]
,hierarchy 的以下元素分別表示
hierarchy[i][0]: the next contour at the same hierarchical level
hierarchy[i][1]: the previous contour at the same hierarchical level
hierarchy[i][2]: the first child contour
hierarchy[i][3]: the parent contour
hierarchy 的這些元素的原始值為0泛啸,如果不存在绿语,置為負(fù)數(shù)int mode
: Contour retrieval mode 取回輪廓模式(復(fù)雜度依次增加)
三、檢測條件
先進(jìn)行二值化候址、高斯濾波吕粹、平滑等處理。再進(jìn)行輪廓分析岗仑。
- 臟污
輪廓圓弧長度大于1 - 油漬
輪廓面積大于50 -
線條破損
輪廓圓弧長度大于10
四匹耕、程序源碼
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Sunny.UI;
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace Ky_FindContours
{
public partial class Form1 : UIForm
{
public Form1()
{
InitializeComponent();
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
}
private Image image = null;
private Mat dst = new Mat();
private Mat src_img;
string filePath = "";
private List<Mat> reList = new List<Mat>();
private int step = 1;
private void openImage_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = "選擇操作的圖片";
openFileDialog.Filter = "圖片 *.jpg|*.jpg|圖像*.png|*.png";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
filePath = openFileDialog.FileName;
image = Image.FromFile(filePath);
src_img = Cv2.ImRead(filePath);
Mat tem1 = new Mat();
src_img.CopyTo(tem1);
if (reList.Count > 0)
{
reList[0] = tem1;
}
else
{
reList.Add(tem1);
}
}
if (filePath != "")
{
picBoxShowDel.Image = image;
picShowOri.Image = image;
}
}
/// <summary>
/// 臟污缺陷檢測
/// </summary>
/// <param name="img">測試圖像</param>
/// <returns>結(jié)果圖</returns> //也可設(shè)置bool類型表示OK或NG
static Mat DirtyDetection(Mat img)
{
Mat result = img.Clone();
Mat gray = new Mat();
Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY);
Cv2.GaussianBlur(gray, gray, new OpenCvSharp.Size(7, 7), 0);
Cv2.Canny(gray, gray, 10, 30);
OpenCvSharp.Point[][] contours; //輪廓查找結(jié)果變量
HierarchyIndex[] hierarchy; //輪廓拓?fù)浣Y(jié)構(gòu)變量
Cv2.FindContours(gray, out contours, out hierarchy, RetrievalModes.External,
ContourApproximationModes.ApproxNone);
//Console.WriteLine("contour_size = {0}", contours.Length); //輸出輪廓個數(shù)
for (int i = 0; i < contours.Length; i++)
{
double length = Cv2.ArcLength(contours[i], true);
if (length >= 1)
Cv2.DrawContours(result, contours, i, new Scalar(0, 0, 255), 2);
}
return result;
}
/// <summary>
/// 油污缺陷檢測
/// </summary>
/// <param name="img">測試圖像</param>
/// <returns>結(jié)果圖</returns> //也可設(shè)置bool類型表示OK或NG
static Mat OilDetection(Mat img)
{
Mat result = img.Clone();
Mat imgLab = new Mat();
Cv2.CvtColor(img, imgLab, ColorConversionCodes.BGR2Lab);
Mat[] labArray = Cv2.Split(imgLab); //L, a, b
Mat blur = new Mat();
Mat thres = new Mat();
Cv2.GaussianBlur(labArray[2], blur, new OpenCvSharp.Size(3, 3), 0); //b通道
Cv2.Threshold(blur, thres, 130, 255, ThresholdTypes.Binary);
Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3), new OpenCvSharp.Point(-1, -1));
Cv2.MorphologyEx(thres, thres, MorphTypes.Open, element, new OpenCvSharp.Point(-1, -1), 1,
BorderTypes.Default, new Scalar());
OpenCvSharp.Point[][] contours; //輪廓查找結(jié)果變量
HierarchyIndex[] hierarchy; //輪廓拓?fù)浣Y(jié)構(gòu)變量
Cv2.FindContours(thres, out contours, out hierarchy, RetrievalModes.External,
ContourApproximationModes.ApproxNone);
//Console.WriteLine("contour_size = {0}", contours.Length); //輸出輪廓個數(shù)
for (int i = 0; i < contours.Length; i++)
{
double area = Cv2.ContourArea(contours[i]);
if (area >= 50)
Cv2.DrawContours(result, contours, i, new Scalar(0, 0, 255), 2);
}
return result;
}
/// <summary>
/// 線條破損缺陷檢測
/// </summary>
/// <param name="img">測試圖像</param>
/// <returns>結(jié)果圖</returns> //也可設(shè)置bool類型表示OK或NG
static Mat LineDefectDetection(Mat img)
{
Mat result = img.Clone();
Mat imgLab = new Mat();
Cv2.CvtColor(img, imgLab, ColorConversionCodes.BGR2Lab);
Mat[] labArray = Cv2.Split(imgLab); //L, a, b
Mat blur = new Mat();
Mat edged = new Mat();
Cv2.GaussianBlur(labArray[2], blur, new OpenCvSharp.Size(3, 3), 0); //b通道
Cv2.Canny(blur, edged, 5, 10);
OpenCvSharp.Point[][] contours; //輪廓查找結(jié)果變量
HierarchyIndex[] hierarchy; //輪廓拓?fù)浣Y(jié)構(gòu)變量
Cv2.FindContours(edged, out contours, out hierarchy, RetrievalModes.External,
ContourApproximationModes.ApproxNone);
//Console.WriteLine("contour_size = {0}", contours.Length); //輸出輪廓個數(shù)
for (int i = 0; i < contours.Length; i++)
{
double length = Cv2.ArcLength(contours[i], true);
if (length >= 10)
Cv2.DrawContours(result, contours, i, new Scalar(0, 0, 255), 2);
}
return result;
}
private void uiButton1_Click(object sender, EventArgs e)
{
Mat zw_result = DirtyDetection(src_img); //臟污缺陷檢測
picBoxShowDel.Image = zw_result.ToBitmap();
}
private void uiButton2_Click(object sender, EventArgs e)
{
Mat yw_result = OilDetection(src_img); //油污缺陷檢測
picBoxShowDel.Image = yw_result.ToBitmap();
}
private void uiButton3_Click(object sender, EventArgs e)
{
Mat yw_result = LineDefectDetection(src_img); //線條破損缺陷檢測
picBoxShowDel.Image = yw_result.ToBitmap();
}
}
}
五、參考資料
博客:https://blog.51cto.com/stq054188/5543992
來源公眾號:OpenCV與AI深度學(xué)習(xí)