干货 | 局部特征图像配准用于缺陷检测
出自:OpenCV学堂公众号
投稿作者:小黄弟
来自:中国电科智慧城市建模仿真与智能技术重点实验室
文字编辑:gloomyfish
特征提取
基于特征的图像配准,具有非常广泛的应用,大致流程可以如下:
经典的特征匹配算法有SIFT、SURF、ORB等,这三种方法在OpenCV里面都已实现。SURF基本就是SIFT的全面升级版,有 SURF基本就不用考虑SIFT,而ORB的强点在于计算时间,以下具体比较:
计算速度:ORB>>SURF>>SIFT(各差一个量级)
旋转鲁棒性:SURF>ORB~SIFT(~表示差不多)
模糊鲁棒性:SURF>ORB~SIFT
尺度变换鲁棒性:SURF>SIFT>ORB(ORB并不具备尺度变换性)
所以结论就是,如果对计算实时性要求非常高,可选用ORB算法,但基本要保证正对拍摄;如果对稳定性要求稍高,可以选择SURF;基本不用SIFT。
此外补充一点,自从OpenCV3.x开始,受到SIFT跟SURF专利授权的影响,OpenCV正式的发布版本中已经移除了SIFT与SURF算法。
ORB特征提取算法是基于FAST跟BRIEF算法改进的组合算法,其中FAST实现关键点/特征点的检测,在此基础上基于几何矩添加方向属性,BRIEF实现描述子生成,添加旋转不变性支持。
ORB特征匹配速度快的一个原因之一就是使用字符串向量的描述子,避免了浮点数计算。字符串描述子匹配上可以采用汉明距离或者LSH改进算法实现,相比浮点数计算L2距离进一步降低了计算量。所以在一般情况下建议使用ORB特征匹配,如果效果不好再尝试AKAZE/SURF/SIFT等其它特征匹配算法。
特征对齐/配准
两幅图像之间的基于特征匹配的透视变换矩阵求解通常被称为图像对齐或者配准。基于特征的匹配可以很好实现图像对齐或者配准,首先需要获取两张图像的特征关键点与特征描述子,然后通过暴力匹配或者FLANN匹配寻找匹配度高的相关特征点。
最后基于这些相关特征点估算它们之间的单应性矩阵,通过单应性矩阵实现透视变换,完成图像对齐与配准。OpenCV中有两个函数可以获得单映射变换矩阵,分别为:
- findHomography
- getPerspectiveTransform
两者之间的区别在于getPerspectiveTransform只会拿4个点去计算,findHomography则会拿一堆点(>=4)去计算。
应用代码演示
下面是一个简单的代码演示,基于特征对齐,实现基于分差的缺陷检测。
用基于ORB特征的匹配结果,如下图所示,可以看到有一些错误的匹配点
基于ORB特征实现图像相关特征点匹配的代码实现如下:
constint MAX_FEATURES = 5000;
constfloat GOOD_MATCH_PERCENT = 0.45f;
//im1为待配准图片
//im2为模板图片
//im1Reg为配准后的图片
//h为单应性矩阵
void alignImages(Mat&im1, Mat&im2, Mat&im1Reg, Mat&h)
{// 将图像转为灰度图Mat im1Gray, im2Gray;cvtColor(im1, im1Gray, COLOR_BGR2GRAY);cvtColor(im2, im2Gray, COLOR_BGR2GRAY);// 存储特征与特征描述子的变量std::vector<KeyPoint> keypoints1, keypoints2;Mat descriptors1, descriptors2;// 检测ORB特征计算特征描述子.Ptr<Feature2D> orb = ORB::create(MAX_FEATURES);orb->detectAndCompute(im1Gray, Mat(), keypoints1, descriptors1);clock_t start, end;start = clock();orb->detectAndCompute(im2Gray, Mat(), keypoints2, descriptors2); //77ms// 特征匹配.std::vector<DMatch> matches;Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");matcher->match(descriptors1, descriptors2, matches, Mat());// Sort matches by scorestd::sort(matches.begin(), matches.end());//基于GMS的特征匹配算法//vector<DMatch> matchesAll, matchesGMS;//BFMatcher matcher(NORM_HAMMING);//std::vector<DMatch> matches;//matcher.match(descriptors1, descriptors2, matchesAll);//cout << "matchesAll: " << matchesAll.size() << endl;//matchGMS(im1.size(), im2.size(), keypoints1, keypoints2, matchesAll, matches);//std::sort(matches.begin(), matches.end());end = clock();cout << (float)(end - start) * 1000 / CLOCKS_PER_SEC<<"ms"<< endl;// 移除不好的匹配点constint numGoodMatches = matches.size() * GOOD_MATCH_PERCENT;matches.erase(matches.begin() + numGoodMatches, matches.end());// 画匹配点Mat imMatches;drawMatches(im1, keypoints1, im2, keypoints2, matches, imMatches);imwrite("matches.jpg", imMatches);// 存储好的匹配点std::vector<Point2f> points1, points2;for (size_t i = 0; i < matches.size(); i++){points1.push_back(keypoints1[matches[i].queryIdx].pt);points2.push_back(keypoints2[matches[i].trainIdx].pt);}// 找出最优单映射变换矩阵hh= findHomography(points1, points2, RANSAC);// 利用h矩阵进行透视变换warpPerspective(im1, im1Reg, h, im2.size());
}
Grid-based Motion Statistics(GMS)通过网格划分、运动统计特性的方法可以迅速剔除错误匹配,以此来提高匹配的稳定性。ORB+GMS的匹配效果如下,可见错误的匹配点少了很多。
配准后的图如下图所示:
将配准后的图与基准模板图做差分,效果如下:
进行形态学操作:
找出缺陷,比较大的缺陷可以找出来,较小的缺陷还是不能找出来。
这部分的代码实现如下:
int main(intargc, char **argv)
{// Read reference imagestring refFilename("8.jpg");cout <<"Reading reference image : "<< refFilename << endl;Mat imReference = imread(refFilename);// Read image to be alignedstring imFilename("7.jpg");cout <<"Reading image to align : "<< imFilename << endl;Mat im = imread(imFilename);// Registered image will be resotred in imReg. // The estimated homography will be stored in h. Mat imReg, h;// Align imagescout <<"Aligning images ..."<< endl;alignImages(im, imReference, imReg, h);// Write aligned image to disk. string outFilename("aligned.jpg");cout <<"Saving aligned image : "<< outFilename << endl;imwrite(outFilename, imReg);// Print estimated homographycout <<"Estimated homography : \n"<< h << endl;Mat currentframe, previousframe;cvtColor(imReference, previousframe, COLOR_BGR2GRAY);cvtColor(imReg, currentframe, COLOR_BGR2GRAY); //转化为单通道灰度图absdiff(currentframe, previousframe, currentframe);//做差求绝对值imshow("1", currentframe);imwrite("re.jpg", currentframe);threshold(currentframe, currentframe, 120, 255.0, THRESH_BINARY);imwrite("re11.jpg", currentframe);erode(currentframe, currentframe, Mat());//腐蚀dilate(currentframe, currentframe, Mat());//膨胀dilate(currentframe, currentframe, Mat());//膨胀imshow("moving area", currentframe); //显示图像vector<vector<Point>> v;vector<Vec4i> hierarchy;Mat result;Rect rect;findContours(currentframe, v, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);for (int i = 0; i < hierarchy.size(); i++){rect = boundingRect(v.at(i));if (rect.area() > 1){rectangle(imReg, rect, Scalar(0, 0, 255), 2);}}imwrite("res1.jpg", imReg);imshow("moving area1", imReg);waitKey(0);
}
END
备注:工业视觉
工业视觉缺陷检测交流群
工业视觉、缺陷检测、工业测量、定位等技术,
若已为CV君其他账号好友请直接私信。
我爱计算机视觉
微信号:aicvml
QQ群:805388940
微博知乎:@我爱计算机视觉
投稿:amos@52cv.net
网站:www.52cv.net
在看,让更多人看到
干货 | 局部特征图像配准用于缺陷检测相关推荐
- 干货 | 基于特征的图像配准用于缺陷检测
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 特征提取 基于特征的图像配准,具有非常广泛的应用,大致流程可以如下 ...
- 滴普技术荟:某工业产品内部结构尺寸图像测量和缺陷检测分析
作者:杨超 滴普科技2048实验室AI产品部 算法工程师 需求背景 目前,某工业产品是立体实心结构,内部质量抽检依靠扫描设备,从三个面对内部进行扫描成像后人工判读,但判读自动化程度比较低,测量尺寸需要 ...
- 缺陷检测相关论文阅读总结(记录自己读过的论文主要内容/Ideas)
缺陷检测相关论文阅读总结(记录自己读过的论文主要内容) Attention!!! 点击论文题目即可访问原文or下载原文PDF文件: 每篇文章的内容包含:内容总结.文章Ideas: 更多关于缺陷检测以及 ...
- 汇总|缺陷检测数据集
点击上方"计算机视觉工坊",选择"星标" 干货第一时间送达 一.弱监督学习下的工业光学检测(DAGM 2007) 数据下载链接: https://hci.iwr ...
- 智能手机背面玻璃的缺陷检测,分割网络的应用
点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 这是一篇关于手机玻璃表面缺陷检测的文章,由浙江大学发表.主要创新点在成像系统部分,大家可以借鉴参考.而 ...
- 缺陷检测公开数据集大全
一.弱监督学习下的工业光学检测(DAGM 2007) 数据下载链接:https://hci.iwr.uni-heidelberg.de/node/3616 数据集简介: 主要针对纹理背景上的杂项缺陷. ...
- 如何解决工业缺陷检测小样本问题?
作者丨吴雨培 来源丨act 工业AI 编辑丨极市平台 当前基于有监督的缺陷检测算法,在数据量充足的场景下已经逐步成功落地,但工业场景具有一定的离散性,大部分应用场景均为小样本检测场景,小样本问题的解决 ...
- 【缺陷检测】基于形态学实现印刷电路板缺陷检测技术附matlab代码
1 简介 当今,电子工业在国家经济发展中扮演着越来越重要的角色,作为各种电子元器件的高度信息集合,印刷电路板(PCB)被广泛应用在电子工业中的各个领域.经济的不断发展促使电子技术不断地提高,轻薄.便捷 ...
- 如何解决工业缺陷检测小样本问题
吴雨培/文 阿丘(Aqrose)科技公司算法总监 在工业生产制造中,由于生产过程是一个多因素耦合的复杂过程,生产过程中的任何异常都会导致产品缺陷产生,及时识别异常产品的缺陷模式是提高生产质量和生产效率 ...
最新文章
- 注解 @Scheduled
- 后台开发经典书籍--unix环境高级编程
- 【机器学习入门笔记14:BP神经网络基础】20190218
- [工具]微软的学习平台Microsoft Learn很好用,推荐一下
- 三个剩两个,两个剩一个,最后一个都没剩下。
- 输电线路巡检机器人PPT_“高空大师”来了!架空输电线路智能巡检机器人在宁波投运...
- Image Cup,我和几位师兄一起奋战!
- 13.SpringMVC核心技术-异常处理
- Eigen官网教程(5) 规约、范数等
- 你能想到几种方式实现数组扁平化(越多越好)
- asp.net下ajax.ajaxMethod使用方法
- 《MySQL必知必会》学习笔记——第七章(数据过滤)
- pyqt 鼠标离开按钮_小米 Smart Pad 体验:表面它是个鼠标垫,其实还是个鼠标垫...
- innerHTMLinnerText区别
- js怎么获取扫码枪条码_JS 如何获取扫码枪输入数据
- 第一次服务器被黑 既惊讶 又后怕!!!
- 曼哈顿算法公式_距离计算方法总结
- 借助Docker hub自己手动制作镜像(以Nginx镜像为例)
- TTE系统容错设计(2) ——COM/MON机制
- Buffer Overflow Vulnerability Prediction from x86 executables using Static Analysis and ML
热门文章
- php 显示中文utf,php adodb 从mysql数据库中输出中文显示到utf编码网页乱码问题
- 软件工程——硬件汇编程序设计实验——顺序程序实验
- Oracle PL/SQL进阶
- php 中文截断,PHP中实现中文字串截取无乱码的解决方法
- mysql插10万条数据_如何快速安全的插入千万条数据?
- 深度学习stride_深度强化学习成名作——DQN
- java list 交集_java两个List的交集,并集
- 自然语言处理模型_ICLR 2020 「自然语言处理」【Prosus AI】金融情感分析FinBERT模型(含源码)!...
- 表格状态列_不用软件也能做好多个项目跟进管理?我用一个协同表格就搞定
- ansible免密登录和账号登录方式