轮廓查找问题小记
来源:互联网 发布:php统计总访问量代码 编辑:程序博客网 时间:2024/06/05 18:43
opencv中使用Mat进行轮廓查找的函数如下:
void findContours(InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point())
opencv文档地址
这个函数看起来挺简单的,我们输入一张图像,它就给我们返回相应的轮廓,但是一张图像经过不同处理,得到的轮廓可是会有非常大的不同的。
使用轮廓查找我遇到了如下的几个问题:
1.CV_RETR_EXTERNAL下找到的轮廓居然是整张图像边缘
此处查找轮廓的步骤为:
- 输入图像
- 将图像转为gray
- 将gray图像转为二值图像
- 将二值图像作为findContours输入
- 画出轮廓
使用的图片为一张发票图像(这张图片是从一篇新闻里边取到的,应该不涉及隐私信息吧):
二值化图像结果为:
最后画出的轮廓如下:
运行输出的轮廓数如下:
代码如下:
int main(int argc, char *argv[]) { //载入图像,并判断图像是否为空 Mat srcImage = imread("fapiao.jpg"); if (srcImage.empty()) { printf("Src Image is empty\n"); return -1; } //将图像正规化到一定大小方便查看 Size dsize = Size(800, 500); Mat resizedSrcImage = Mat(dsize,CV_32S); resize(srcImage, resizedSrcImage,dsize); //转化为灰度图像 Mat grayImage; cvtColor(resizedSrcImage, grayImage, CV_BGR2GRAY); imshow("gray", grayImage); //灰度图像二值化 Mat thresholdImage; threshold(grayImage, thresholdImage, 200, 255, THRESH_BINARY); imshow("threshold", thresholdImage); //查找轮廓 vector<vector<Point>> contours; findContours(thresholdImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); printf("contour size: %d\n", contours.size()); //画出轮廓 Mat result(resizedSrcImage.size(),CV_8U,Scalar(0)); drawContours(result,contours,-1,Scalar(255),1); imshow("contours", result); waitKey(0); return 0;}
问题分析:
是什么原因导致找到的轮廓居然是这样的呢?
难道是因为findContours的参数设置有误么?
代码中轮廓查找的方式为CV_RETR_EXTERNAL,它在opencv中的说明是只查找外轮廓,难道这就是原因么?
下面把CV_RETR_EXTERNAL修改为其它三种模式:
CV_RETR_LIST,CV_RETR_CCOMP,CV_RETR_TREE
用这三种模式都能得到如下的轮廓图:
问题似乎解决了,但是CV_RETR_EXTERNAL这种方式该如何得到轮廓呢?难道只能得到图片最外边缘这个轮廓么?那这种模式有什么用啊!
据我实验分析,opencv找轮廓是喜欢找的是图中的白色区域,所以上图中二值图像背景是白色导致把整张图片当做了一个大轮廓。
那么如何做修改呢?
二值化改成:
threshold(grayImage, thresholdImage, 200, 255, THRESH_BINARY_INV);
此时二值图变为:
得到的轮廓就变成如下结果啦:
2.输入给findContours的图片被破坏了
这是一个挺奇怪的问题
下面代码中threshold为找轮廓前的图片,threshold2为找轮廓后的图片
imshow("threshold", thresholdImage); //轮廓查找,并将小轮廓去掉 vector<vector<Point>> contours; findContours(thresholdImage, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); printf("contour size: %d\n", contours.size()); imshow("threshold2", thresholdImage);
对比好明显哦,太可怕了,这一问题完全是想不到啊,感觉是opencv的一个陷阱。
解决办法:
给findContours的图片用clone()深拷贝一份,原图像则不传入里边。
3.过滤小轮廓
下面是用CV_RETR_TREE找到的轮廓,我想把里边那些小子都给去掉,该怎么办呢?
其实就是遍历找到的轮廓,然后验证该轮廓的size是否大于阈值,如果不大于,则删掉这个轮廓。
我写了个函数如下:
/** * 功能描述: 轮廓过滤 * @param 需处理的图片inputImg、轮廓的最小阈值minThreshold * * @return 过滤后的轮廓 */ vector<std::vector<Point>> findFilteredCountour(Mat inputImg,int minThreshold){ std::vector<std::vector<Point>> contours; //如果直接把inputImg放进去会毁掉它的,好可怕!吓死了 Mat srcClone = inputImg.clone(); findContours(srcClone,contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); std::vector<std::vector<Point>>::const_iterator itc = contours.begin(); while(itc != contours.end()) { if(itc->size() < minThreshold) itc = contours.erase(itc); else ++itc; } return contours;}
处理之后轮廓如下,小轮廓被去掉,剩下的线条非常清晰:
- 轮廓查找问题小记
- 轮廓 - 查找轮廓、表示轮廓、绘制轮廓
- 轮廓 - 查找轮廓、表示轮廓、绘制轮廓
- 轮廓 - 查找轮廓、表示轮廓、绘制轮廓
- 轮廓查找
- opencv 查找轮廓 绘制轮廓
- 第八章 - 轮廓 - 查找轮廓、表示轮廓、绘制轮廓
- OpenCV查找轮廓
- OpenCV笔记: 查找轮廓
- opencv查找轮廓
- opencv 轮廓查找 findContours
- 查找轮廓总结
- OpenCV 查找图像轮廓
- Opencv轮廓查找检测
- findContours 轮廓查找
- Atitit 查找轮廓 findContours
- opencv--查找图像轮廓
- findcontours查找轮廓函数
- linux中部署SVN服务器
- push到github时,每次都要输入用户名和密码的问题
- 手机游戏资源 特效 显存分析工具
- 多线程:使用ImageView分类下载图片(模仿 SDWebImage)
- phpcms二次开发_创建功能模块
- 轮廓查找问题小记
- jQuery.form.js使用
- 算法:实现链表存储的回文字符串判断
- 美容护肤小技巧
- Java 构造器之构造器的隐式调用和显式调用
- iOS中GCD的使用小结
- DOM操作表格和样式
- 再生龙u盘制作及使用 - Linux - clonezilla
- STM32模拟IIC驱动OLED屏 原理+源码