0
点赞
收藏
分享

微信扫一扫

OpenCV + CPP 系列(廿六)轮廓 (contour) 与 凸包 (convex Hull)


文章目录

  • ​​一、轮廓(find contour)​​
  • ​​findContours发现轮廓​​
  • ​​drawContours绘制轮廓​​
  • ​​二、凸包(Convex Hull)​​
  • ​​函数 convexHull​​

一、轮廓(find contour)

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法。
所以边缘提取的阈值选定会影响最终轮廓发现结果

findContours发现轮廓

在二值图像上发现轮廓使用


InputOutputArray binImg,     输入图像,非0的像素被看成1,0的像素值保持不变,8-bit

OutputArrayOfArrays contours,  全部发现的轮廓对象


OutputArray, hierachy      图该的拓扑结构

​std::vector<cv::Vec4i>​​,可选,该轮廓发现算法正是基于图像拓扑结构实现。它的元素与轮廓的数量一样多。对于每个第 i 个轮廓轮廓[i],元素hierarchy[i][0]、hierarchy[i][1]


int mode,            轮廓返回的模式


int method,            发现方法


Point offset=Point()       轮廓像素的位移,默认(0, 0)没有位移


)


drawContours绘制轮廓

在二值图像上发现轮廓cv::findContours之后对发现的轮廓数据进行绘制显示


InputOutputArray binImg,      输出图像


OutputArrayOfArrays

contours,    全部发现的轮廓对象


Int contourIdx            轮廓索引号


const Scalar & color,        绘制颜色


int thickness,/           绘制线宽


int lineType ,             线的类型LINE_8


InputArray hierarchy,        拓扑结构图


int maxlevel,           最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓


Point offset=Point()        轮廓位移,可选


头文件 quick_opencv.h:声明类与公共函数

#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;

class QuickDemo {
public:
...
void contours_Demo(Mat& image1);
void convexhull_Demo(Mat& image1);
};

主函数调用该类的公共成员函数

#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;


int main(int argc, char** argv) {
Mat src1 = imread("D:\\Desktop\\ttt.png");
if (src1.empty()) {
printf("Could not load images1...\n");
return -1;
}
imshow("input1", src1);

QuickDemo qk;
qk.contours_Demo(src1);
qk.convexhull_Demo(src1);

waitKey(0);
destroyAllWindows();
return 0;
}

源文件 quick_demo.cpp:实现类与公共函数

#include <quick_opencv.h>

using namespace cv;
using namespace std;


void QuickDemo::contours_Demo(Mat& image) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
int threshold_val = 100;
Mat gray_img, edges_img;
cvtColor(image, gray_img, COLOR_BGR2GRAY);


Canny(gray_img, edges_img, threshold_val, threshold_val * 2, 3, false);
if (edges_img.empty()) {return;}

findContours(edges_img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
if (contours.size() == 0) {return;}

Mat drawImg = Mat::zeros(edges_img.size(), CV_8UC3);
RNG rng(1234);

for (int i = 0; i < contours.size(); i++) {
Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawImg, contours, i, color, 2, 8, hierarchy, 0, Point(0, 0));
}
imshow("gray_img", gray_img);
imshow("edges_img", edges_img);
imshow("drawImg", drawImg);
}

OpenCV + CPP 系列(廿六)轮廓 (contour) 与 凸包 (convex Hull)_边缘提取

二、凸包(Convex Hull)

什么是凸包(Convex Hull),在一个多变形边缘或者内部任意两个点的连线都包含在多边形边界或者内部。即:包含点集合S中所有点的最小凸多边形称为凸包

OpenCV + CPP 系列(廿六)轮廓 (contour) 与 凸包 (convex Hull)_边缘提取_02


检测算法 - Graham扫描法

  1. 首先选择Y方向最低的点作为起始点p0
  2. 从p0开始极坐标扫描,依次添加(排序顺序是根据极坐标的角度大小,逆时针方向)
  3. 对每个点pi来说,如果添加pi点到凸包中导致一个左转向(逆时针方法)则添加该点到凸包, 反之如果导致一个右转向(顺时针方向)删除该点从凸包中
  4. OpenCV + CPP 系列(廿六)轮廓 (contour) 与 凸包 (convex Hull)_scala_04

函数 convexHull

InputArray points,     // 输入候选点,来自findContours


OutputArray hull,    // 凸包

bool clockwise,     // default true, 顺时针方向

bool returnPoints    // true 表示返回点个数,如果第二个参数是 vector则自动忽略


演示示例:

流程:

  1. 转成灰度图
  2. 模糊降噪
  3. 边缘轮廓检测
  4. 查找轮廓
  5. 生成凸包

void QuickDemo::convexhull_Demo(Mat& image) {
Mat gray_img, edges_img;
cvtColor(image, gray_img, COLOR_BGR2GRAY);
blur(gray_img, gray_img, Size(3, 3));
Canny(gray_img, edges_img, 100, 100 * 2);


vector<vector<Point>> contours;
findContours(edges_img, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);
if (contours.size() == 0) { return; }

vector<vector<Point>> hulls(contours.size());
for (size_t i = 0; i < contours.size(); i++) {
convexHull(contours[i], hulls[i]);
}

RNG rng(1234);
Mat dst = Mat::zeros(image.size(), CV_8UC3);
for (size_t k = 0; k < contours.size(); k++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, contours, (int)k, color, 2, 8);
drawContours(dst, hulls, (int)k, color, 2, 8);
}
imshow("edges_img", edges_img);
imshow("dst", dst);
}

OpenCV + CPP 系列(廿六)轮廓 (contour) 与 凸包 (convex Hull)_边缘提取_05


举报

相关推荐

0 条评论