基于模板匹配的马赛克检验

基于模板匹配的视频马赛克实时检测

本方法来自于论文《Fast Mosaic Detection for Real-time Video Based on Template Matching Strategy》。

算法描述

  1. 计算图像的灰度梯度
    使用Canny边缘检测算子(论文阐述的是Canny算子,但Canny检测是基于Sobel算子的多步骤检测,因此在实现时采用Sobel算子),分别计算得到水平方向和竖直方向的灰度梯度,称为灰度一阶导数。Sobel算子如下图所示,(G_x)是用于计算水平梯度,(G_y)用于计算竖直梯度。(文末附有梯度计算原理)

    根据计算原理可知,(G_x)计算得到的在数值上反映了图像在水平方向的突变程度,如果图像上有很多竖条纹,那么其水平梯度将会很高。类似的,(G_y)可可以反映图像中横条纹情况。
  2. 得到二值边缘图
    选择合适的门限值,让水平和竖直的灰度图二值化。如果灰度值高于门限值为255,低于门限值设为0。
    门限的选择很关键:门限越低,边缘线越多,检测结果越容易受到噪音影响。相反,门限过高,将导致图像细节丢失。
  3. 预处理边缘图像
    计算灰度梯度(G_x)在每一列的二值总和,设定一个门限值,如果总和值大于等于线门限,则表明这列存在竖条纹,记下该列位置,如果低于线门限,什么也不做。对水平方向做类似处理,计算(G_y)在每行的二值总和,设定门限值,记下可能存在横条纹的行位置。
  4. 使用模板匹配检测相交位置的Mosaic Point
    行列位置相交的点可能是马赛克点,但需要进一步检测判断。在候选点左、右、上和下四个方向,统计二值灰度梯度值为255的点数。如果点数表明,该位置存在下图所示的五个模板之一,则判定该点是马赛克点。
  5. 识别马赛克图片
    设定一定的门限值,如果马赛克点足够多,则可认为是该图存在马赛克。

Canny边缘检测详解

一直对边缘检测算子一知半解,网上的也都是摘抄别人的理论,下面自己写写。

opencv中的canny函数

void Canny(InputArray img, //单通道8位输入图像
    OutputArray edges,     //输出边缘图,和img有相同size和type
    double thresh1,        //first threshold for the 滞后处理程序
    double thresh2,        //second threshold for the hysteresis procedure
    int apertureSize = 3,    //孔径 size for the Sobel() operator.
    bool L2gradient = false);

L2gradient = ture:(L_2=sqrt{(frac{dI}{dx})^2+(frac{dI}{dy})^2})用于计算图像梯度值;
L2gradient = false:(L_1=|frac{dI}{dx}|+|frac{dI}{dy}|)

void cvCanny(const CvArr* image,
     CvArr* edges,
     double thresh1,
     double thresh2,
    int apertureSize = 3);

以上函数可以帮助我们从一副图像获得包含符合条件的边缘图像edges,需要给定两个门限值。但中间的处理过程不是很清楚。

Canny边缘检测算法

算法处理过程:

  1. 对输入的灰度图进行Gaussian滤波,除燥;
    高斯核尺寸的大小会影响检测结果,尺寸越大,检测器对噪音的敏感程度越低,对局部边缘的检测错误将会稍多。需根据实际情况选择。
  2. 找到图像中梯度强度;
    图像的边可以指向很多方向,所以Canny算法使用四个filter检测横、竖、斜边。边缘检测算子(例如Robets,Prewitt或Sobel)返回的是水平方向、竖直方向的一阶导数值(G_x)(G_y)。根据这两个值,可以得出边的幅值G和方向( heta)

[G=sqrt{G_x^2+G_y^2} ]

[ heta=atan2(G_y, G_x) ]

  1. 非极大值抑制法;
    非极大值抑制主要用于"瘦边"。梯度计算后,从梯度值提取的边很模糊,对于图像的边,应当只有一个精确响应,因此,本步骤只保留局部最大值,抑制了所有梯度值为0,局部最大值表示了强度变化最尖锐的位置。
  2. 双门限决定潜在边缘;
  3. 根据hysteresis跟踪边缘。

附:梯度推导

假设数字图像在(x,y)位置的像素值记为(f(x,y))(注意:以水平方向为x,以竖直方向为y),在该位置的梯度由二维列向量定义:

[ abla vec f=egin{bmatrix}G_x \ G_yend{bmatrix}=egin{bmatrix}frac {partial f} {partial x} \ frac {partial f} {partial y}end{bmatrix} ag{1} ]

该梯度向量的模值通常被称为“梯度”,可通过下式计算得到:

[ abla f = | abla vec f| = {sqrt{{G_x}^2+{G_y}^2}} ag{2} ]

为了简化上式梯度值的计算,用如下近似求解梯度模值:

[ abla f = |G_x| + |G_y| ag{3} ]

一阶微分的求解,可通过如下求得:

[frac {partial f} {partial x} = f(x+1,y) - f(x,y) ag{4} ]

所以,梯度模值可通过下式计算得到:

[ abla f = |f(x+1,y)-f(x,y)| + |f(x,y+1)-f(x,y)| ag{5} ]

根据上式,sobel算子就是通过近似等于的思想,将梯度计算进行了转化:利用当前点所在的右排减去左排值,同时赋予当前排的位置较高权重,公式表示如下,

[ abla f = |[f(x+1,y-1)+2f(x+1,y)+f(x+1,y+1)]-[(f(x-1,y-1)+2f(x-1,y)+f(x-1,y+1))]| \ +|[f(x-1,y+1)+2f(x,y+1)+f(x+1,y+1)]-[f(x-1,y-1)+2f(x,y-1)+f(x+1,y-1)]| ag{7}]

上式第一个绝对值项对应的卷积核就是Sobel的G_x算子,第二个绝对值项对应的就是G_y算子。这就是Sobel算子计算梯度的方法。
(注:冈萨雷斯的书中以竖直方向为x方向,与通常习惯有差异,结果也有差异。)

原文地址:https://www.cnblogs.com/imagezy/p/7009121.html