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 的方向旋转图像
漫水填充法是根据像素灰度值之间的差值寻找相同区域以实现分割。可以将图像的灰度值理解成像素点的高度,这样一幅图像可以看成崎岖不平的地面或者山地,向地面上某一个低洼的地方倾倒一定量的水,水将掩盖低于某个高度的区域。
与地面注水一致,漫水填充法也需要在图像选择一个“注水”像素,改像素称为种子点,种子点按照一定规则不断向外扩散,从而形成具有相似特征的独立区域,进而实现图像分割。主要分为以下3个步骤:
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_RANGE | 1 << 16 | 如果设置该参数,那么仅考虑当前像素值与初始种子点像素值之间的差值,否则考虑新种子点像素值与当前像素值之间的差异,即范围是否浮动的标志 |
FLOODFILL_MASK_ONLY | 1 << 17 | 如果设置,那么该函数不会更改原始图像,即忽略第四个参数 newVal,只会生成掩码矩阵 |
有时我们并不需要使用掩码矩阵,输入掩码矩阵是对内存资源的浪费,因此提供了第二种原型,用于不输入矩阵掩码
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标志不起任何作用,因此在该函数原型中没有任何意义,甚至可以默认表示掩码举证中被填充像素点的新像素值的第二部分
输出填充像素数目
Canny 边缘检测
该算法不容易受到噪声的影响,能够识别图像中的弱边缘和强边缘,并结合强弱边缘的位置关系,综合给出图像整体的边缘信息。该方法的检测过程分为以下5个步骤:
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 算法提取图像中的边缘信息。
霍夫变换直线检测
霍夫变换是图像处理中检测是否存在直线的重要算法,霍夫变换算法检测图像中的直线主要分为以下4个步骤:
霍夫变换具有抗干扰能力强,对图像中直线的残缺部分、噪声以及其他共存的非直线结果不敏感,能容忍特征边界描述的间隙,并且相对不受图像噪声影响等优点,但是霍夫变换的时间复杂度和空间复杂度都很高,并且检测精度受参数离散间隔制约。
离散间隔较大时会降低检测精度,离散间隔较小时虽然能提高精度,但是会增加计算负担,导致计算时间变长。
OpenCV 提供了两种用于检测图像中直线的相关函数,分别是标准霍夫变换和多尺度霍夫变换函数 HoughLines ,以及渐进概率式霍夫变换很熟 HoughLinesP
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_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 //同一直线上相邻的两个点之间的最大距离
);
该函数用于寻找图像中满足条件的直线或者线段两个端点的坐标。