基于OpenCV的PCB缺损判断研究
来源:互联网 发布:视频讲课软件 编辑:程序博客网 时间:2024/06/10 19:59
本人模式识别小硕一枚,目前帝都某校研一在读。寒假自己用opencv做了一个对PCB板的好坏的检测,拿出来和大家一起学习讨论,这篇博文也是我在CSDN上发表的第一篇文章,欢迎各路大神指导。
基本思想是通过定焦的工业摄像头,对放置于卡槽中的PCB进行拍摄并取ROI,与标准的PCB图片进行模板匹配,两者二值化后相减并中值滤波,在缺损处用红色矩形标出,最后只命名输出缺损PCB图片。
为了给大家更好的演示,我将程序改为直接读取图片。
程序如下:
(可能有些杂乱,本人水平还需提高)
/********************************************************************************/ /* * Copyright(c)2016 * ALL rights reserved. * * file name: Lab_Identification_Program.cpp * file description: * * Abstract: * current version:2.0 * author: L T * date: 2016.2.3 * * replacement version: * original author: * date: *//********************************************************************************/#include<opencv2/opencv.hpp>#include<iostream>using namespace cv;//------------------------------------------------------// 全局变量//------------------------------------------------------Mat frame, grayimage, StandardPhoto, WaitJudgePhoto, g_resultImage, srcImage;Mat img,dst,edge,out,mask,out1,out2,out3,out4;Mat img_result,img_result1,img_result2,Wback,WbackClone,WbackClone1;int ConditionJudgment;int g_nMatchMethod = 5;#define pic01 "AFTER2.jpg" //需要比对的图#define pic02 "PRO5.jpg"#define WINDOW_NAME1 "【原始图片】" //为窗口标题定义的宏 #define WINDOW_NAME2 "【匹配窗口】" //------------------------------------------------------// 二值化(需先灰度化)//------------------------------------------------------void Binarization(){ threshold(grayimage, out, 90, 255, 0);//THRESH_BINARY = 0 threshold(StandardPhoto, out1, 90, 255, 0);//将标准图二值化 threshold(WaitJudgePhoto, out2, 90, 255, 0);}//------------------------------------------------------// 读入图片//------------------------------------------------------void ReadPic(){ StandardPhoto = imread( pic02, 0 );//完美标准图 (灰度图) WaitJudgePhoto = imread( pic01, 0 );//读入“待判断”图片 (灰度图) out3 = imread( pic01, 1 );//再读入一张无修改图 mask = imread( pic01, 0 );//mask图必须读灰度图 Wback = imread("WhiteBack02.jpg",1);//同分辨率白底板 WbackClone = Wback.clone(); WbackClone1 = Wback.clone();}//------------------------------------------------------// 模板匹配//------------------------------------------------------void TempMatch(){ out1.copyTo( srcImage ); int resultImage_cols = out1.cols - out2.cols + 1; int resultImage_rows = out1.rows - out2.rows + 1; g_resultImage.create( resultImage_cols, resultImage_rows, CV_32FC1 ); matchTemplate( out1, out2, g_resultImage, g_nMatchMethod ); normalize( g_resultImage, g_resultImage, 0, 1, NORM_MINMAX, -1, Mat() ); double minValue; double maxValue; Point minLocation; Point maxLocation; Point matchLocation; minMaxLoc( g_resultImage, &minValue, &maxValue, &minLocation, &maxLocation, Mat() ); if( g_nMatchMethod == CV_TM_SQDIFF || g_nMatchMethod == CV_TM_SQDIFF_NORMED ) { matchLocation = minLocation; } else { matchLocation = maxLocation; } rectangle( out1, matchLocation, Point( matchLocation.x + out2.cols , matchLocation.y + out2.rows ), Scalar(0,0,255), 2, 8, 0 ); rectangle( g_resultImage, matchLocation, Point( matchLocation.x + out2.cols , matchLocation.y + out2.rows ), Scalar(0,0,255), 2, 8, 0 ); Mat imageROI = out1(Rect(matchLocation.x,matchLocation.y,out2.cols,out2.rows)); out2.copyTo(imageROI,mask); Mat imageROI1 = WbackClone(Rect(matchLocation.x,matchLocation.y,out3.cols,out3.rows)); out3.copyTo(imageROI1,mask); cvtColor(WbackClone,out4,CV_BGR2GRAY);//灰度化 threshold(out4, WbackClone, 90, 255, 0);//二值化 Mat img2 = imread(pic01); Mat imageROI2 = WbackClone1(Rect(matchLocation.x,matchLocation.y,out3.cols,out3.rows)); out3.copyTo(imageROI2,mask); imshow("【彩色ROI位置待判断图】",WbackClone1);}//------------------------------------------------------// 缺损判断//------------------------------------------------------void DefectJudgment(){ int rowNumber = img_result.rows;//行数 int colcolNumber = img_result.cols;//列数 int colNumber = img_result.cols*img_result.channels(); //列数 x 通道数=每一行元素的个数 ConditionJudgment=1; for(int i = 0; i < rowNumber && ConditionJudgment; i++) //行循环 { uchar* data = img_result.ptr<uchar>(i); //获取第i行的首地址 for(int j = 0;j < colNumber;j++) //列循环 { // ---------【开始处理每个像素】------------- //data[j] = data[j]/div*div + div/2; if(data[j]==255)//如果白色 { //imshow("【效果图】Canny边缘检测", grayImage); imwrite("有问题的PCB.jpg",WbackClone1); ConditionJudgment=0; break; } // ----------【处理结束】--------------------- } //行处理结束 } }//------------------------------------------------------// 主程序//------------------------------------------------------int main(){ //CallCamera();//调用摄像头 namedWindow("【滤波前二值化效果】", 2); namedWindow("【滤波后缺损二值化显示】", 2); namedWindow("【对拍摄图缺损位置进行标注】", 2); namedWindow("【彩色ROI位置待判断图】", 2); ReadPic();//读入图片 Binarization();//二值化 TempMatch();//模板匹配 subtract(srcImage,WbackClone,img_result1);//相减 subtract(WbackClone,srcImage,img_result2); medianBlur(img_result1,img_result,3);//小噪点使用中值滤波 或 erode + dilate方案 3 medianBlur(img_result2,img_result2,3); //GaussianBlur(img_result1,img_result,Size(3,3),0,0);//高斯滤波 //adaptiveThreshold(img, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY,3,5); add(img_result,img_result2,img_result);//两幅互减图叠加 Mat ele = getStructuringElement(MORPH_RECT, Size(5,5)); dilate(img_result,img_result,ele); Mat threshold_output; vector<vector<Point>> contours; vector<Vec4i> hierarchy; threshold( img_result, threshold_output, 50, 255, THRESH_BINARY );//二值化 findContours( threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); vector<vector<Point> > contours_poly( contours.size() ); vector<Rect> boundRect( contours.size() ); for( unsigned int i = 0; i < contours.size(); i++ ) { approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true ); boundRect[i] = boundingRect( Mat(contours_poly[i]) ); //minEnclosingCircle( contours_poly[i], center[i], radius[i] ); } for( int unsigned i = 0; i<contours.size( ); i++ ) { Scalar color = Scalar( 0, 0, 255 ); //rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );//效果图上绘制矩形 rectangle( WbackClone1, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );//原图上绘制矩形 } DefectJudgment();//缺损判断 imshow( "【滤波前二值化效果】", img_result1 ); imshow( "【滤波后缺损二值化显示】", img_result ); imshow( "【对拍摄图缺损位置进行标注】", WbackClone1 ); waitKey(0);}
效果如下图所示:
【完好无损的PCB】
【有缺损的PCB】(焊盘缺失或缺损)
【处理后未滤波的图片】
【滤波后图像】
【缺损判断标记】(图上红色矩形框)
程序中Wback是读入的一张纯白色底板图片,这个底板分辨率和标准模板图片一致,为了在模板匹配后相减时防止检测图片因拍摄或放PCB板入卡槽时,位置的改变而处理的。
还有太多的东西需要学习,欢迎大神前辈们指教。
0 0
- 基于OpenCV的PCB缺损判断研究
- standby缺损归档的处理
- 基于Opencv的车辆识别系统研究
- CamShift算法研究(基于opencv)
- CamShift算法研究(基于opencv)
- 基于感光干膜的PCB制作
- 基于FPGA的高速PCB板设计
- 【MFC基础入门】基于Adaboost算法的车牌检测在OpenCV上的研究与实现
- 基于Adaboost算法的车牌检测在OpenCV上的研究与实现
- 基于Adaboost算法的车牌检测在OpenCV上的研究与实现
- 混合信号PCB设计中单点接地技术的研究
- 基于opencv的CLAHE
- 基于Altium Designer的4层PCB板的绘制
- 基于Altium Designer的4层PCB板的绘制
- 基于Altium Designer的4层PCB板的绘制
- 基于XMPP的IM研究
- 基于信号完整性分析的高速PCB设计
- 基于WG2005的PCB设计-DxDesigner使用指南(一)
- Android版本支付宝集成获取私钥与公钥
- 数据降维 实例
- Android自定义内容提供者使用
- Android查看wakelock
- 【OpenGL】详解第一个OpenGL程序
- 基于OpenCV的PCB缺损判断研究
- 内存溢出和内存泄露
- GPRS-SIM900模块应用程序——接电话
- git tag 在原有版本上重建同一版本
- iOS NSFileManager(文件操作)
- Android动态加载进阶 代理Activity模式
- IOS 图片上传处理 图片压缩 图片处理
- 整理github上的一些好的项目(C\C++\Java\PHP\Android\Linux\JS\CSS\iOS)
- nyoj-692-Chinese checkers【思维题】【好题】