OpenCV学习之旅6——图像轮廓与图像分割修复(1)

1. 查找并绘制轮廓

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;

//-----------------------------------【宏定义部分】-------------------------------------------- 
//      描述:定义一些辅助宏 
//------------------------------------------------------------------------------------------------ 
#define WINDOW_NAME1 "【原始图窗口】"          //为窗口标题定义的宏 
#define WINDOW_NAME2 "【轮廓图】"                    //为窗口标题定义的宏 

//----------------------------------【全局变量声明部分】--------------------------------------
//      描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage; 
Mat g_grayImage;
int g_nThresh = 80;
int g_nThresh_max = 255;
RNG g_rng(12345);
Mat g_cannyMat_output;
vector<vector<Point>> g_vContours;
vector<Vec4i> g_vHierarchy;

//vector<vector<Point>> g_vContours 被定义成二维浮点型向量,这里面将来会存储找到的边界的(x,y)坐标。
//vector<Vec4i> g_vHierarchy 是定义的层级。这个在找边界findcontours的时候会自动生成,这里只是给它开辟一个空间。
//将来findContours( src, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );
//就能算出边界的坐标,存在g_vContours里面。

//-----------------------------------【全局函数声明部分】--------------------------------------
//      描述:全局函数的声明
//-----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void* );

//-----------------------------------【main( )函数】--------------------------------------------
//      描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
    //【0】改变console字体颜色
    system("color 1F"); 

    // 加载源图像
    g_srcImage = imread( "4.jpg" );

    if(!g_srcImage.data ) 
    { 
        printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); 
        return false; 
    } 

    // 转成灰度并模糊化降噪
    cvtColor( g_srcImage, g_grayImage, CV_BGR2GRAY );
    blur( g_grayImage, g_grayImage, Size(3,3) );

    // 创建窗口
    namedWindow( WINDOW_NAME1, CV_WINDOW_AUTOSIZE );
    imshow( WINDOW_NAME1, g_srcImage );

    //创建滚动条并初始化
    createTrackbar( "canny阈值", WINDOW_NAME1, &g_nThresh, g_nThresh_max, on_ThreshChange );
    on_ThreshChange( 0, 0 );

    waitKey();
    return(0);
}

//-----------------------------------【on_ThreshChange( )函数】------------------------------  
//      描述:回调函数
//----------------------------------------------------------------------------------------------  
void on_ThreshChange(int, void* )
{

    // 用Canny算子检测边缘
    Canny( g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh*2 );

    // 寻找轮廓
    findContours( g_cannyMat_output, g_vContours, g_vHierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    // 绘出轮廓
    Mat drawing = Mat::zeros( g_cannyMat_output.size(), CV_8UC3 );
    for( int i = 0; i< g_vContours.size(); i++ )
    {
        Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );//任意值
        drawContours( drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point() );
    }

    // 显示效果图
    imshow( WINDOW_NAME2, drawing );
}

1.1 findContours()函数

void findContours( InputOutputArray image, OutputArrayOfArrays contours,OutputArray hierarchy, int mode,int method, Point offset=Point());

第一个参数:八位单通道二值图;
第四个参数:轮廓检索模式,一共有四种模式;
第五个参数:轮廓近似方法,有三种近似方法;
第六个参数:轮廓点偏移量,默认Point(),即不偏移。

1.2 drawCoutours()函数

void drawContours( InputOutputArray image, InputArrayOfArrays contours,int contourIdx, const Scalar& color,int thickness=1, int lineType=8,InputArray hierarchy=noArray(),int maxLevel=INT_MAX, Point offset=Point() );

第三个参数:轮廓绘制的指示变量。

2. 寻找物体凸包

凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集里的所有点。理解物体轮廓一种比较有用的方法就是计算出这一物体的凸包,计算其凸缺陷。

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;

//-----------------------------------【宏定义部分】-------------------------------------------- 
//  描述:定义一些辅助宏 
//------------------------------------------------------------------------------------------------ 
#define WINDOW_NAME1 "【原始图窗口】"                  //为窗口标题定义的宏 
#define WINDOW_NAME2 "【效果图窗口】"                  //为窗口标题定义的宏 

//-----------------------------------【全局变量声明部分】--------------------------------------
//  描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage; 
Mat g_grayImage;
int g_nThresh = 50;
int g_maxThresh = 255;
RNG g_rng(12345);
Mat srcImage_copy = g_srcImage.clone();
Mat g_thresholdImage_output;
vector<vector<Point> > g_vContours;
vector<Vec4i> g_vHierarchy;

//-----------------------------------【全局函数声明部分】--------------------------------------
//   描述:全局函数的声明
//-----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void* );

//-----------------------------------【main( )函数】------------------------------------------
//   描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(  )
{
    system("color 3F");

    // 加载源图像
    g_srcImage = imread( "1.jpg", 1 );

    // 将原图转换成灰度图并进行模糊降噪
    cvtColor( g_srcImage, g_grayImage, CV_BGR2GRAY );
    blur( g_grayImage, g_grayImage, Size(3,3) );

    // 创建原图窗口并显示
    namedWindow( WINDOW_NAME1, CV_WINDOW_AUTOSIZE );
    imshow( WINDOW_NAME1, g_srcImage );

    //创建滚动条
    createTrackbar( " 阈值:", WINDOW_NAME1, &g_nThresh, g_maxThresh, on_ThreshChange );
    on_ThreshChange( 0, 0 );//调用一次进行初始化

    waitKey(0);
    return(0);
}

//-----------------------------------【thresh_callback( )函数】----------------------------------  
//      描述:回调函数
//----------------------------------------------------------------------------------------------  
void on_ThreshChange(int, void* )
{
    // 对图像进行二值化,控制阈值
    threshold( g_grayImage, g_thresholdImage_output, g_nThresh, 255, THRESH_BINARY );

    // 寻找轮廓
    findContours( g_thresholdImage_output, g_vContours, g_vHierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    // 遍历每个轮廓,寻找其凸包
    vector<vector<Point> >hull( g_vContours.size() );
    for( unsigned int i = 0; i < g_vContours.size(); i++ )
    {  
        convexHull( Mat(g_vContours[i]), hull[i], false );
    }

    // 绘出轮廓及其凸包
    Mat drawing = Mat::zeros( g_thresholdImage_output.size(), CV_8UC3 );
    for(unsigned  int i = 0; i< g_vContours.size(); i++ )
    {
        Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );
        drawContours( drawing, g_vContours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
        drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
    }

    // 显示效果图
    imshow( WINDOW_NAME2, drawing );
}

2.1 convexHull()函数

void convexHull( InputArray points, OutputArray hull,bool clockwise=false, bool returnPoints=true );

第一个参数:InputArray 类型的points,即二维点集,可以是Mat类或std::vector;
第三个参数:操作方向标识符;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值