基EmguCv/OpenCv的零件的缺陷检测
2017-02-17 10:48
399 查看
基EmguCv/OpenCv的零件的缺陷检测
思路:
对图像去噪和二值化处理;
提取外部轮廓,并填充;
提取内部轮廓并以另一种颜色填充;
外轮廓和内轮廓叠加,得到缺陷区域;
对缺陷区域做二值化处理,并提取轮廓计算缺陷面积;
标记处缺陷位置。
存在的缺陷:只能检测外测缺陷,无法检测内部缺陷。
效果图
源代码(c#)
思路:
对图像去噪和二值化处理;
提取外部轮廓,并填充;
提取内部轮廓并以另一种颜色填充;
外轮廓和内轮廓叠加,得到缺陷区域;
对缺陷区域做二值化处理,并提取轮廓计算缺陷面积;
标记处缺陷位置。
存在的缺陷:只能检测外测缺陷,无法检测内部缺陷。
效果图
源代码(c#)
using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using Emgu.CV.Util; using System; using System.Drawing; using System.IO; using System.Windows.Forms; namespace DefectDetection2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private string[] FileNmae = null;//读取文件夹下的文件 private int times = 0;//上一张/下一张按钮点击次数(对应图片数组的索引) private int ErodeVaule = 1, DelitVaule = 1;//膨胀/腐蚀运算 private Image<Bgr, byte> picture = null;//原始图片 private int BinVaule = 0;//二值化阈值 private int y = 0, cr_min = 0, cb_min = 0, cr_max = 0,cb_max=0;//YCC颜色阈值 private double area1 = 0, area2 = 0;//缺陷面积 /// <summary> /// Erode值 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void domainUpDown1_SelectedItemChanged(object sender, EventArgs e) { ErodeVaule = Convert.ToInt16(domainUpDown1.Text); } /// <summary> /// Delite值 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void domainUpDown2_SelectedItemChanged(object sender, EventArgs e) { DelitVaule = Convert.ToInt16(domainUpDown2.Text); } /// <summary> /// 选择图片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { pictureBox2.Image = Image.FromFile(ofd.FileName); picture = new Image<Bgr, byte>(ofd.FileName); Image <Bgr ,byte >pic= new Image<Bgr, byte>(PicSubtraction(ContourFilling(ToBin(picture)), ContourFilling2(ToBin(picture))).Bitmap); pictureBox1.Image = ContourFilling3(pic).Bitmap; label4.Text = Path.GetFileName(ofd.FileName); } } /// <summary> /// 上一张 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { FileNmae = Directory.GetFiles(@"D:\work\HCI\工件样品"); times--; if (times < 0) times = FileNmae.Length - 1; picture = new Image<Bgr, byte>(FileNmae[times]); pictureBox2.Image = Image.FromFile(FileNmae[times]); label4.Text = Path.GetFileName(FileNmae[times]); Image<Bgr, byte> pic = new Image<Bgr, byte>(PicSubtraction(ContourFilling(ToBin(picture)), ContourFilling2(ToBin(picture))).Bitmap); pictureBox1.Image = ContourFilling3(pic).Bitmap; } /// <summary> /// 下一张 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) { FileNmae = Directory.GetFiles(@"D:\work\HCI\工件样品"); times++; if (times > FileNmae.Length - 1) times = 0; picture = new Image<Bgr, byte>(FileNmae[times]); pictureBox2.Image = Image.FromFile(FileNmae[times]); label4.Text = Path.GetFileName(FileNmae[times]); Image<Bgr, byte> pic = new Image<Bgr, byte>(PicSubtraction(ContourFilling(ToBin(picture)), ContourFilling2(ToBin(picture))).Bitmap); pictureBox1.Image = ContourFilling3(pic).Bitmap; } /// <summary> /// 二值化 /// </summary> /// <param name="pic">输入Bgr图片</param> /// <returns></returns> private Image<Gray, byte> ToBin(Image<Bgr, byte> pic) { Image<Gray, byte> outpic = pic.Convert<Gray, byte>(); outpic = outpic.ThresholdBinary(new Gray(100), new Gray(255)); outpic = outpic.Erode(ErodeVaule); outpic = outpic.Dilate(DelitVaule); return outpic; } /// <summary> /// 补全轮廓并填充 /// </summary> /// <param name="pic">输入灰度图</param> /// <returns></returns> private Image<Bgr, byte> ContourFilling(Image<Gray, byte> pic) { Image<Bgr, byte> outpic = new Image<Bgr, byte>(pic.Size); pic = pic.Canny(100, 255); Image<Gray, byte> outcon = new Image<Gray, byte>(pic.Size); VectorOfVectorOfPoint con = new VectorOfVectorOfPoint(); CvInvoke.FindContours(pic, con, outcon, RetrType.External, ChainApproxMethod.ChainApproxNone); Point[][] con1 = con.ToArrayOfArray(); PointF[][] con2 = Array.ConvertAll(con1, new Converter<Point[], PointF[]>(PointToPointF)); PointF[] hull = new PointF[con[0].Size]; for (int i = 0; i < con.Size; i++) { hull = CvInvoke.ConvexHull(con2[i], true); for (int j = 0; j < hull.Length; j++) { Point p1 = new Point((int)(hull[j].X + 0.5), (int)(hull[j].Y + 0.5)); Point p2; if (j == hull.Length - 1) { p2 = new Point((int)(hull[0].X + 0.5), (int)(hull[0].Y + 0.5)); } else p2 = new Point((int)(hull[j + 1].X + 0.5), (int)(hull[j + 1].Y + 0.5)); CvInvoke.Line(outpic, p1, p2, new MCvScalar(255, 0, 255, 255), 2, 0, 0); } } Image<Gray, byte> gray = new Image<Gray, byte>(pic.Size); gray = outpic.Convert<Gray, byte>(); gray = gray.ThresholdBinary(new Gray(100), new Gray(255)); gray = gray.Canny(100, 255); VectorOfVectorOfPoint con3 = new VectorOfVectorOfPoint(); CvInvoke.FindContours(gray, con3, outcon, RetrType.External, ChainApproxMethod.ChainApproxNone); for (int i = 0; i < con3.Size; i++) { CvInvoke.DrawContours(outpic, con3, i, new MCvScalar(255, 0, 0), -1); } return outpic; } /// <summary> /// 填充缺陷轮廓 /// </summary> /// <param name="pic"></param> /// <returns></returns> private Image<Bgr, byte> ContourFilling2(Image<Gray, byte> pic) { Image<Bgr, byte> outpic = new Image<Bgr, byte>(pic.Size); pic = pic.Canny(100, 255); Image<Gray, byte> outcon = new Image<Gray, byte>(pic.Size); VectorOfVectorOfPoint con = new VectorOfVectorOfPoint(); CvInvoke.FindContours(pic, con, outcon, RetrType.External, ChainApproxMethod.ChainApproxNone); for (int i = 0; i < con.Size; i++) { CvInvoke.DrawContours(outpic, con, i, new MCvScalar(0, 255, 255, 0), -1); } for (int i = 0; i < con.Size; i++) { CvInvoke.DrawContours(outpic, con, i, new MCvScalar(0, 255, 255, 0),10); } return outpic; } /// <summary> /// 叠加图像 /// </summary> /// <param name="pic1">输入Bgr图像1</param> /// <param name="pic2">输入Bgr图像2</param> /// <returns></returns> private Image<Bgr, byte> PicSubtraction(Image<Bgr, byte> pic1, Image<Bgr, byte> pic2) { Image<Bgr, byte> outpic = new Image<Bgr, byte>(pic1.Size); pic1 = ContourFilling(ToBin(picture)); pic2 = ContourFilling2(ToBin(picture)); CvInvoke.AddWeighted(pic1, 0.5, pic2, 0.5, 1, outpic); return outpic; } /// <summary> /// Point转换为PointF /// </summary> /// <param name="pt">输入Point</param> /// <returns></returns> private PointF[] PointToPointF(Point[] pt) { PointF[] aaa = new PointF[pt.Length]; int num = 0; foreach (var point in pt) { aaa[num].X = point.X; aaa[num++].Y = (int)point.Y; } return aaa; } /// <summary> /// 填充缺陷轮廓 /// </summary> /// <param name="pic">输入Bgr图像</param> /// <returns></returns> private Image<Bgr, byte> ContourFilling3(Image<Bgr, byte> pic) { Image<Bgr, byte> outpic = new Image<Bgr, byte>(pic.Size); Image<Ycc, byte> ycc = pic.Convert<Ycc, byte>(); for(int i=0;i<ycc.Height;i++) for(int j=0;j<ycc.Width;j++) { if (ycc[i, j].Cr > 35 && ycc[i, j].Cr < 148 && ycc[i, j].Cb > 48 && ycc[i, j].Cb < 141) { ycc[i, j] = new Ycc(0, 0, 0); } else ycc[i, j] = new Ycc(255, 255, 255); } Image<Gray, byte> gray = ycc.Convert<Gray, byte>(); gray = gray.ThresholdBinary(new Gray(100 ), new Gray(255)); gray = gray.Canny(100, 60); Image<Gray, byte> outcon = new Image<Gray, byte>(pic.Size); VectorOfVectorOfPoint con = new VectorOfVectorOfPoint(); CvInvoke.FindContours(gray, con, outcon, RetrType.External, ChainApproxMethod.ChainApproxNone); int n=0; for (int i = 0; i < con.Size; i++) { if (CvInvoke.ContourArea(con[i]) >0) { n++; } } textBox1.Text = "共" + n.ToString() + "个缺陷"+" "; n = 0; for (int i = 0; i <con .Size ; i++) { if (CvInvoke.ContourArea(con[i]) >0) { CvInvoke.DrawContours(outpic, con, i, new MCvScalar(0, 255, 0), 5); textBox1.Text = textBox1.Text + "第" + (++n).ToString() + "个缺陷的面积为" + CvInvoke.ContourArea(con[i]); } } CvInvoke.AddWeighted(outpic , 0.5,picture , 0.5, 0, outpic); return outpic; } } }
相关文章推荐
- 机器视觉缺陷检测-边学边做-OpenCV + Visiual Studio 2017 C++环境搭建
- OpenCV项目实战机器视觉之零件缺陷检测(1)
- 利用OpenCV的convexHull和convexityDefects做凸包(凸壳)检测及凸包(凸壳)的缺陷检测
- OpenCV凸包凸缺陷检测
- [置顶] opencv 玻璃镜面缺陷检测,缺陷信息标记及提取
- OpenCV-Python—图像梯度和Canny边缘检测
- 【OpenCV】角点检测:Harris角点及Shi-Tomasi角点检测
- OpenCV自学笔记14:Harris角点检测实例
- opencv 霍夫变换检测直线
- 学习OpenCV——肤色检测
- opencv三帧差分法运动检测
- opencv+Recorder︱OpenCV 中使用 Haar 分类器进行面部检测
- OpenCV 边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑
- opencv学习笔记(六)二值化以及边缘检测
- OpenCV笔记12:霍夫变换检测圆
- OpenCV【5】---通过反投影直方图以检测特定的图像内容
- OpenCV编程->HOG检测(2)
- OpenCV 摄像头Canny边缘检测 (python)
- 图像腐蚀,模糊,canny边缘检测,opencv中摄像头捕捉的图像
- 人脸识别系统开发(8) -- OpenCV人脸检测