Opencv 图像分割: 阈值化分割 区域分割 边缘分割
卷积
就是两个函数之间的相互关系,然后得出一个新的值,在连续空间做积分计算,然后在离散空间内求和的过程。
在计算机视觉里面,可以把卷积当做一个抽象的过程,就是把小区域内的信息统计抽象出来
图像阈值化分割
按照灰度级,对像素集合进行一个划分,得到的每个子集形成一个与现实景物相对应的区域,
各个区域内部具有一致的属性,而相邻区域不具有这种一致属性。
它是一种传统的最常用的图像分割方法,因计算简单、运算效率较高、速度快、性能较稳定而成为图像分割中最基本和应用最广泛的分割技术。
它特别适用于目标和背景占据不同灰度级范围的图像,在极大的压缩数据量的同时也大大简化了分析和处理步骤,是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。
它有全局阈值、自适应阈值、最佳阈值等
二值化cvThreshold
/* Applies fixed-level threshold to grayscale image.
This is a basic operation applied before retrieving contours */
CVAPI(double) cvThreshold( const CvArr* src, CvArr* dst,
double threshold, double max_value,
int threshold_type );
src输入图像,须为单通道灰度图。
dst输出的边缘图像,为单通道黑白图。
threshold表示阈值
max_value表示最大值。
threshold_type表示二值化类型(即对图像取阈值的方法)
/* Threshold types */
enum
{
CV_THRESH_BINARY =0, /* value = value > threshold ? max_value : 0 */
//if src(x,y)>threshold dst(x,y) = max_value,
//otherwise dst(x,y) = 0,
CV_THRESH_BINARY_INV =1, /* value = value > threshold ? 0 : max_value */
//if src(x,y)>threshold dst(x,y) = 0,
//otherwise dst(x,y) = max_value,
CV_THRESH_TRUNC =2, /* value = value > threshold ? threshold : value */
//if src(x,y)>threshold dst(x,y) = threshold,
//otherwise dst(x,y) = src(x,y),
CV_THRESH_TOZERO =3, /* value = value > threshold ? value : 0 */
//if src(x,y)>threshold dst(x,y) = src(x,y),
//otherwise dst(x,y) = 0,
CV_THRESH_TOZERO_INV =4, /* value = value > threshold ? 0 : value */
//if src(x,y)>threshold dst(x,y) = 0,
//otherwise dst(x,y) = src(x,y),
CV_THRESH_MASK =7,
CV_THRESH_OTSU =8 /* use Otsu algorithm to choose the optimal threshold value;
combine the flag with one of the above CV_THRESH_* values */
//threshold_type使用CV_THRESH_OTSU,则cvThreshold()将使用大律法OTSU得到的全局自适应阈值来进行二值化图像,而参数中的threshold不再起作用
};
如:cvThreshold(grayImg, binaryImg, 145, 255, CV_THRESH_BINARY); //二值图
自适应二值化cvAdaptiveThreshold
函数使用Otsu算法(大律法或最大类间方差法)来计算出一个全局阈值,然后根据这个阈值进行二值化
Otsu实现思路
1、计算0~255各灰阶对应的像素个数,保存至一个数组中,该数组下标是灰度值,保存内容是当前灰度值对应像素数
2、计算背景图像的平均灰度、背景图像像素数所占比例
3、计算前景图像的平均灰度、前景图像像素数所占比例
4、遍历0~255各灰阶,计算并寻找类间方差极大值,此时对应的阈值就是大津法(OTSU算法)所求的阈值
/* Applies adaptive threshold to grayscale image.
The two parameters for methods CV_ADAPTIVE_THRESH_MEAN_C and
CV_ADAPTIVE_THRESH_GAUSSIAN_C are:
neighborhood size (3, 5, 7 etc.),
*/
CVAPI(void) cvAdaptiveThreshold( const CvArr* src, CvArr* dst, double max_value,
int adaptive_method CV_DEFAULT(CV_ADAPTIVE_THRESH_MEAN_C),
int threshold_type CV_DEFAULT(CV_THRESH_BINARY),
int block_size CV_DEFAULT(3),
double param1 CV_DEFAULT(5));
src输入图像
dst输出图像
max_value表示最大值
adaptive_method
自适应阈值算法使用:CV_ADAPTIVE_THRESH_MEAN_C 或 CV_ADAPTIVE_THRESH_GAUSSIAN_C .
threshold_type
阈值类型:必须是CV_THRESH_BINARY或者CV_THRESH_BINARY_INV.
block_size
用来计算阈值的象素邻域大小: 3, 5, 7, …,block_size比较小的时候,相当于提取边缘
param1
与方法有关的参数,它是一个从均值或加权均值提取的常数,它可以是负数。
对方法 CV_ADAPTIVE_THRESH_MEAN_C,先求出块中的均值,再减掉param1。
对方法 CV_ADAPTIVE_THRESH_GAUSSIAN_C ,先求出块中的加权和(gaussian),再减掉param1。
区域分割
图像按照相似性准则分成不同的区域,主要包括区域增长,区域分裂合并和分水岭等几种类型
边缘分割
通过边缘检测,即检测灰度级或者结构具有突变的地方,表明一个区域的终结,也是另一个区域开始的地方。
这种不连续性称为边缘。不同的图像灰度不同,边界处一般有明显的边缘,利用此特征可以分割图像
图像中边缘处像素的灰度值不连续,这种不连续性可通过求导数来检测到。
对于阶跃状边缘,其位置对应一阶导数的极值点,对应二阶导数的过零点(零交叉点)。
因此常用微分算子进行边缘检测。常用的:
一阶微分算子有Roberts算子、Prewitt算子和Sobel算子、LoG算子,
二阶微分算子有Laplace算子和Kirsh算子、Canny算子等。
在实际中各种微分算子常用小区域模板来表示,微分运算是利用模板和图像卷积来实现。这些算子对噪声敏感,只适合于噪声较小不太复杂的图像。
由于边缘和噪声都是灰度不连续点,在频域均为高频分量,直接采用微分运算难以克服噪声的影响。因此用微分算子检测边缘前要对图像进行平滑滤波。LoG算子和Canny算子是具有平滑功能的二阶和一阶微分算子,边缘检测效果较好
边缘检测算法:
滤波:边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数的计算对噪声很敏感,因此必须使用滤波器来改善与噪声有关的边缘检测器的性能.
增强:将邻域(或局部)强度值有显著变化的点突显出来.边缘增强一般是通过计算梯度幅值来完成的.
检测:确定边缘,最简单的边缘检测判据是梯度幅值阈值判据.
定位:边缘的位置、方位可在子像素分辨率上估计出来.
CV_EXPORTS_W void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize=3, bool L2gradient=false );
1、高斯平滑滤波器卷积降噪,默然采用size = 5的高斯内核
2、运用一对卷积阵列 (分别作用于x和y方向)求导,Sobel内核大小3 X 3,计算梯度幅值和方向
3、根据阀值、梯度幅值得出边缘
Canny边缘检测算法
一个多级边缘检测算法,普遍认为是边缘检测的最优算法,Canny使用滞后阈值,滞后阈值需要两个阈值(高阈值和低阈值)
Canny使用两种不同的阈值分别检测强边缘和弱边缘,并且仅当弱边缘和强边缘相连时,才将边缘包含在输出图像中。因此不容易被噪声“填充”,更容易检测出真正的弱边缘
原灰度图像: image single-channel 8-bit input image.
输出图像 (支持原地计算,可为输入图像): edges output edge map; it has the same size and type as image
低阈值的: threshold1 first threshold for the hysteresis procedure.
高阈值的3倍 (Canny 推荐的 高:低 阈值比在 2:1 到3:1之间): threshold2 second threshold for the hysteresis procedure.
//! applies generalized Sobel operator to the image
CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, int ksize=3,
double scale=1, double delta=0,
int borderType=BORDER_DEFAULT );
Sobel算子
(对灰度渐变和噪声较多的图像处理效果较好。Sobel算子对于边缘定位比较准确)
是一个离散微分算子 (discrete differentiation operator), 它用来计算图像灰度函数的近似梯度。
通过像素点空间邻域内上下,左右相邻点的灰度加权运算,求取物体边缘(边缘是指一个物体与另一个物体的分界处,一般边缘内外处都会有灰度值上的差异)
Sobel 算子结合了高斯平滑和微分求导, Scharr更准确地计算 3 X 3 核(Gx、Gy卷积因子)的导数
X\Y两个方向求导(输入图像与卷积核Gx和Gy进行卷积)-> 图像的每一点,结合以上两个结果求出近似梯度 -> 定位梯度值大于邻域的相素,作为边缘
ddepth: value as below
CV_8U = 0,
CV_8S = 1,
CV_16U = 2,
CV_16S = 3,
CV_32S = 4,
CV_32F = 5,
CV_64F = 6,
CV_USRTYPE1 = 7;