OpenCV 常用函数汇总(imread、floodFill、Canny、HoughLines、HoughLinesP)

cv::imread

  CV_EXPORTS_W Mat imread(
  const String& filename, //需要读取图像的文件名称,包括图像地址、名称和图像文件扩展名
  int flags = IMREAD_COLOR  //读取图像行驶的标志
  );
       IMREAD_UNCHANGED            = -1, //按照图像原样读取,保留Alpha通道
       IMREAD_GRAYSCALE            = 0,  //将图像转成单通道灰度图像后读取
       IMREAD_COLOR                = 1,  //将图像转成3通道BGR彩色图像
       IMREAD_ANYDEPTH             = 2,  //保留原图像的16位、32位深度,不声明该参数则转成8位读取
       IMREAD_ANYCOLOR             = 4,  //以任何可能的颜色读取图像
       IMREAD_LOAD_GDAL            = 8,  //使用gdal驱动程序加图像
       IMREAD_REDUCED_GRAYSCALE_2  = 16, //将图像转成单通道灰度图像,尺寸缩小 1/2。可以更改最后一位数组实现缩小 1/4(最后一位更改为4)和 1/8(最后一位更改为8)
       IMREAD_REDUCED_COLOR_2      = 17, //将图像转成3通道彩色图像,尺寸缩小 1/2。可以更改最后一位数组实现缩小 1/4(最后一位更改为4)和 1/8(最后一位更改为8)
       IMREAD_REDUCED_GRAYSCALE_4  = 32, //
       IMREAD_REDUCED_COLOR_4      = 33, //
       IMREAD_REDUCED_GRAYSCALE_8  = 64, //
       IMREAD_REDUCED_COLOR_8      = 65, //
       IMREAD_IGNORE_ORIENTATION   = 128 //不以 EXIF 的方向旋转图像

cv::floodFill

漫水填充法是根据像素灰度值之间的差值寻找相同区域以实现分割。可以将图像的灰度值理解成像素点的高度,这样一幅图像可以看成崎岖不平的地面或者山地,向地面上某一个低洼的地方倾倒一定量的水,水将掩盖低于某个高度的区域。
与地面注水一致,漫水填充法也需要在图像选择一个“注水”像素,改像素称为种子点,种子点按照一定规则不断向外扩散,从而形成具有相似特征的独立区域,进而实现图像分割。主要分为以下3个步骤:

  1. 选择种子点(x,y)
  2. 以种子点为中心,判断 4-邻域或者 8-邻域的像素值与种子点像素值的差值,将差值小于阈值的像素点添加进区域内
  3. 将新加入的像素点作为新的种子点,反复执行第二步,直到没有新的像素点被添加进该区域为止
cv::floodFill 原型1
 CV_EXPORTS_W int floodFill(
 InputOutputArray image, //输入及输出图像,图像可以为 CV_8U 或者 CV_32F 数据类型的单通道或者三通道图像
 InputOutputArray mask, //掩码矩阵,尺寸比输入图像宽和高各大2的单通道图像,用于标记漫水填充的区域
 Point seedPoint, //种子点
 Scalar newVal, //归入种子点区域内像素点的新像素值
 CV_OUT Rect* rect=0, //归入种子点区域的最小矩形边界,默认值为0,表示不输出边界
 Scalar loDiff = Scalar(), //添加进种子点区域条件的下界差值,当领域某像素点的像素值与种子点像素值的差值大于该值时,该像素点被添加进种子点所在的区域
 Scalar upDiff = Scalar(), //添加进种子点区域条件的上界差值,当种子点像素值与领域某像素点的像素值的差值小于该值时,该像素点被添加进种子点所在的区域
 int flags = 4 //漫水填充法的操作标志,由3部分构成,分别表示邻域种类、掩码矩阵中被填充像素点的像素值、填充算法的规则,下方给出填充算法规则
 );
标志简记含义
FLOODFILL_FIXED_RANGE1 << 16如果设置该参数,那么仅考虑当前像素值与初始种子点像素值之间的差值,否则考虑新种子点像素值与当前像素值之间的差异,即范围是否浮动的标志
FLOODFILL_MASK_ONLY1 << 17如果设置,那么该函数不会更改原始图像,即忽略第四个参数 newVal,只会生成掩码矩阵
  • 该函数的第一个参数既是输入图像又是输出图像
  • 该函数的第二个参数是漫水填充的矩阵掩码,非零像素点表示在原图像中被填充的区域。掩码矩阵的宽和高要比原图像的宽和高大2,并且需要在函数之间将该举证初始化。
  • 该函数的第三个参数是种子点,可以是图像范围内的任意一点
  • 该函数的第四个参数是被填充像素点的新像素值,该值会直接作用在原图中,对原图进行修改
  • 该函数的第五个参数是填充像素的最小矩阵区域
  • 该函数的第六个、第七个参数是像素点被填充的阈值条件,分别表示范围的上界和下界。
  • 该函数的最后一个参数是填充方法的操作标志,上文介绍了3部分,这3部分可以通过 | 符号连接,例如“4|(255<<8)|FLOODFILL_FIXED_RANGE”

有时我们并不需要使用掩码矩阵,输入掩码矩阵是对内存资源的浪费,因此提供了第二种原型,用于不输入矩阵掩码

cv::floodFill 原型2
 CV_EXPORTS int floodFill(
 InputOutputArray image,
 Point seedPoint,
 Scalar newVal,
 CV_OUT Rect* rect = 0,
 Scalar loDiff = Scalar(),
 Scalar upDiff = Scalar(),
 int flags = 4
 );

其余参数与上述原型1类似,由于函数不输出掩码矩阵,FLOODFOLL_MASK_ONLY标志不起任何作用,因此在该函数原型中没有任何意义,甚至可以默认表示掩码举证中被填充像素点的新像素值的第二部分

输出填充像素数目

cv::Canny

Canny 边缘检测

该算法不容易受到噪声的影响,能够识别图像中的弱边缘和强边缘,并结合强弱边缘的位置关系,综合给出图像整体的边缘信息。该方法的检测过程分为以下5个步骤:

  1. 使用高斯滤波平滑图像,减少图像中的噪点。
  2. 计算图像中每个像素的梯度方向和幅值。首先通过 Sobel 算子分别检测图像 X 方向的边缘和 Y 方向的边缘,之后计算梯度的方向和幅值。
  3. 应用非极大值抑制算法消除边缘检测带来的杂散响应。首先,将像素的梯度强度与沿正负梯度方向上的两个像素进行比较,如果当前像素的梯度强度与另外两个像素梯度强度相比最大,那么该像素点保留为边缘点,否则该像素点将被抑制。
  4. 应用双阈值法划分强边缘和弱边缘。将边缘处的梯度值与两个阈值进行比较,如果某像素的梯度幅值小于较小的阈值,那么会被去除;如果某像素的梯度幅值大于较小阈值、小于较大阈值,那么将该像素标记为弱边缘;如果某像素的梯度幅值大于较大阈值,那么将该像素标记为强边缘。
  5. 消除孤立的弱边缘。在弱边缘的8邻域范围寻找强边缘,如果8邻域内存在强边缘,就保留该弱边缘,否则将删除弱边缘,最终输出边缘检测结果
cv::Canny 函数原型
 CV_EXPORTS_W void Canny(
 InputArray image, //输入图像,必须是 CV_8u 的单通道或者三通道图像
 OutputArray edges, //输出图像,与输入图像具有相同尺寸的单通道图像,且数据类型为 CV_8U
 double threshold1, //第一个滞后阈值
 double threshold2, //第二个滞后阈值
 int apertureSize = 3, //Sobel 算子的直径
 bool L2gradient = false //计算图像梯度幅值方法的标志
 );

该函数利用 Canny 算法提取图像中的边缘信息。

  • 第一个参数是需要提取边缘的输入图像,目前只支持数据类型为 CV_8U的图像,输入图像可以是灰度图或者彩色图像。
  • 第二个参数是边缘检测结果的输出图像,图像是数据类型为 CV_8U 的但通道灰度图像。
  • 该函数的第三个、第四个参数是 Canny 算法中用于区分强边缘和弱边缘的两个阈值,两个参数不区分较大阈值和较小阈值,函数会自动比- 较区分两个阈值的大小。在一般情况下,较大阈值与较小阈值的比例在2:1到3:1之间。
  • 该函数最后一个参数是计算梯度幅度方法的选择标志,在无特殊需求的情况下,使用默认值即可。

cv::HoughLines

霍夫变换直线检测
霍夫变换是图像处理中检测是否存在直线的重要算法,霍夫变换算法检测图像中的直线主要分为以下4个步骤:

  1. 将参数空间的坐标轴离散化
  2. 将图像中每个非零像素通过映射关系求取在参数空间通过的方格
  3. 统计参数空间内每个方格出现的次数,选取次数大于某一阈值的方格作为表示直线的方格
  4. 将参数空间中表示直线的方格的参数作为图像中的直线的参数

霍夫变换具有抗干扰能力强,对图像中直线的残缺部分、噪声以及其他共存的非直线结果不敏感,能容忍特征边界描述的间隙,并且相对不受图像噪声影响等优点,但是霍夫变换的时间复杂度和空间复杂度都很高,并且检测精度受参数离散间隔制约。
离散间隔较大时会降低检测精度,离散间隔较小时虽然能提高精度,但是会增加计算负担,导致计算时间变长。
OpenCV 提供了两种用于检测图像中直线的相关函数,分别是标准霍夫变换和多尺度霍夫变换函数 HoughLines ,以及渐进概率式霍夫变换很熟 HoughLinesP

cv::HoughLines 函数原型
 CV_EXPORTS_W void HoughLines(
 InputArray image, //待检测直线的原图像,必须是 CV_8U 的单通道二值图像
 OutputArray lines, //霍夫变换检测到的直线极坐标描述的系数,每一条直线都由两个参数表示,分别表示直线距离坐标原点的距离 r 和坐标原点到直线的垂线与 x 轴的夹角
 double rho, //以像素为单位的距离分辨率,即距离 r 离散化时的单位长度
 double theta, //以弧度为单位的角度分辨率,即夹角 θ 离散化时的单位角度
 int threshold, //累加器的阈值,即参数空间中离散化后每个方格被通过的累计次数大于该阈值时将被识别为直线,否则不被识别为直线
 double srn = 0, //对于多尺度霍夫变换算法,该参数表示距离分辨率的出书,祖略的累加器距离分辨率是第三个参数 rho,精确的累加器分辨率是 rho/srn。这个参数必须是非负数,默认参数为 0 。
 double stn = 0, //对于多尺度霍夫变换算法,该参数表示角度分辨率的除数,祖略的累加器距离分辨率是第三个参数 theta,精确的累加器分辨率是 theta/stn。这个参数必须是非负数,默认参数为 0 。当这个参数与第六个参数 srn 同时为0时,此函数表示的是标准霍夫变换。
 double min_theta = 0, //检测直线的最小角度,默认参数为0
 double max_theta = CV_PI //检测直线的最大角度,默认参数为 CV_PI
 );

该函数用于寻找图像中的直线,并以极坐标的形式将图像中直线的极坐标参数输出。

  • 该函数第一个参数为输入图像,必须是 CV_8U 的单通道二值图像,如果需要检测彩色图像或者灰度图像中是否存在直线,可以通过 Canny 函数计算图像的边缘,并将边缘检测结果二值化后的图像作为出入图像赋值给该参数。
  • 该函数的第二个参数是霍夫变换检测到的图像中直线极坐标描述的系数,是一个 Nx2 的 vector 矩阵,每一行中的第一个元素是直线距离坐标原点的距离,第二个元素是该直线过坐标原点的垂线与x轴的夹角,这里需要注意的是,图像中的坐标原点在图像的左上角。
  • 该函数第三个、第四个参数分别是霍夫变换中对参数空间坐标轴进行离散化后的单位长度和单位角度,这两个参数的大小直接影响到检测图像中直线的精度,数值越小,进度越高。
  • 其中第三个参数表示参数空间r轴的单位长度,单位为像素,该参数常设置为1;第四个参数表示参数空间θ轴的单位角度,单位为弧度,该参数常设置为 CV_PI/180
  • 该函数的第五个参数是累加器的阈值,表示参数空间中某个方格是否被认定为直线的判定标准,这个数值越大,对应在原图像中构成直线的像素点越多,反之则越少。
  • 该函数的第六个、第七个参数起到选择标准霍夫变换和多尺度霍夫变换的作用。

重点说明第二个函数原型

cv::HoughLinesP 函数原型
 CV_EXPORTS_W void HoughLinesP(
 InputArray image, //待检测直线的原图像,必须是 CV_8C 的单通道二值图像
 OutputArray lines, //霍夫变换检测到的直线或者线段两个端点的坐标,每一条直线都由4个参数进行描述,分别是直线两个端点的坐标(x1,y1,x2,y2)
 double rho, //以像素为单位的距离分辨率。即距离 r 离散化时的单位长度
 double theta, //以弧度为单位的角度分辨率,即夹角 θ 离散化时的单位角度
 int threshold, //累加器的阈值,即参数空间中离散化后每个方格被通过的累计次数大于阈值时被识别为直线,否则不被识别为直线
 double minLineLength = 0, //直线的最小长度,当检测直线的长度小于该数值时将被剔除
 double maxLineGap = 0 //同一直线上相邻的两个点之间的最大距离
 );

该函数用于寻找图像中满足条件的直线或者线段两个端点的坐标。

  • 该函数的第一个参数为输入图像,必须是 CV_8U 的单通道二值图像,如果需要检测彩色图像或者灰度图像中是否存在直线,可以通过 Canny 函数计算图像的边缘,并将边缘检测结果二值化后的图像作为输入图像赋值给该参数。
  • 该函数的第二个参数是通过图像中直线或者线段两个端点的坐标,是一个 Nx4 的 vector 矩阵。Vec4i 中前两个元素分别是直线或者线段的第一个端点的x坐标和y坐标,后两个元素分别是直线或者线段另一个端点的x坐标和y坐标。
  • 该函数的第三个、第四个参数含义与 HoughLines函数中对应的参数含义相同,这两个参数的大小直接影响到检测图像中直线的精度,数值越小,精度越高。
  • 该函数的第五个参数是累加器的阈值,表示参数空间中某个方格是否被认定为直线的判定标准,这个数值越大,对应在原图像中的直线越长,反之则越短。
  • 第六个参数是检测直线或者线段的长度,如果图像中直线的长度小于这个阈值,及时是直线也不会作为最终结果输出。
  • 该函数的左后一个参数是同一条直线上邻近两个点连续的最大距离,这个参数主要能够控制倾斜直线的检测长度,当提取较长的倾斜直线时,该参数应该具有较大取值
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值