图像处理与分析

一、照明与图像

光通量(Φ 流明 lm):光通量指人眼所能感觉到的辐射功率,它等于单位时间内某一波段的辐射能量和该波段的相对视见率的乘积。
辐照度(E 勒克斯 lux):辐照度指投射到一平表面上的辐射通量密度。指到达一表平面上,单位时间,单位面积上的辐射能。

1lux = 1 lm /m³

RGB与CMYK颜色模型

RGB:红绿蓝三原色
CMYK:品红 黄 青 三补色


两种颜色模型
HSI颜色模型
  • 色调H是描述纯色的属性(如红色、黄色等)
  • 饱和度S表示的是一种纯色被白光稀释的程度的度量
  • 亮度体现了无色的光强度概念,是一个主观的描述
HSI(HSV颜色模型)
OpenCV颜色空间转换

dst = cv.cvtColor(src, dst, code)
*src:输入
dst:输出
code:色彩空间转换模式

  • OpenCV中,彩色图像缺省为BGR格式,颜色三通道顺序为B,G,R,分别对应索引0,1,2
  • OpenCV中,HSI/HSV颜色空间中H的取值范围是0-180,其他两个是0-255
  • 两个相似的概念:HSI和HSV空间。HSV里面的v指的是RGB里面的最大的值,v=max(r,g,b);而HSI的是平均值,l=(r+g+b)/3;另外两个分量应该是一样的

二、图像平滑滤波

图像的卷积
  • 图像滤波由卷积定义:
  • 若滤波器对称:
  • 图像卷积操作,由卷积核逐点乘积后累加得到
  • 图像卷积操作需要事先将滤波器上下左右反转再计算
4-邻域 8-邻域

平均滤波
  • 在一个小区域内像素值平均:
    \frac {1} {5} \left[ \begin{array} { c c c } { 0 } & { 1 } & { 0 } \\ { 1 } & { 1 } & { 1 } \\ { 0 } & { 1 } & { 0 } \end{array} \right] \quad \frac {1} {8} \left[ \begin{array} { c c c } { 1 } & { 1 } & { 1 } \\ { 1 } & { 0 } & { 1 } \\ { 1 } & { 1 } & { 1 } \end{array} \right] \quad \frac {1} {9} \left[ \begin{array} { c c c } { 1 } & { 1 } & { 1 } \\ { 1 } & { 1 } & { 1 } \\ { 1 } & { 1 } & { 1 } \end{array} \right]

使图像边缘变得平滑,损失了图像的细节,核越大,图像越模糊,对椒盐噪声效果不佳


加权平均滤波
  • 在一个小区域内像素值加权平均:

高斯滤波:根据像素位置赋不同的权值,临近的像素具有更高的重要度

高斯滤波

使图像边缘变得平滑的同时不损失图像的细节,应用广泛


双边滤波
  • 权值同时与像素位置和灰度值有关

    其中\begin{aligned} w_{x,y,k,l} &= exp(- \frac {(x -k)^2+(y-l)^2}{2 {\sigma_d}^2} - \frac {||f(x,y) - f(k, l)||^2}{2 {\sigma_r}^2}) \\ &= { { d_{x, y, k, l } } \cdot { r_{x, y, k, l }} } \end{aligned}
    分别为空域核(高斯核)和值域核(类阶跃高斯核)
    双边滤波

中值滤波
  • 确定窗口及位置(含有奇数个像素)
  • 窗口内像素按灰度大小排序
  • 取中间值代替原窗口中心像素值

对孤立噪声特别有效,核越大图像越模糊,核必须是奇数


三、数学形态学滤波

膨胀


膨胀操作

腐蚀


腐蚀操作

腐蚀与膨胀

腐蚀:灰度值大的变小(图像变暗)
膨胀:灰度值大的变大(图像变亮)
膨胀腐蚀都会使图像颗粒化

开闭运算

开运算:先腐蚀后膨胀

闭运算:先膨胀后腐蚀

先开后闭:可有效去除噪声

开闭运算
OpenCV 图像滤波
滤波函数

dst = cv2.filter2D(src , ddepth, kernel, dst, anchor, delta, borderType)
src:输入图像
ddepth:目标图像的所需深度,包括CV_16S/CV_32F/CV_64F等
kernel:卷积核(或相当于相关核),单通道浮点矩阵;如果要将不同的内核应用于不同的通道,请使用拆分将图像拆分为单独的颜色平面,然后单独处理它们
dst:输出图像,与输入图像尺寸和通道数相同
anchor:内核的锚点,指示内核中过滤点的相对位置;锚应位于内核中;默认值(-1,-1) 表示锚位于内核中心
delta:在将它们存储在dst中之前,将可选值添加到已过滤的像素中。类似于偏置
borderType:卷积填充方式,包括BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT 等

常用滤波函数
  • 平均滤波
    dst=cv2.blur(src,ksizel,dst,anchor,borderType)
  • 高斯平滑滤波
    dst=cv2.GaussianBlur(src,ksize,sigmaX,dst,sigmaY,borderType)
  • 中值滤波
    dst=cv2.medianBlur(src,ksizeL,dst)
参数 描述
ksize 滤波器大小,如(5,5)
  • 双边滤波
    dst=cv2. bilateralFilter(src, d, sigmaColor, sigmaSpace, dst, borderType)
参数 描述
src 原始图像:8-bit或floating-point,1-channel或3-channel
dst 目标图像:size和type与原始图像相同
d 过滤期间使用的各像素邻域的直径
sigmacolor 色彩空间的sigma参数,该参数较大时,各像素邻域内相距较远的颜色会被混合到一起,从而造成更大范围的半相等颜色
sigmaSpace 坐标空间的sigma参数,该参数较大时,只要颜色相近,越远的像素会相互影响
borderType 卷积填充方式,包括BORDER_CONSTANT,BORDERREPLICATE, BORDER_REFLECT等
原图——————————均值滤波——————————高斯滤波——————————中值滤波——————————双边滤波

四、边缘检测

计算过程
  • 1.使用相应边缘检测滤波器(如果是卷积核需要进行上下左右翻转);
  • 2.进行卷积运算计算边缘检测结果
基本算子
  • Robert算子卷积核
  • Sobel 算子卷积核(常用)
  • Laplace算子
  • LoG算子
  1. 边缘检测即图像差分
  2. 常见边缘检测算子包括Robert算子,Sobel算子,LoG 算子等,其中Sobel算子最为常用
  3. 二维图像的边缘具有强度和方向两个性质
  • Canny算子
    优点:边缘可自动连通
  • 算法步骤:
    1.平滑图像
  • 使用高斯函数完成平滑,以 5×5 为例
    \begin{aligned} G(x,y) &= \frac {1} { \sqrt{2\pi} \sigma }{ exp \left[ { - \frac{x^2 + y^2 }{ \sigma^2 }} \right]} \\ K &= \frac {1} {139} \left[ \begin{array} { c c c c c} { 2 } & { 4 } & { 5 } &{ 4 } &{ 2 }\\ { 4 } & { 9 } & { 12 } &{ 9 } &{ 4 } \\ { 5 } & { 12 } & { 15 } &{ 12 } &{ 9 }\\ { 4 } & { 9 } & { 12 } &{ 9 } &{ 4 }\\ { 2 } & { 4 } & { 5 } &{ 4 } &{ 2 } \end{array} \right] \end{aligned}

2.计算梯度(幅值和方向)

  • 使用Sobel边缘检测算子对平滑图像进行xy方向的边缘检测,假设得到结果分别为,
  • 进一步计算梯度幅值和方向:
    \begin{aligned} M ( x , y ) &= \sqrt { E _ { x } ^ { 2 } ( x , y ) + E _ { y } ^ { 2 } ( x , y ) } \\ \theta ( x , y ) &= \tan ^ { - 1 } \left( \frac { E _ { y } ( x , y ) } { E _ { x } ( x , y ) } \right) \end{aligned}
  • 方向离散化

3.梯度幅值进行非极大值抑制

细化梯度幅值图像中的屋脊带,只保留幅值局部变化最大的点

4.自动边缘连接

  • 对上一步得到的图像使用低、高阈值阈值化,得到三幅图像
    \left\{ \begin{array} \\{ T _ { 1 } [ i , j ] \left( M ( i , j ) < \tau _ { 1 } \right) } \\ { T _ { 2 } [ i , j ] \left( \tau _ { 1 } \leq M ( i , j ) \leq \tau _ { 2 } \right) } \\ { T _ { 3 } [ i , j ] \left( M ( i , j ) > \tau _ { 2 } \right) } \end{array} \right.
    对应假边缘,去除
    对应真边缘,全部保留
    连接:临接像素中是否有属于的像素
  • 通过查看弱边缘像素及其8个邻域像素,只要其中一个为强 边缘像素,则该弱边缘点就可以保留为真实的边缘。

数学形态学边缘检测


  • 边缘梯度(gradient)
    定义:灰度膨胀图像与灰度腐蚀图像的差值


  • 顶帽与黑帽变换

顶帽变换(tophat)定义为图像与其开运算的差值:

黑帽变换(blackhat)定义为图像闭运算与自身的差值:

原图
顶帽变换 底帽变换

顶帽变换和底帽变换的结合使用能够应用于灰度图像的对比度增强
常用做法:将源图像加上顶帽变换再减去底帽变换 →增强对比度


  • 击中或击不中变换(HMT)
    输出图像由所有在中匹配的像素(击中)和未在中匹配的像素(击不中)组成

OpenCV实现边缘检测
  • Sobel算子边缘检测
    dst = cv2.Sobel(src , ddepth , dx , dy [, dst [, ksize [, scale [, delta [, borderType ]]]]] )
  • Laplace算子
    dst = cv2.Laplacian( src , ddepth [, dst [, ksize [, scale [, delta [, borderType ]]]]] )
  • Canny算子
    dst = cv2.Canny( image , threshold1 , threshold2 [, edges [, apertureSize [, L2gradient ]]] )
参数 描述
ddepth 目标图像的所需深度,包括CV_16S/CV_32F/CV_64F等
ksize 滤波器大小,通常可选为(5,5)或(3,3),或直接使用缺省
  • 形态学滤波
    dst = cv2.morphologyEx( src , op , kernel [, dst [, anchor [, iterations [, borderType [, borderValue ]]]]] )
参数 描述
src 原图像
op 形态学操作,包括MORPH_ERODE, MORPH_DILATE, MORPH_OPEN, MORPH_CLOSE,MORPH_GRADIENT, MORPH_TOPHAT, MORPH_BLACKHAT, MORPH_HITMISS
kernel 滤波结构元素,参见getStructuringElement
iterations 进行操作的次数

dst = cv2.getStructuringElement(shape , ksize [, anchor ] )
这个函数的第一个参数表示内核的形状,有三种形状可以选择。
矩形:MORPH_RECT;
交叉形:MORPH_CROSS;
椭圆形:MORPH_ELLIPSE;

1.OpenCV提供了Sobel,Canny等函数用于边缘检测
2. OpenCV提供了MorphologyEx函数用于形态学滤波


五、图像变换

常见几何变换
  • 放缩
  • 平移
  • 旋转
  • 镜像
距离变换
  • 通常作用于二值图像上,描述的是该位置像素点到最近的区域边界的距离。如果假设背景为黑(对应值为0),则为到最近0值的距离
距离变换
对数极坐标变换(Log-Polar变换)
  • 将图像像素坐标转换为极坐标,然后对距离取对数
    变换公式:
    反变换公式:
Log-Polar变换

Log-Polar变换应用:全景展开

六、灰度直方图

灰度直方图是关于灰度级分布的函数,是对图像中灰度级分布的统计。灰度直方图是将数字图像中的所有像素,按照灰度值的大小,统计其出现的频率。灰度直方图是灰度级的函数,它表示图像中具有某种灰度级的像素的个数,反映了图像中某种灰度出现的频率。通过直方图可判断图像曝光及对比度等情况 .


灰度直方图对图像照明特征的反映

越集中对比度越低

直方图均衡化
  • 直方图均衡化的作用就是图像增强
    需要满足条件:亮的依然亮,暗的依然暗。
  • 直方图映射方法:
局部直方图均衡化
  • 在图像的一个小邻域内使用直方图均衡化,直方图均衡可增加图像对比度
    缺点:在照度正常区域将对比度拉大容易出现明暗相间条纹
利用局部直方图统计进行灰度增强
  • 在图像的每个小邻域内,计算局部直方图,进而计算灰度和方差;
  • 根据需求,对图像的亮部或暗部进行增强。如前例需对暗部增强,
    (1)计算局部均值,与全局均值,如,则认为该点是候选点
    (2)进一步计算局部方差与全局方差,如,且(对标准差为0的区域不增强),则满足增强条件
    (3)对同时满足(1),(2)条件的点进行增强:

七、霍夫(Hough)变换

  • 功能:确定图像中哪些点对应一条直线
  • 核心思想:将原坐标(x,y)转换到参数空间中表示,进一步利用投票机制解决鲁棒性问题。
  • 直线方程表达:
    (1)斜率/截距:每一条直线对应一个,
    (2)法线式:
  • 直角坐标系的一点,对应参数空间中一条近似正弦曲线:
  • 同一条直线上的多个点,在空间中必相交于一点
    Hough变换
Hough变换步骤
  • 将空间量化成许多小格
  • 根据平面每一个点代入的量化值,算出各个
  • 将对应格计数累加
  • 当全部点变换后,对小格进行检验(投票机制)。设置累计阈值,计数器大于的小格对应于共线点,其可以用作直线拟合参数。小于T的反映非共线点,丢弃不用
图像变换OpenCV函数
  • 距离变换
dst  =   cv.distanceTransform(  src, distanceType ,  maskSize [ , dst [,  dstType ]]   ) 
参数 功能
distanceType 距离计算方式,DIST_L1DIST_L2DIST_C
maskSize 掩模尺寸,可取DIST_MASK_PRECISEDIST_MASK_3,5
  • Log-polar变换
dst  =   cv.logPolar(  src ,  center ,  M ,  flags [, dst] )
参数 功能
center 变换中心点
M 幅值尺度参数
flags 标志位,是插值方法和下面选项的组合:CV_WARP_FILL_OUTLIERS 填充目标图像中的所 有像素;CV_WARP_INVERSE_MAP 表示矩阵是从目标图像到源图像的反变换
  • 计算直方图
  matplotlib.pyplot.hist( x, bins=None, range=None,  ...) 
参数 功能
bins 多少个柱
range 显示的范围
  • 直方图均衡化
dst  =   cv.equalizeHist(  src  [, dst] )
  • 标准Hough变换
lines  = cv.HoughLines(  image ,  rho ,  theta ,  threshold [,  lines [,  srn [,  stn [,  min_theta [,  max_theta ]]]]] ) 
参数 功能
image 输入图像,应为二值图像,通常使用边缘检测结果;
rho 线段以像素为单位的距离精度,double类型的,推荐用1.0
theta 线段以弧度为单位的角度精度,推荐用numpy.pi/180
threshod 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线 段越长,检出的线段个数越少
  • 累计概率Hough变换
lines  = cv.HoughLinesP(  image ,  rho ,  theta ,  threshold [,  lines [,  minLineLength [,  maxLineGap ]]] ) 

效果更好,能检测大部分的直线线条!

八、图像分割

  • 目标:将图像划分为不同区域
  1. 图像分割是中层视觉的重要内容,具有广泛应用
  2. 图像分割的主要方法包括阈值法、区域法等
  3. 图像标记为分割后的结果打上不同标签,便于后续处理
灰度阈值分割
  • 假设:图像中的目标区和背景区之间或者不同目 标区之间,灰度存在明显差异


    Example
  • 凡是灰度值包含于z的像素都变成某一灰度值,其 他的变成另一个灰度值,则该图像就以为界被分成两个区域

  • 特殊的,如果=1和=0,分割后的图像为二值图像

自动阈值分割

自动确定最佳阈值,使背景和目标之间的差异 最大

  • 大津(Otsu)算法原理I
    根据统计分析理论,最佳阈值确定的最佳二分类应使类内方差最小,等同于类间方差最大
    大津算法基本思想:确定使灰度直方图类间方差最大的最佳阈值假设灰度直方图已经归一化,即
  • 假设阈值将像素灰度划为两类:和,则每一类出现的概率:


    其中 。显然有
  • 两类的类内方差:
    \sigma _ { 0 } ^ { 2 } = \sum _ { i = 1 } ^ { T } \left( i - \mu _ { 0 } \right) ^ { 2 } p _ { i } / \omega _ { 0 } , \sigma _ { 1 } ^ { 2 } = \sum _ { i = T + 1 } ^ { N } \left( i - \mu _ { 1 } \right) ^ { 2 } p _ { i } / \omega _ { 1 }
    对应的类间方差:
    \sigma _ { B } ^ { 2 } = \omega _ { 0 } \left( \mu _ { 0 } - \mu \right) ^ { 2 } + \omega _ { 1 } \left( \mu _ { 1 } - \mu \right) ^ { 2 } = \omega _ { 0 } \omega _ { 1 } \left( \mu _ { 1 } - \mu _ { 0 } \right) ^ { 2 }
  • 显然,是关于最佳阈值r的隐函数,应选取:
  • 大津算法是常用的一类灰度阈值自动选取方式,目标是令类间方差最大
  • 大津算法求解采用遍历方式,思想直接,实现速度快。
OpenCV边缘轮廓分割

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

参数 含义
image 单通道图像矩阵,可以是灰度图,但更常用的是经过边缘检测算子处理后的二值图像
contours 定义为vector>contours,是一个轮廓列表
hierarchy 存在嵌套轮廓时,分别为第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号
mode 定义轮廓的检索模式, 包括CV_RETR_EXTERNAL只检测最外围轮廓,CV_RETR_LIST检测所有轮廓,但不建立等级关系等
method 包括CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours
offset 所有的轮廓信息相对于原始图像对应点的偏移量, 缺省不设置

局部阈值分割
  • 全局阈值法存在的问题


    分割效果不佳

    局部阈值分割

    局部阈值分割效果

多阈值分割
多阈值分割

1. 局部阈值法可有效解决照明不均的问题
2. 多阈值法是二值化分割方法的扩展,可解决多值目标 的分割问题


区域生长法分割
  • 大津算法的局限性
    对于渐变的图像分割效果不佳

区域生长法:从种子点开始,按照一定准则(如 相邻像素灰度相似性)向周围扩散 ,将邻域相似像素加入区域中

区域生长实现步骤:

  1. 对图像顺序扫描。找到第1个还没有归属的像素, 设该像素为;
  2. 以为中心, 考虑(的8邻域像素,如果满足生长 准则, 将与 合并, 同时将压入堆栈;
  3. 从堆栈中取出一个像素, 把它当作返回到步骤2;
  4. 当堆栈为空时,返回到步骤1;
  5. 重复步骤1 - 4直到图像中的每个点都有归属时。生长结束。

图像分裂
图像分裂
  • 对区域分裂合并法无需预先指定种子点,它按某种一致性准则分裂 或者合并区域。
  • 可以先进行分裂运算,然后再进行合并运算;也可以分裂和合并运算 同时进行,经过连续的分裂和合并,最后得到图像的精确分割效果。
  • 分裂合并法对分割复杂的场景图像比较有效。

1. 区域生长法基于相邻像素间的相似性,由种子像素逐 步生长得到
2. 分裂-合并基于图像块内在的相似性,通过不断分裂得 到区域外边界,通过合并将不同块连接


分水岭分割
分水岭分割
  • 如果以图像位置为坐标,则图像可以看作是地形俯视图,其中“山峰的高度”与图像中的 灰度值对应。
  • 假设在每个“盆地”的最低点开始打洞让水漫上来,并且让水以均匀速率上升。那么,当不同“盆地”的水开 始汇聚时,能通过修建一个“水坝”挡住这种聚合的弧线就是图像的分界线

漫水原则

局部极小值点:该点对应一个盆地的最低点,当我们在盆地滴一滴水的时候,由于重力作用,水最终会汇聚到该点。注意:可能存在一个最小值面,该平面内的都是最小值点。
盆地的其它位置点:该位置滴的水滴会汇聚到局部最小点。
盆地的边缘点:是该盆地和其它盆地交接点,在该点滴一滴水,会等概率的流向任何一个盆地。

分水岭算法的过分割问题

由于噪声点或者其它干扰因素的存在,使用分水岭算法常常存在过度分 割的现象,这是因为很多很小的局部极值点的存在


分水岭算法的过分割问题

在初始时给marker,改善过分割问题,为了解决过度分割的问题,可以使用基于标记(mark)图像的分水岭算法,就是指定mark 图像,在这个区域的洪水淹没过程中,水平面都是从定义的marker开始的,这样可以避 免一些很小的噪声极值区域的分割。

加入Marker改善后的分割结果

Opencv实现

区域生长法:retval , image , mask , rect = cv.floodFill( image , mask , seedPoint , newVal [, loDiff [, upDiff [, flags]]] )
分水岭算法:markers = cv.watershed( image, markers #marker种子点

你可能感兴趣的:(图像处理与分析)