opencv之7.5提取联通区域的轮廓

提取白色区域的轮廓

void findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              int mode, int method, Point offset = Point());
第一个参数:image但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像,提取白色的轮廓;
第二个参数:contours,定义为“vector<vector> contours”,是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。有多少轮廓,向量contours就有多少元素。
        contours.size()给出了轮廓的数量
第三个参数:hierarchy,定义为“vector<Vec4i> hierarchy”,先来看一下Vec4i的定义:
           typedef    Vec<int, 4>   Vec4i;                                                                                                                                       
           Vec4i是Vec<int,4>的别名,定义了一个“向量内每一个元素包含了4int型变量”的向量。 所以从定义上看,hierarchy也是一个向量,向量内每个元素保存了一个包含4int整型的数组。 向量hiararchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。 hierarchy向量内每一个元素的4int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第 i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为默认值-1
第四个参数:int型的mode,定义轮廓的检索模式:
        取值一:CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
        取值二:CV_RETR_LIST   检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到
        取值三:CV_RETR_CCOMP  检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层
        取值四:CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。

第五个参数:int型的method,定义轮廓的近似方法:
        取值一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内         
        取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
第六个参数:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!
画出轮廓:
    
    

drawContours( InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color,
int thickness = 1, int lineType = LINE_8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX, Point offset = Point() );
第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓
代码:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
int main()
{
    cv::Mat image = cv::imread("D:/animal.jpg", 0);
    cv::Mat binary;
    cv::threshold(image, binary, 120, 255, cv::THRESH_BINARY_INV);
    cv::namedWindow("binary");
    cv::imshow("binary", binary);
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
    cv::Mat result(image.size(), CV_8U, cv::Scalar(255));
    cv::drawContours(result, contours, -1, cv::Scalar(0), 2);
    cv::namedWindow("contours");
    cv::imshow("contours", result);
    cv::waitKey(0);
    return 0;
}
    
    

提取联通的原理:系统地扫描图像直到遇到联通区域的第一个点,以它为起始点,跟踪它的轮廓,标记边界上的像素点。当轮廓闭合时,扫描回到上一个位置,直到发现新的成分。同时也可以使用周长极大值和极小值来筛选联通区域。
代码:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

int main()
{
    cv::Mat image = cv::imread("D:/animal.jpg", 0);
    cv::Mat binary;
    cv::threshold(image, binary, 120, 255, cv::THRESH_BINARY_INV);
    cv::namedWindow("binary");
    cv::imshow("binary", binary);
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
    cv::Mat result(image.size(), CV_8U, cv::Scalar(255));
    cv::drawContours(result, contours, -1, cv::Scalar(0), 2);
    cv::namedWindow("contours");
    cv::imshow("contours", result);
    std::vector<std::vector<cv::Point>>::iterator it = contours.begin();
    while (it != contours.end())
    {
        if (it->size() < 200)
        {
            it = contours.erase(it);
        }
        else
        {
            ++it;
        }
    }
    cv::Mat result1(image.size(), CV_8U, cv::Scalar(255));
    cv::drawContours(result1, contours, -1, cv::Scalar(0), 2);
    cv::namedWindow("contours1");
    cv::imshow("contours1", result1);
    cv::waitKey(0);
    return 0;
}
    
    

提取白色区域的轮廓

void findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              int mode, int method, Point offset = Point());
第一个参数:image但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像,提取白色的轮廓;
第二个参数:contours,定义为“vector<vector> contours”,是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。有多少轮廓,向量contours就有多少元素。
        contours.size()给出了轮廓的数量
第三个参数:hierarchy,定义为“vector<Vec4i> hierarchy”,先来看一下Vec4i的定义:
           typedef    Vec<int, 4>   Vec4i;                                                                                                                                       
           Vec4i是Vec<int,4>的别名,定义了一个“向量内每一个元素包含了4int型变量”的向量。 所以从定义上看,hierarchy也是一个向量,向量内每个元素保存了一个包含4int整型的数组。 向量hiararchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。 hierarchy向量内每一个元素的4int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第 i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为默认值-1
第四个参数:int型的mode,定义轮廓的检索模式:
        取值一:CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
        取值二:CV_RETR_LIST   检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到
        取值三:CV_RETR_CCOMP  检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层
        取值四:CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。

第五个参数:int型的method,定义轮廓的近似方法:
        取值一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内         
        取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
第六个参数:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!
画出轮廓:
  
  

drawContours( InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color,
int thickness = 1, int lineType = LINE_8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX, Point offset = Point() );
第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓
代码:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
int main()
{
    cv::Mat image = cv::imread("D:/animal.jpg", 0);
    cv::Mat binary;
    cv::threshold(image, binary, 120, 255, cv::THRESH_BINARY_INV);
    cv::namedWindow("binary");
    cv::imshow("binary", binary);
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
    cv::Mat result(image.size(), CV_8U, cv::Scalar(255));
    cv::drawContours(result, contours, -1, cv::Scalar(0), 2);
    cv::namedWindow("contours");
    cv::imshow("contours", result);
    cv::waitKey(0);
    return 0;
}
  
  

提取联通的原理:系统地扫描图像直到遇到联通区域的第一个点,以它为起始点,跟踪它的轮廓,标记边界上的像素点。当轮廓闭合时,扫描回到上一个位置,直到发现新的成分。同时也可以使用周长极大值和极小值来筛选联通区域。
代码:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

int main()
{
    cv::Mat image = cv::imread("D:/animal.jpg", 0);
    cv::Mat binary;
    cv::threshold(image, binary, 120, 255, cv::THRESH_BINARY_INV);
    cv::namedWindow("binary");
    cv::imshow("binary", binary);
    std::vector<std::vector<cv::Point>> contours;
    cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
    cv::Mat result(image.size(), CV_8U, cv::Scalar(255));
    cv::drawContours(result, contours, -1, cv::Scalar(0), 2);
    cv::namedWindow("contours");
    cv::imshow("contours", result);
    std::vector<std::vector<cv::Point>>::iterator it = contours.begin();
    while (it != contours.end())
    {
        if (it->size() < 200)
        {
            it = contours.erase(it);
        }
        else
        {
            ++it;
        }
    }
    cv::Mat result1(image.size(), CV_8U, cv::Scalar(255));
    cv::drawContours(result1, contours, -1, cv::Scalar(0), 2);
    cv::namedWindow("contours1");
    cv::imshow("contours1", result1);
    cv::waitKey(0);
    return 0;
}
  
  

猜你喜欢

转载自blog.csdn.net/a839766550/article/details/78324491