opencv---(腐蚀、膨胀、边缘检测、轮廓检索、凸包、多边形拟合)

一、腐蚀(Erode)

  取符合模板的点, 用区域最小值代替中心位置值(锚点)

  作用: 平滑对象边缘、弱化对象之间的连接。

opencv 中相关函数:(erode)

 1 //      C++
 2 /**
 3 shape:  形状
 4                   MORPH_RECT  矩形
 5                   MORPH_CROSS   交叉形  十字型
 6                   MORPH_ELLIPSE   椭圆形
 7 esize : 大小
 8 anchor: 锚点,默认为中心
 9 **/
10 Mat getStructuringElement(int shape, Size esize, Point anchor = Point(-1, -1));
11
12 /**
13 src:  input Mat
14 dst:  output Mat
15 element : kernel element
16 完整参数:https://docs.opencv.org/4.1.0/d4/d86/group__imgproc__filter.html#gaeb1e0c1033e3f6b891a25d0511362aeb
17 **/
18 erode(const Mat& src, Mat&dst , const Mat& element)  // 基本参数

 1 # python
 2 #    dst    =    cv.erode(    src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]    )
 3
 4 import cv2 as cv
 5 import numpy as np
 6
 7 im = cv.imread("test.jpg")
 8 gray = cv.cvtColor(im,cv.COLOR_BGR2GRAY)
 9 ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)
10
11 # 获取 kerenl element
12 kernel = cv.getStructuringElement(cv.MORPH_RECT,(5,5))
13 # 腐蚀
14 dst = cv.erode(binary,kernel)

二、 膨胀(Dilate)

  实现: 使用kernel 划过图像,将区域的最大值赋给锚点位置。

  作用: 致使图像的亮区扩展,能起到平滑边缘的作用。

// C++
/**
src:  input Mat
dst:  output Mat
kernel : kernel element
完整参数:https://docs.opencv.org/master/d4/d86/group__imgproc__filter.html#ga4ff0f3318642c4f469d0e11f242f3b6c
 **/#include<opencv2\imgproc\imgproc.hpp>
void  dilate(InputArray src, OutputArray dst , InputArray kernel)  // 基本参数

三、边缘检测

边缘检测一般步骤:

  平滑去噪

对比度增强

计算梯度

过滤判断边缘

1、Canny 边缘检测

 1 // C++
 2 #include<opencv2\imgproc\imgproc.hpp>
 3
 4 /**
 5 image  : 输入图像
 6 edges  :  输出图像
 7 threshold1: 阈值1,高于该值 被认为时边缘
 8 threshold2: 阈值2, 低于该值可认为不是边缘
 9                                 若在两值之间,该像素仅连接一个高阈值的像素时被保留。
10 apertureSize : kernel 大小,默认3  sobel kernel ,;取值 1 3 5 7 (奇数,<31)
11 L2gradient : L2 norm 求梯度
12
13 详细参数: https://docs.opencv.org/3.4/dd/d1a/group__imgproc__feature.html#ga04723e007ed888ddf11d9ba04e2232de
14 **/
15 void  Canny (InputArray  image,  OutputArray   edges,  double threshold1,  double threshold2,  int apertureSize = 3,  bool  L2gradient = false  )

1 import numpy as np
2 import cv2 as cv
3
4 # edges    =    cv.Canny(    image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]    )
5
6 img = cv2.imread(‘3.jpg‘,0)
7 edges = cv2.Canny(img,100,200)

2、 sobel

sobel kernel:

X 方向3X3:                                                                                                       Y方向3x3:

                                             

X 方向5x5:

在opencv sobel 函数中当ksize =-1 时:kernel 为:SCHARR

opencv 中函数:
 1 // C++
 2 #include <opencv2/imgproc.hpp>
 3
 4 /** https://docs.opencv.org/master/d4/d86/group__imgproc__filter.html#gacea54f142e81b6758cb6f375ce782c8d
 5     src:   输入图像
 6     dst:   输出图像
 7     ddepth: output image depth
 8                           src.depth() = CV_8U     ---------------    ddepth =-1/CV_16S/CV_32F/CV_64F
 9                           src.depth() = CV_16U/CV_16S -----    ddepth =-1/CV_32F/CV_64F
10                           src.depth() = CV_64F    ---------------    ddepth = -1/CV_64F
11      dx  / dy  :  差分阶数 0  or 1
12      ksize:   取奇数  -1 : SCHARR (3x3)   1: 1x3  or 3x1
13 **/
14 void cv::Sobel( InputArray src, OutputArray  dst, int ddepth, int dx, int dy,int ksize=3, double scale=1, double delta=0, int borderType = BORDER_DEFAULT )
1 import cv2 as cv
2 import numpy as np
3
4 # dst = cv.Sobel(  src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]  )
5
6 img = cv.imread(‘flower.jpg‘,0)
7 #默认ksize=3
8 sobelx = cv.Sobel(img,cv2.CV_64F,1,0,ksize=3)

四、二值图像的轮廓分析

opencv  中可以使用 findContours()工具,分析二值图像的拓扑结构

void findContours//提取轮廓,用于提取图像的轮廓
(
    InputOutputArray image,//输入图像,必须是8位单通道图像,并且应该转化成二值的
    OutputArrayOfArrays contours,//检测到的轮廓,每个轮廓被表示成一个point向量
    OutputArray hierarchy,//可选的输出向量,包含轮廓的拓扑信息。其中元素的个数和检测到的轮廓的数量相等
    int mode,     //说明需要的轮廓类型和希望的返回值方式
    int method,//轮廓近似方法
    Point offset = Point()
)

参数说明:

hierarchy:  每一个轮廓,都包含4个整型数据,分别表示:后一个轮廓的序号前一个轮廓的序号子轮廓的序号父轮廓的序号

mode: 轮廓检索模式

  method :

      1)、CV_CHAIN_APPROX_NONE  边界上所有连续点

2)、CV_CHAIN_APPROX_SIMPLE   拐点

      3)and 4) 、 CV_CHAIN_APPROX_TC89_L1  、  CV_CHAIN_APPROX_TC89_KCOS  使用teh-Chinl chain 近似法

# python
import cv2 as cv
import numpy as np

#     contours, hierarchy    =    cv.findContours(    image, mode, method[, contours[, hierarchy[, offset]]]    )

img = cv.imread(‘12.jpeg‘)
gray = cv.cvtColor ( img , cv2.COLOR_BGR2GRAY )
ret , binary = cv.threshold ( gray , 220 , 255 , cv2.THRESH_BINARY )

# 检测轮廓
contours , hierarchy = cv.findContours ( binary , cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE )

# 画出轮廓
cv.drawContours(img,contours,-1,(0,0,255),3) 

‘‘‘
void cv::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:输入输出图像,Mat类型即可
#contours:使用findContours检测到的轮廓数据,每个轮廓以点向量的形式存储,point类型的vector
#contourIdx:绘制轮廓的只是变量,如果为负值则绘制所有输入轮廓
#color:轮廓颜色
#thickness:绘制轮廓所用线条粗细度,如果值为负值,则在轮廓内部绘制
#lineTpye:线条类型,有默认值LINE_8
‘‘‘

五、 凸包 和 多边形拟合

凸包:

opencv 中使用 convexHull() 函数来查找对象的凸包。

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

参数: points: input 2D point set, stored in std::vector or Mat.

hull : 输出参数,用于输出函数调用后找到的凸包

clockwise : 操作方向,true顺时针,fasle逆时针

详细参考: https://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga014b28e56cb8854c0de4a211cb2be656

多边形拟合:

opencv 中使用 approxPolyDP() 函数对图像的轮廓点进行多边形拟合。

void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)

参数:

    curve : Input vector of a 2D point stored in std::vector or Mat

approxCurve : 表示输出的多边形点集

    epsilon:    精度,两个轮廓点之间的最大距离数

closed:  表示输出的多边形是否封闭

#include<opencv2\opencv.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<iostream>

using namespace std;
using namespace cv;

int  main()
{
    //  三通道二值图像
    Mat img = imread("E:\\pcblabels\\labels2019-11-01-094405.jpg");
    cout << "read image end..." << endl;

    // 膨胀
    Mat kernel = getStructuringElement(MORPH_RECT, Size(6, 6));
    Mat dilateImg;
    dilate(img, dilateImg, kernel);
    cout << "dilate end....." << endl;

    // 腐蚀
    Mat erodeImg;
    erode(dilateImg, erodeImg, kernel);
    cout << "erode end....." << endl;

    // canny
    Mat cannyImg;
    Canny(dilateImg, cannyImg, 5, 2, 5); // ksize: 奇数
    cout << "Canny end....." << endl;

    // find contours
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    // 只检测最外层轮廓,并且保存轮廓上所有点
    findContours(cannyImg, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());
    drawContours(contours, hierarchy, img.size());

    // 找一个点数最多的轮廓
   int index = 0;
    for (int i = 0; i< contours.size(); i++)
    {
        if (contours[i].size() > contours[index].size())
        {
        index = i;
    }
    }
    cout << "findContours end....." << endl;

     //凸包
    Mat hullImg = img.clone();
    vector<Point> hull;
    convexHull(Mat(contours[index]), hull, true);
    drawContours(hullImg, vector<vector<Point>>{hull}, 0, Scalar(0,0,255), 1, 8, vector<Vec4i>(), 0, Point());
    cout << "draw hull end....." << endl;   

    // 多边形拟合
    Mat approxImg = img.clone();
    Mat approxImgRes = Mat::zeros(img.size(), CV_8UC1);
    vector<Point> approxPloy;
    approxPolyDP(contours[index], approxPloy, 1, true);
    drawContours(approxImg, contours, index, Scalar(255, 0, 0), 1, 8, hierarchy);
    drawContours(approxImgRes, vector<vector<Point>>{approxPloy}, 0, Scalar(255), 2, 8, vector<Vec4i>(), 0, Point());
    cout << "draw approxPolyDP end....." << endl;

    return 0;
}
        

  

   

  

原文地址:https://www.cnblogs.com/feihu-h/p/11814150.html

时间: 2024-10-19 19:14:48

opencv---(腐蚀、膨胀、边缘检测、轮廓检索、凸包、多边形拟合)的相关文章

opencv cv.findContours 函数详解 图像轮廓层级 图像轮廓检索方式详解

函数 cv.findContours contours, hierarchy = cv.findContours( image, mode, method[, contours[, hierarchy[, offset]]] ) 参数1:源图像 参数2:轮廓的检索方式,这篇文章主要讲解这个参数 参数3:一般用 cv.CHAIN_APPROX_SIMPLE,就表示用尽可能少的像素点表示轮廓 contours:图像轮廓坐标,是一个链表 hierarchy:[Next, Previous, First

OpenCV入门之寻找图像的凸包(convex hull)

介绍   凸包(Convex Hull)是一个计算几何(图形学)中的概念,它的严格的数学定义为:在一个向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包.  在图像处理过程中,我们常常需要寻找图像中包围某个物体的凸包.凸包跟多边形逼近很像,只不过它是包围物体最外层的一个凸集,这个凸集是所有能包围这个物体的凸集的交集.如下图所示: 在上图中,绿色线条所包围的凸集即为白色图形的凸包.  在opencv中,通过函数convexHulll能很容易的得到一系列点的凸包,比如由点组成的轮廓

图像形态学操作—腐蚀膨胀深入

这里我们主要想讲解冈萨雷斯的数字图像处理这本书上膨胀腐蚀的定义及用opencv实现的结果,然后对比它们之间的差异. 一:opencv实现 在这之前可以看我的另外一篇blog:http://blog.csdn.net/lu597203933/article/details/17184439 膨胀: 案例代码: int main() { int a[8][8] = { {0,0,0,0,0,0,0,0}, {0,0,5,1,0,0,1,1}, {0,1,0,1,0,1,0,0}, {0,1,1,2,

基于FPGA的腐蚀膨胀算法实现

本篇文章我要写的是基于的腐蚀膨胀算法实现,腐蚀膨胀是形态学图像处理的基础,,腐蚀在二值图像的基础上做"收缩"或"细化"操作,膨胀在二值图像的基础上做"加长"或"变粗"的操作.那么什么是二值图像呢?把一幅图片看做成一个二维的数组,那么二值图像是一个只有0和1的逻辑数组,我们前面Sobel边缘检测后的图像输出边缘效果,设置个阈值,大于阈值输出为1,小于阈值输出为0,最后输出就是一幅二维图像了. 上一篇我是直接用MATLAB处理后的

opencv使用convexityDefects计算轮廓凸缺陷

引自:http://www.xuebuyuan.com/1684976.html http://blog.csdn.net/lichengyu/article/details/38392473 http://www.cnblogs.com/yemeishu/archive/2013/01/19/2867286.html谈谈NITE 2与OpenCV结合提取指尖坐标 一 概念: Convexity hull, Convexity defects 如上图所示,黑色的轮廓线为convexity hul

基于MATLAB的腐蚀膨胀算法实现

本篇文章要分享的是基于MATLAB的腐蚀膨胀算法实现,腐蚀膨胀是形态学图像处理的基础,腐蚀在二值图像的基础上做“收缩”或“细化”操作,膨胀在二值图像的基础上做“加长”或“变粗”的操作. 什么是二值图像呢?把一幅图片看做成一个二维的数组,那么二值图像是一个只有0和1的逻辑数组,我们前面Sobel边缘检测后的图像输出边缘效果,设置个阈值,大于阈值输出为1,小于阈值输出为0,最后输出就是一幅二维图像了. 腐蚀 腐蚀是一种消除边界点,使边界向内部收缩的过程.可以用来消除小且无意义的物体.用3X3的结构元

形态学腐蚀膨胀操作

1.腐蚀操作 增强图像的暗部(图像矩阵中数值更小的部分),滤波得到的新像素点为滤波器内最小的值,也就是用最暗的点代替滤波器内的锚点 erode(src,dst,kernel,Point,epoch_num) 参数分别为:输入图像,输出图像,滤波器,锚点(一般为Point(-1,-1)),迭代次数(默认为一次) 2.膨胀操作 增强图像的亮部(图像矩阵中数值更大的部分),滤波得到的心像素点为滤波器内的最大值,也就是用最亮的点代替滤波器内的锚点 dilate(src,dst,kernel,Point,

opencv初学习-椒盐噪声-中值滤波-均值滤波-腐蚀膨胀

#include <opencv2\opencv.hpp>#include <opencv2\highgui\highgui.hpp>#include <opencv2\imgcodecs\imgcodecs.hpp>#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<iomanip>void salt(cv

opencv 轮廓的外围多边形提取或者删除最小最大轮廓

std::vector resultpoly; cv::approxPolyDP(contours[0], resultpoly,4, true);//轮廓contours[0] ,resultpoly多边形的点集 cv::polylines(src, resultpoly, true, 150, 1);//画多边形的外轮廓 cv::imshow("detected polyLines", src);//显示多边形的外轮廓 //相关链接https://www.cnblogs.com/d