此前在《【OpenCV3】图像轮廓查找与绘制——cv::findContours()与cv::drawContours()详解》一文中,详细介绍了图像轮廓的检测与绘制,但是在实际的应用中,往往需要检测目标的最大轮廓,但是OpenCV本身并没有封装这样一个函数,下面就贴上封装好的接口,供参考使用。

说明:对于最大轮廓的定义,有些以轮廓的点数最多为标准,有的以所包围的面积最大为标准,这里将两种都实现一下。

1、C接口的封装(最多点数)

CvSeq* cvFindBiggestCountour(IplImage *binaryImage)
{int polyHull0 = 1;CvPoint offset;offset.x = 0;offset.y = 0;CvMemStorage *tempStorage = cvCreateMemStorage(0);CvSeq *contour;CvSeq *c;int nContours = 0;double largest_length = 0;double len = 0;CvContourScanner scanner;CvSlice slice = CV_WHOLE_SEQ;scanner = cvStartFindContours(binaryImage, tempStorage, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, offset);while ((c = cvFindNextContour(scanner)) != 0){len = cvContourPerimeter(c);if (len > largest_length){largest_length = len;}}scanner = cvStartFindContours(binaryImage, tempStorage, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, offset);while ((c = cvFindNextContour(scanner)) != 0){len = cvContourPerimeter(c);double q = largest_length;if (len < q)cvSubstituteContour(scanner, 0);else{CvSeq *newC;if (polyHull0)newC = cvApproxPoly(c, sizeof(CvContour), tempStorage, CV_POLY_APPROX_DP, 2, 0);elsenewC = cvConvexHull2(c, tempStorage, CV_CLOCKWISE, 1);cvSubstituteContour(scanner, newC);}nContours++;}printf("End find contours!\n");contour = cvEndFindContours(&scanner);cvReleaseMemStorage(&tempStorage);cvRelease(&c);return contour;
}

2、C接口的封装(最大面积)

CvSeq* cvFindBiggestCountour(IplImage *binaryImage)
{int polyHull0 = 1;CvPoint offset;offset.x = 0;offset.y = 0;CvMemStorage *tempStorage = cvCreateMemStorage(0);CvSeq *contour;CvSeq *c;int nContours = 0;double largest_length = 0;double len = 0;CvContourScanner scanner;CvSlice slice = CV_WHOLE_SEQ;scanner = cvStartFindContours(binaryImage, tempStorage, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, offset);while ((c = cvFindNextContour(scanner)) != 0){len = cvContourArea(c, slice, 0);if (len > largest_length){largest_length = len;}}scanner = cvStartFindContours(binaryImage, tempStorage, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, offset);while ((c = cvFindNextContour(scanner)) != 0){len = cvContourArea(c, slice, 0);double q = largest_length;if (len < q)cvSubstituteContour(scanner, 0);else{CvSeq *newC;if (polyHull0)newC = cvApproxPoly(c, sizeof(CvContour), tempStorage, CV_POLY_APPROX_DP, 2, 0);elsenewC = cvConvexHull2(c, tempStorage, CV_CLOCKWISE, 1);cvSubstituteContour(scanner, newC);}nContours++;}printf("End find contours!\n");contour = cvEndFindContours(&scanner);cvReleaseMemStorage(&tempStorage);cvRelease(&c);return contour;
}

3、C++接口封装(最多点数)

std::vector<cv::Point> findBiggestContour(cv::Mat binary_image)
{std::vector<std::vector<cv::Point>> contours;int largest_area = 0;int largest_contour_index = 0;cv::findContours(binary_image, contours, cv::noArray(), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);for (int i = 0; i < contours.size(); i++)  {int a = contours[i].size();  if (a > largest_area){largest_area = a;largest_contour_index = i;               }}return contours[largest_contour_index];
}

4、C++接口封装(最大面积)

std::vector<cv::Point> findBiggestContour(cv::Mat binary_image)
{std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;int largest_area = 0;int largest_contour_index = 0;cv::findContours(binary_image, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);for (int i = 0; i < contours.size(); i++) // iterate through each contour. {double a = contourArea(contours[i], false);  //  Find the area of contourif (a > largest_area){largest_area = a;largest_contour_index = i;                //Store the index of largest contour}}return contours[largest_contour_index];
}

其中C++接口的测试代码如下

cv::Mat src = cv::imread("Hepburn.png", 1);cv::Mat result = src.clone();cv::Mat gray;cv::cvtColor(src, gray, CV_BGR2GRAY);cv::Mat binary;cv::threshold(gray, binary, 100, 255, cv::THRESH_BINARY);std::vector< std::vector< cv::Point> > contours;std::vector< cv::Point>  biggest_contour;std::vector< std::vector< cv::Point> > temp_contours;cv::findContours(binary,contours,cv::noArray(),cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE);biggest_contour = findBiggestContour(binary);temp_contours.push_back(biggest_contour);cv::drawContours(result, contours, -1, cv::Scalar(0, 255, 0));cv::drawContours(result, temp_contours, 0, cv::Scalar(0, 0, 255));cv::imshow("src", src);cv::imshow("gray", gray);cv::imshow("binary", binary);cv::imshow("result", result);cv::waitKey(0);return 0;

测试结果如下,其中红色曲线代表的是最大轮廓:

参考:https://harismoonamkunnu.blogspot.tw/2012/11/opencv-find-biggest-contour.html

【OpenCV3】图像最大轮廓检测——cvFindBiggestContour()封装相关推荐

  1. 利用OpenCV进行图像的轮廓检测

    简 介: 本文对于OpenCV中的轮廓检测算法进行了讨论,可以看到一些基于轮廓检测的应用.接着对四种不同的提取方式的结果进行了讨论.你还了解了如何将轮廓进行绘制的方法. 关键词: 轮廓检测,二值化 § ...

  2. python+OpenCV图像处理(十一)图像轮廓检测

    图像轮廓检测 (一)检测轮廓 在OpenCV-python中,使用cv2.findContours()函数来对图像进行轮廓检测. 返回三个值:image,contours,hierarchy cont ...

  3. 【OpenCV入门指南】第五篇轮廓检测 下

    上一篇<[OpenCV入门指南]第五篇轮廓检测上>介绍了cvFindContours函数和cvDrawContours函数,并作了一个简单的使用示范.本篇将展示一个实例,让大家对轮廓检测有 ...

  4. 【OpenCV入门指南】第五篇 轮廓检测 上

    <[OpenCV入门指南]第三篇Canny边缘检测>中介绍了边缘检测,本篇介绍轮廓检测,轮廓检测的原理通俗的说就是掏空内部点,比如原图中有3*3的矩形点.那么就可以将中间的那一点去掉. 在 ...

  5. 轮廓检测和边缘检测区别

    边缘检测 主要是通过一些手段检测数字图像中明暗变化剧烈(即梯度变化比较大)像素点,偏向于图像中像素点的变化.如canny边缘检测,结果通常保存在和源图片一样尺寸和类型的边缘图中. 轮廓检测 指检测图像 ...

  6. OCR文本扫描 轮廓检测 透视变换

    OCR文本扫描项目实战(图像预处理,调用pytesseract.image_to_string()完成文本识别) 本项目和源代码来自唐宇迪opencv项目实战 本文是一篇OCR文本扫描项目实战的学习笔 ...

  7. java opencv3轮廓_Java+opencv3.2.0实现轮廓检测

    Java+opencv3.2.0实现轮廓检测 发布时间:2020-08-28 13:27:52 来源:脚本之家 阅读:96 作者:帅气的猫爪 轮廓是由一系列的点组成的集合,表现在图像中就是一条曲线. ...

  8. Python-OpenCV 处理图像(五):图像中边界和轮廓检测

    关于边缘检测的基础来自于一个事实,即在边缘部分,像素值出现"跳跃"或者较大的变化.如果在此边缘部分求取一阶导数,就会看到极值的出现. 而在一阶导数为极值的地方,二阶导数为0,基于这 ...

  9. Python-OpenCV 处理图像(四)(五):图像直方图和反向投影 图像中边界和轮廓检测

    当我们想比较两张图片相似度的时候,可以使用这一节提到的技术 直方图对比 反向投影 关于这两种技术的原理可以参考我上面贴的链接,下面是示例的代码: 0x01. 绘制直方图 import cv2.cv a ...

最新文章

  1. Linux 终端訪问 FTP 及 上传下载 文件
  2. Larbin使用方法2
  3. 新一代开源Android渠道包生成工具Walle
  4. 网易云信集成视频教程(六):如何快速实现iOS下IM自定义消息收发?
  5. JavaScript与 HTML表单的交互过程,想要学习动态网页但是无从下手的新手看看。...
  6. HDFC的完整形式是什么?
  7. 一步步编写操作系统 27 处理器微架构之流水线简介
  8. 苹果全新指纹识别专利过审 Touch ID或将重回iPhone
  9. 【kafka】如何修改分区的指定副本为Leader|设计方案
  10. 10. 在constructors内阻止资源泄露
  11. Darklabel多目标跟踪标注工具
  12. 百度网盘免费jdk1.8中文chm下载(不要积分点个赞就好)
  13. 使用win7 快捷键
  14. 密码学基础(数学理论)
  15. 若已知1800年1月1日为星期3,则对于一个给定的年份和月份,输出这个月的最后一天是星期几。
  16. 女性睾酮水平高(High Testosterone Levels in Women)
  17. 万字长文告诉你喜茶为什么能成功
  18. **caffe_vcpkg+vs2017+win7安装整理**
  19. 三星80亿美元收购Harmon真正意图是它?
  20. linux目录下多个文件行数比对函数 关键字遍历文件 linux命令写入C函数

热门文章

  1. blp模型 上读下写_Java高并发编程(三):Java内存模型
  2. java WebMvcConfig 全局设置时间服务器时区
  3. python 拆分excel openpyxl_openpyxl(python操作Excel)
  4. angular五大服务顺序_建议收藏 | 一篇文章告诉你工种的进场顺序
  5. vue中组件在不同页面中渲染出错
  6. vue单向数据流与双向绑定两者区别
  7. c语言数码管编写程序,跪求单片机0~99数码管显示用C语言编写的程序
  8. 界面上下固定_基于ANSYS的胶粘结构界面开裂有限元计算
  9. 学习鸟哥的Linux私房菜笔记(1)——Linux系统入门
  10. Visual Studio Debug 教程 之 入门