当前位置: 首页 > news >正文

11---OpenCV:图像进阶操作之①轮廓②凸包操作

一、图像轮廓操作

图像轮廓

图像轮廓是一系列相连的点组成的曲线,代表了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全部连续。一般地,获取图像轮廓要经过下面几个步骤

  • 读取图片

  • 灰度处理-->imread("testMin.jpg", IMREAD_GRAYSCALE)

  • 二值化处理,查找轮廓

    • 二值化---> threshold(result["Gray"], result["Binary"], 125, 255, THRESH_BINARY);

  • 显示轮廓边缘

查找轮廓

void findContours( InputArray image, OutputArrayOfArrays contours,int mode, int method, Point offset = Point());
/*******************************************************************
*           image:          单通道灰度图              
*           contours:       检测到的轮廓,存储的是点坐标  
*           mode:           轮廓检索模式
*           method:         轮廓逼近方法
*           offset:         按照偏移量移动所有的轮廓 一般不使用
*********************************************************************/
void findContours( InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode,int method, Point offset = Point());
/*******************************************************************
*           image:          输入单通道灰度图                
*           contours:       检测到的轮廓,存储的是点坐标  
*           hierarchy:      轮廓的拓扑信息
*               contours[i]包含4个hierarchy[i]元素,
*                           hierarchy[i][0]:后一个轮廓
*                           hierarchy[i][1]:前一个轮廓
*                           hierarchy[i][2]:父轮廓
*                           hierarchy[i][3]:内嵌轮廓                                        
*           mode:           轮廓检索模式
*           method:         轮廓逼近方法
*           offset:         按照偏移量移动所有的轮廓 一般不使用
*********************************************************************/

//mode取值:
enum RetrievalModes {
    RETR_EXTERNAL  = 0,//只检索最外面的轮廓
    RETR_LIST      = 1,//检索所有轮廓,并保存到一条链表中
    RETR_CCOMP     = 2,//检索所有轮廓,组织为顶层(外部边界)和次层(内部边界)
    RETR_TREE      = 3,//检索所有的轮廓,并重构嵌套轮廓的整个层次
    RETR_FLOODFILL = 4 //支持CV_32SC1图像,不等于仅支持CV_8UC1图像
};
//method取值:
enum ContourApproximationModes {
    CHAIN_APPROX_NONE      = 1, //保存所有轮廓点
    CHAIN_APPROX_SIMPLE    = 2, //压缩水垂直对角线,只保留线的两端点
    CHAIN_APPROX_TC89_L1   = 3, //使用teh-Chinl chain 近似算法
    CHAIN_APPROX_TC89_KCOS = 4  //使用teh-Chinl chain 近似算法
};

绘制轮廓

void 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());
/*******************************************************************
*           image:                  输出单通道灰度图    
*           contours:               所有的输入轮廓
*           contourIdx:             指定轮廓列表的索引 ID(将被绘制)
*                                       若为负数,则所有的轮廓将会被绘制
*           color:                  绘制轮廓的颜色
*           thickness:              绘制轮廓线条的宽度
*           lineType:               线条的类型,8连通型或4连通型
*           hierarchy:              层次结构信息
*           maxLevel:               绘制轮廓的最高级别
*                                        0:绘制指定轮廓
*                                        1:绘制该轮廓和所有嵌套轮廓
*                                        2:绘制该轮廓、嵌套轮廓子轮廓等
*           offset:                 按照偏移量移动所有的轮廓
*********************************************************************/

综合代码

#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
class OutLine 
{
public:
    OutLine() :img(imread("testMin.jpg", IMREAD_GRAYSCALE)) 
    {
        result["Gray"] = img;
    }
    void Show() 
    {
        for (auto& v : result) 
        {
            imshow(v.first, v.second);
        }
        waitKey(0);
    }
​
    //查找轮廓
    void FindOutLine() 
    {
        threshold(result["Gray"], result["Binary"], 125, 255, THRESH_BINARY);
        findContours(result["Binary"], contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
    }
    //着色
    void DrawOutLine() 
    {
        result["OutLine"] = Mat::zeros(result["Binary"].size(), CV_8UC3);
        for (int i = 0; i < contours.size(); i++) 
        {
            Scalar color = Scalar(0, 255, 0);
            //drawContours(result["OutLine"], contours, i, color, 1, 8, hierarchy);
            drawContours(result["OutLine"], contours, i, color);
        }
    }
private:
    Mat img;
    map<string, Mat> result;
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
};
​
int main() 
{
    OutLine* p = new OutLine;
    p->FindOutLine();
    p->DrawOutLine();
    p->Show();
    return 0;
}

二、图像凸包操作

凸包

        凸包指如果在集合A内连接任意两个点的直线段都在A的内部,则称集合A是凸形的。

        简单点理解,就是一个多边型,没有凹的地方。凸包(凸壳)能包含点集中所有的点,凸包检测常应用在物体识别、手势识别及边界检测等领域。一个轮廓可以有无数个包围它的外壳,而其中表面积最小的一个外壳,就是凸包。

凸包绘制步骤

  • 图像灰度处理

  • 灰度图二值化处理

  • 轮廓检测得到候选点

  • 凸包API调用,筛选可用点

  • 绘制显示

API介绍

void convexHull( InputArray points, OutputArray hull,bool clockwise = false, bool returnPoints = true );
/*******************************************************************
*           points:             轮廓点集                
*           hull:               凸包点集输出  
*           clockwise:          凸包方向的标志位
*                                   true:顺时针方向
*                                   false:逆时针
*           returnPoints:       返回点个数
*********************************************************************/

综合代码

注意:

        ①在做二值化处理之前,建议先用blur函数进行模糊处理(为了降噪)-->再去二值化处理效果会更好

        ②在画关键点和凸包处是一个重点。

 hull[(j+1)%count]随着j不断循环,最后一个点以及j+1取余之后会回到第一个点,实现闭环,完成凸包的绘制。

        ③ 绘制凸包前,需要得到外部轮廓的关键点,需要使用findContour函数去找并进行相应的存储

 #include <iostream>
#include <string>
#include <map>
#include <vector>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class ConvexHull 
{
public:
    ConvexHull() :img(imread("hand.jpg")) 
    {
        result["img"] = img;
    }
    void TestConvexHull()
    {
        //图像灰度处理
        cvtColor(result["img"], result["Gray"], COLOR_BGR2GRAY);
        //灰度图二值化处理
        blur(result["Gray"], result["Gray"], Size(3, 3));
        threshold(result["Gray"], result["Binary"], 240, 255, THRESH_BINARY_INV);
        //轮廓检测得到候选点
        vector<vector<Point>> contours;
        vector<Vec4i> hierarchy;
        findContours(result["Binary"], contours, hierarchy, RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
        //凸包API调用,筛选可用点
        //绘制显示
        for (int i = 0; i < contours.size(); i++) 
        {
            vector<Point> hull;
            convexHull(contours[i], hull);
            //bool isOk = isContourConvex(contours[i]);  //判断当前点是否为有效点
            int count = hull.size();
            for (int j = 0; j < count; j++) 
            {
                circle(img, hull[j], 5, Scalar(0, 0, 255));
                line(img, hull[j % count], hull[(j + 1) % count], Scalar(255, 0, 0), 2);
            }
        }
    }
    void Show() 
    {
        for (auto& v : result) 
        {
            imshow(v.first, v.second);
        }
        waitKey(0);
    }
private:
    Mat img;
    map<string, Mat> result;
};
​
int main() 
{
    ConvexHull* p = new ConvexHull;
    p->TestConvexHull();
    p->Show();
    return 0;
}

相关文章:

  • C语言运算符与表达式
  • Python从入门到实践:字节串与字符串
  • k8s教程:使用cert-manager证书管理工具在集群中提供https证书并自动续期
  • MIKE水动力笔记13_数字化海图2之克里金插值
  • QuantLib 金融计算库
  • OpenSergo CloudWeGo 共同保障微服务运行时流量稳定性
  • 全网最牛自动化测试框架系列之pytest(8)-参数化
  • App Store上架iOS App的详细流程
  • 链动2+1模式系统,如何抓住酒业新局的机遇?
  • 携创教育:2022年自考大专需要什么条件?怎么报名?
  • 基于Cookie-Editor与curl实现跨设备的文件下载
  • 百度智慧交通组-EdgeBoard基础操作合集
  • 1.4_8 Axure RP 9 for mac 高保真原型图 - 案例7 【旋转的唱片5】进度条计时器 关联
  • 岑溪农产品检验实验室建设细节概述
  • tf.convert_to_tensor
  • ES6指北【2】—— 箭头函数
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • 0x05 Python数据分析,Anaconda八斩刀
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • JAVA之继承和多态
  • Laravel5.4 Queues队列学习
  • nodejs调试方法
  • Promise面试题2实现异步串行执行
  • React-Native - 收藏集 - 掘金
  • ReactNative开发常用的三方模块
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 大数据与云计算学习:数据分析(二)
  • 大主子表关联的性能优化方法
  • 对JS继承的一点思考
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 规范化安全开发 KOA 手脚架
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 基于Android乐音识别(2)
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 前端知识点整理(待续)
  • 巧用 TypeScript (一)
  • 树莓派 - 使用须知
  • 提醒我喝水chrome插件开发指南
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 中文输入法与React文本输入框的问题与解决方案
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • $jQuery 重写Alert样式方法
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (Ruby)Ubuntu12.04安装Rails环境
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (四)汇编语言——简单程序
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转)ORM