【OpenCV学习笔记】6.边缘检测

  • 图像的边缘指的是灰度发生急剧变化的位置。边缘检测的目的是制作一个线图,在不损害理解图像内容的情况下,同时大大减少图像数据量,提供对图像数据的合适概述。
  • 边缘检测大多是通过基于方向导数掩码(梯度方向导数)求卷积的方法。

1.Roberts算子

  • Roberts边缘检测是图像矩阵与以下两个卷积核分别做卷积:
    R o b e r t s 135 = ( 1 0 0 − 1 ) , R o b e r t s 45 = ( 0 1 − 1 0 ) Roberts_{135}=\begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}, Roberts_{45}=\begin{pmatrix} 0 & 1 \\ -1 & 0 \end{pmatrix} Roberts135=(1001),Roberts45=(0110)
  • 与Roberts核卷积,本质上是两个对角方向上的差分。对Roberts算子进行改进,如下反映的是垂直方向和水平方向上的边缘:
    R o b e r t s x = ( 1 − 1 ) , R o b e r t s y = ( 1 − 1 ) Roberts_x=\begin{pmatrix} 1 & -1 \end{pmatrix}, Roberts_y=\begin{pmatrix} 1 \\ -1 \end{pmatrix} Robertsx=(11),Robertsy=(11)
  • 大多数边缘检测算子时基于方向差分卷积核求卷积的方法,在使用由多个卷积核组成的边缘检测算子时,假设有n个卷积核,记 c o v 1 、 c o v 2 、 … 、 c o v n cov_1、cov_2、…、cov_n cov1cov2covn为图像分别与各卷积核做卷积后的结果,通常有四种方式衡量最后输出的边缘强度。
    (1)取对应位置绝对值的和: ∑ i = 1 n ∣ c o v i ∣ \sum_{i=1}^n|cov_i| i=1ncovi
    (2)取对应位置平方和的开方: ∑ i = 1 n c o v i 2 \sqrt{\sum_{i=1}^ncov_i^2} i=1ncovi2
    (3)取对应位置绝对值得最大值: m a x { ∣ c o v 1 ∣ , ∣ c o v 2 ∣ , … , ∣ c o v n ∣ } max\{|cov_1|,|cov_2|,…,|cov_n|\} max{ cov1,cov2,,covn}
    (4)插值法: ∑ i = 1 n a i ∣ c o v i ∣ \sum_{i=1}^na_i|cov_i| i=1naicovi,其中 a i ≥ 0 a_i\geq0 ai0,且 ∑ i = 1 n a i = 1 \sum_{i=1}^na_i=1 i=1nai=1
    其中,取绝对值的最大值的方式对边缘的走向有些敏感,其他几种方式可以获得性能更一致的全方位响应。取平方和开方效果一般最好,但更加耗时。
void roberts(InputArray src, OutputArray dst, int ddepth, int x = 1, int y = 0, int borderType = BORDER_DEFAULT)
{
    
    
	CV_Assert(!(x == 0 & y == 0));
	Mat roberts_1 = (Mat_<float>(2, 2) << 1, 0, 0, -1);
	Mat roberts_2 = (Mat_<float>(2, 2) << 0, 1, -1, 0);
	//当x不等于0,src和roberts_1卷积
	if (x != 0 && y == 0)
		conv2D(src, roberts_1, dst, ddepth, Point(0, 0), borderType); 
	if (y != 0 && x == 0)
		conv2D(src, roberts_2, dst, ddepth, Point(0, 0), borderType);
}

void conv2D(InputArray src, InputArray kernel, OutputArray dst, int ddepth,
	Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT)//卷积运算
{
    
    
	//卷积运算第一步:卷积核逆时针翻转180°
	Mat kernelFlip;
	flip(kernel, kernelFlip, -1);
	//卷积运算第二步
	filter2D(src, dst, ddepth, kernelFlip, anchor, 0.0, borderType);
}

2.Prewitt边缘检测

  • 标准的Prewitt边缘检测算子由以下两个卷积核组成:
    p r e w i t t x = ( 1 0 − 1 1 0 − 1 1 0 − 1 ) , p r e w i t t y = ( 1 1 1 0 0 0 − 1 − 1 − 1 ) prewitt_x=\begin{pmatrix} 1&0&-1\\ 1&0&-1\\ 1&0&-1\\ \end{pmatrix}, prewitt_y=\begin{pmatrix} 1&1&1\\ 0&0&0\\ -1&-1&-1 \end{pmatrix} prewittx=111000111,prewitty=101101101
  • 图像与 p r e w i t t x prewitt_x prewittx卷积后可以反映图像垂直方向的边缘,与 p r e w i t t y prewitt_y prewitty卷积后可以反映图像水平方向的边缘。这两个卷积核可分离:
    p r e w i t t x = ( 1 1 1 ) ⋆ ( 1 0 − 1 ) prewitt_x= \begin{pmatrix} 1\\1\\1 \end{pmatrix} \star \begin{pmatrix} 1&0&-1 \end{pmatrix} prewittx=111(101) ,
    p r e w i t t y = ( 1 1 1 ) ⋆ ( 1 0 − 1 ) prewitt_y= \begin{pmatrix} 1&1&1 \end{pmatrix} \star \begin{pmatrix} 1\\0\\-1 \end{pmatrix} prewitty=(111)101
  • 由于对图像进行了平滑处理,所以对噪声较多的图像进行Prewitt边缘检测得到的边缘比Roberts要好。可以对标准的Prewitt算子改进,比如:
    p r e w i t t 135 = ( 1 1 0 1 0 − 1 0 − 1 − 1 ) , p r e w i t t 45 = ( 0 1 1 − 1 0 1 − 1 − 1 0 ) prewitt_{135}=\begin{pmatrix} 1&1&0\\ 1&0&-1\\ 0&-1&-1\\ \end{pmatrix}, prewitt_{45}=\begin{pmatrix} 0&1&1\\ -1&0&1\\ -1&-1&0 \end{pmatrix} prewitt135=110101011,prewitt45=011101110
void prewitt(InputArray src, OutputArray dst, int ddepth, int x = 1, int y = 0, int borderType = BORDER_DEFAULT)
{
    
    
	CV_Assert(!(x == 0 & y == 0));
	//当x不等于0,src和prewitt_x卷积
	if (x != 0 && y == 0)
	{
    
    
		Mat prewitt_x_y = (Mat_<float>(3, 1) << 1, 1, 1);
		Mat prewitt_x_x = (Mat_<float>(1, 3) << 1, 0, -1);
		sepConv2D_X_Y(src, dst, ddepth, prewitt_x_x, prewitt_x_y, Point(-1, -1), borderType);
	}
	//当x等于0且y不等于0,src和prewitt_y卷积
	if (y != 0 && x == 0)
	{
    
    
		Mat prewitt_y_x = (Mat_<float>(1, 3) << 1, 1, 1);
		Mat prewitt_y_y = (Mat_<float>(3, 1) << 1, 0, -1);
		sepConv2D_X_Y(src, dst, ddepth, prewitt_y_x, prewitt_y_y, Point(-1, -1), borderType);
	}
}

void sepConv2D_X_Y(InputArray src, OutputArray dst, int ddepth, InputArray kernelX, InputArray kernelY,
	Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT)//可分离的离散二维卷积
{
    
    
	//输入矩阵与水平方向卷积核的卷积
	Mat src_kerX;
	conv2D(src, kernelX, src_kerX, ddepth);
	//上面结果与垂直方向卷积核的卷积
	conv2D(src_kerX, kernelY, dst, ddepth);
}

3.Sobel边缘检测

  • 将高斯卷积算子的二项式近似展开的系数,可以作为非归一化的高斯平滑算子,利用 n = 2 n=2 n=2时展开项的系数,把Prewitt算子的非归一化的均值平滑算子换成该系数,即得三阶Sobel边缘检测算子:
    s o b e l x = ( 1 2 1 ) ⋆ ( 1 0 − 1 ) = ( 1 0 − 1 2 0 − 2 1 0 − 1 ) sobel_x= \begin{pmatrix} 1\\2\\1 \end{pmatrix} \star \begin{pmatrix} 1&0&-1 \end{pmatrix} =\begin{pmatrix} 1&0&-1\\ 2&0&-2\\ 1&0&-1\\ \end{pmatrix} sobelx=121(101)=121000121 ,
    s o b e l y = ( 1 2 1 ) ⋆ ( 1 0 − 1 ) = ( 1 2 1 0 0 0 − 1 − 2 − 1 ) sobel_y= \begin{pmatrix} 1&2&1 \end{pmatrix} \star \begin{pmatrix} 1\\0\\-1 \end{pmatrix} =\begin{pmatrix} 1&2&1\\ 0&0&0\\ -1&-2&-1\\ \end{pmatrix} sobely=(121)101=101202101
void Sobel(InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, 
           double scale=1, double selta=0, int borderType=BORDER_DEFAULT)
//src-输入矩阵
//dst-输出矩阵
//ddepth-输出矩阵数据类型
//dx-不等于0时,src与差分方向为水平方向上的Sobel核卷积
//dy-dx为0、dy不为0时,src与差分方向为垂直方向上的Sobel核卷积
//ksize-sobel核的尺寸,值为1,3,5,7
//scale-比例系数
//delta-平移系数
//borderType-边界扩充类型

4.Scharr算子

  • 标准Scharr边缘检测算子与Prewitt边缘检测算子和Sobel边缘检测算子类似:
    s c h a r r x = ( 3 0 − 3 10 0 − 10 3 0 − 3 ) , s c h a r r y = ( 3 10 3 0 0 0 − 3 − 10 − 3 ) scharr_x=\begin{pmatrix} 3&0&-3\\ 10&0&-10\\ 3&0&-3\\ \end{pmatrix}, scharr_y=\begin{pmatrix} 3&10&3\\ 0&0&0\\ -3&-10&-3 \end{pmatrix} scharrx=31030003103,scharry=30310010303
    拓展到其他方向:
    p r e w i t t 135 = ( 10 3 0 3 0 − 3 0 − 3 − 10 ) , p r e w i t t 45 = ( 0 3 10 − 3 0 3 − 10 − 3 0 ) prewitt_{135}=\begin{pmatrix} 10&3&0\\ 3&0&-3\\ 0&-3&-10\\ \end{pmatrix}, prewitt_{45}=\begin{pmatrix} 0&3&10\\ -3&0&3\\ -10&-3&0 \end{pmatrix} prewitt135=10303030310,prewitt45=03103031030
void Scharr(InputArray src, OutputArray dst, int ddepth, int dx, int dy, 
           double scale=1, double selta=0, int borderType=BORDER_DEFAULT)
//src-输入矩阵
//dst-输出矩阵
//ddepth-输出矩阵数据类型
//dx-不等于0时,src与差分方向为水平方向上的Sobel核卷积
//dy-dx为0、dy不为0时,src与差分方向为垂直方向上的Sobel核卷积
//scale-比例系数
//delta-平移系数
//borderType-边界扩充类型

5.Kirsch算子和Robinson算子

  • Kirsch算子由以下八个卷积核组成:
    k 1 = ( 5 5 5 − 3 0 − 3 − 3 − 3 − 3 ) k 2 = ( − 3 − 3 − 3 − 3 0 − 3 5 5 5 ) k 3 = ( − 3 5 5 − 3 0 5 − 3 − 3 − 3 ) k 4 = ( − 3 − 3 − 3 5 0 − 3 5 5 − 3 ) k_1=\begin{pmatrix} 5&5&5\\ -3&0&-3\\ -3&-3&-3 \end{pmatrix} k_2=\begin{pmatrix} -3&-3&-3\\ -3&0&-3\\ 5&5&5 \end{pmatrix} k_3=\begin{pmatrix} -3&5&5\\ -3&0&5\\ -3&-3&-3 \end{pmatrix} k_4=\begin{pmatrix} -3&-3&-3\\ 5&0&-3\\ 5&5&-3 \end{pmatrix} k1=533503533k2=335305335k3=333503553k4=355305333
    k 5 = ( − 3 − 3 5 − 3 0 5 − 3 − 3 5 ) k 6 = ( 5 − 3 − 3 5 0 − 3 5 − 3 − 3 ) k 7 = ( − 3 − 3 − 3 − 3 0 5 − 3 5 5 ) k 8 = ( 5 5 − 3 5 0 − 3 − 3 − 3 − 3 ) k_5=\begin{pmatrix} -3&-3&5\\ -3&0&5\\ -3&-3&5 \end{pmatrix} k_6=\begin{pmatrix} 5&-3&-3\\ 5&0&-3\\ 5&-3&-3 \end{pmatrix} k_7=\begin{pmatrix} -3&-3&-3\\ -3&0&5\\ -3&5&5 \end{pmatrix} k_8=\begin{pmatrix} 5&5&-3\\ 5&0&-3\\ -3&-3&-3 \end{pmatrix} k5=333303555k6=555303333k7=333305355k8=553503333
    图像与每一个核进行卷积,然后取绝对值作为对应方向上的边缘强度的量化。对8个卷积结果取绝对值,然后在对应值位置取最大值作为最后输出的边缘强度。
  • Robinson算子由以下八个卷积核组成:
    r 1 = ( 1 1 1 1 − 2 1 − 1 − 1 − 1 ) r 2 = ( 1 1 1 − 1 − 2 1 − 1 − 1 1 ) r 3 = ( − 1 1 1 − 1 − 2 1 − 1 1 1 ) r 4 = ( − 1 − 1 1 − 1 − 2 1 1 1 − 1 ) r_1=\begin{pmatrix} 1&1&1\\ 1&-2&1\\ -1&-1&-1 \end{pmatrix} r_2=\begin{pmatrix} 1&1&1\\ -1&-2&1\\ -1&-1&1 \end{pmatrix} r_3=\begin{pmatrix} -1&1&1\\ -1&-2&1\\ -1&1&1 \end{pmatrix} r_4=\begin{pmatrix} -1&-1&1\\ -1&-2&1\\ 1&1&-1 \end{pmatrix} r1=111121111r2=111121111r3=111121111r4=111121111
    r 5 = ( − 1 − 1 − 1 1 − 2 1 1 1 1 ) r 6 = ( 1 − 1 − 1 1 − 2 − 1 1 1 1 ) r 7 = ( 1 1 − 1 1 − 2 − 1 1 1 − 1 ) r 8 = ( 1 1 1 1 − 2 − 1 1 − 1 − 1 ) r_5=\begin{pmatrix} -1&-1&-1\\ 1&-2&1\\ 1&1&1 \end{pmatrix} r_6=\begin{pmatrix} 1&-1&-1\\ 1&-2&-1\\ 1&1&1 \end{pmatrix} r_7=\begin{pmatrix} 1&1&-1\\ 1&-2&-1\\ 1&1&-1 \end{pmatrix} r_8=\begin{pmatrix} 1&1&1\\ 1&-2&-1\\ 1&-1&-1 \end{pmatrix} r5=111121111r6=111121111r7=111121111r8=111121111

6.Canny边缘检测

  • 基于卷积运算的边缘检测算法,比如Sobel、Prewitt等,有如下两个缺点:
    (1)没有充分利用梯度的边缘方向。
    (2)最后输出的边缘二值图,阈值处理过于简单。
  • Canny边缘检测基于这两点做了改进:
    (1)基于边缘梯度方向的非极大值抑制。
    (2)双阈值的滞后阈值处理。
void Canny(InputArray image, OutputArray edges, double threshold, double threshold2, int apertureSize=3, bool L2gradient=false)
//apertureSize-Sobel核的窗口大小
//L2gradient-true代表使用平方和开方,false代表绝对值

7.Laplacian算子

  • 二维函数 f ( x , y ) f(x,y) f(x,y)的Laplacian变换,由以下计算公式定义:
    ▽ 2 f ( x , y ) = ∂ 2 f ( x , y ) ∂ 2 x + ∂ 2 f ( x , y ) ∂ 2 y \bigtriangledown^2f(x,y)=\frac{\partial^2f(x,y)}{\partial^2x}+\frac{\partial^2f(x,y)}{\partial^2y} 2f(x,y)=2x2f(x,y)+2y2f(x,y)
                                     ≈ ∂ ( f ( x + 1 , y ) − f ( x , y ) ) ∂ x + ∂ ( f ( x , y + 1 ) − f ( x , y ) ) ∂ y \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\approx\frac{\partial(f(x+1,y)-f(x,y))}{\partial x}+\frac{\partial (f(x,y+1)-f(x,y))}{\partial y} x(f(x+1,y)f(x,y))+y(f(x,y+1)f(x,y))
                                     ≈ f ( x + 1 , y ) + f ( x − 1 , y ) + f ( x , y + 1 ) + f ( x , y − 1 ) − 4 f ( x , y ) \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\approx f(x+1,y)+f(x-1,y)+f(x,y+1)+f(x,y-1)-4f(x,y) f(x+1,y)+f(x1,y)+f(x,y+1)+f(x,y1)4f(x,y)

  • 将其推广到离散的二维数组,即矩阵的拉普拉斯变换是矩阵与拉普拉斯核的卷积:
    l 0 = ( 0 − 1 0 − 1 4 − 1 0 − 1 0 ) l_0=\begin{pmatrix} 0&-1&0\\ -1&4&-1\\ 0&-1&0 \end{pmatrix} l0=010141010 l 0 − = ( 0 1 0 1 − 4 1 0 1 0 ) l_{0^-}=\begin{pmatrix} 0&1&0\\ 1&-4&1\\ 0&1&0 \end{pmatrix} l0=010141010

  • 此外,拉普拉斯算子还有其它形式:
    l 1 = ( − 1 − 1 − 1 − 1 8 − 1 − 1 − 1 − 1 ) l 2 = ( 2 − 1 2 − 1 − 4 − 1 2 − 1 2 ) l 3 = ( 0 2 0 2 − 8 2 0 2 0 ) l 4 = ( 2 0 2 0 − 8 0 2 0 2 ) l_1=\begin{pmatrix} -1&-1&-1\\ -1&8&-1\\ -1&-1&-1 \end{pmatrix} l_2=\begin{pmatrix} 2&-1&2\\ -1&-4&-1\\ 2&-1&2 \end{pmatrix} l_3=\begin{pmatrix} 0&2&0\\ 2&-8&2\\ 0&2&0 \end{pmatrix} l_4=\begin{pmatrix} 2&0&2\\ 0&-8&0\\ 2&0&2 \end{pmatrix} l1=111181111l2=212141212l3=020282020l4=202080202

  • 拉普拉斯核内所有值的和必须等于0,拉普拉斯算子均是不可分离的。

void Laplacian(InputArray src, OutputArray dst, int ddepth, int ksize=1, 
           double scale=1, double selta=0, int borderType=BORDER_DEFAULT)
//src-输入矩阵
//dst-输出矩阵
//ddepth-输出矩阵数据类型
//ksize-拉普拉斯核的类型,1对应l0-,3对应l4
//scale-比例系数
//delta-平移系数
//borderType-边界扩充类型

8.高斯拉普拉斯(LoG)边缘检测

  • 拉普拉斯边缘检测算子没有对图像做平滑处理,会对噪声产生明显响应。因此可以利用二维高斯函数 g a u s s ( x , y , σ ) = 1 2 π σ e x p ( − x 2 + y 2 2 σ 2 ) gauss(x,y,\sigma)=\frac{1}{2\pi\sigma}exp(-\frac{x^2+y^2}{2\sigma^2}) gauss(x,y,σ)=2πσ1exp(2σ2x2+y2)的拉普拉斯变换:
    ▽ 2 ( g a u s s ( x , y , σ ) ) = ∂ 2 ( g a u s s ( x , y , σ ) ) ∂ 2 x + ∂ 2 ( g a u s s ( x , y , σ ) ) ∂ 2 y \bigtriangledown^2(gauss(x,y,\sigma))=\frac{\partial^2(gauss(x,y,\sigma))}{\partial^2x}+\frac{\partial^2(gauss(x,y,\sigma))}{\partial^2y} 2(gauss(x,y,σ))=2x2(gauss(x,y,σ))+2y2(gauss(x,y,σ))
                                                                 = 1 2 π σ 2 ∂ ( − x σ 2 e x p ( − x 2 + y 2 2 σ 2 ) ) ∂ x + 1 2 π σ 2 ∂ ( − y σ 2 e x p ( − x 2 + y 2 2 σ 2 ) ) ∂ y \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;=\frac{1}{2\pi\sigma^2}\frac{\partial(-\frac{x}{\sigma^2}exp(-\frac{x^2+y^2}{2\sigma^2}))}{\partial x}+\frac{1}{2\pi\sigma^2}\frac{\partial(-\frac{y}{\sigma^2}exp(-\frac{x^2+y^2}{2\sigma^2}))}{\partial y} =2πσ21x(σ2xexp(2σ2x2+y2))+2πσ21y(σ2yexp(2σ2x2+y2))
                                                                 = 1 2 π σ 4 ( x 2 σ 2 − 1 ) e x p ( − x 2 + y 2 2 σ 2 ) + 1 2 π σ 4 ( y 2 σ 2 − 1 ) e x p ( − x 2 + y 2 2 σ 2 ) \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;=\frac{1}{2\pi\sigma^4}(\frac{x^2}{\sigma^2}-1)exp(-\frac{x^2+y^2}{2\sigma^2})+\frac{1}{2\pi\sigma^4}(\frac{y^2}{\sigma^2}-1)exp(-\frac{x^2+y^2}{2\sigma^2}) =2πσ41(σ2x21)exp(2σ2x2+y2)+2πσ41(σ2y21)exp(2σ2x2+y2)
                                                                 = 1 2 π σ 4 ( x 2 + y 2 σ 2 − 2 ) e x p ( − x 2 + y 2 2 σ 2 ) \;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;=\frac{1}{2\pi\sigma^4}(\frac{x^2+y^2}{\sigma^2}-2)exp(-\frac{x^2+y^2}{2\sigma^2}) =2πσ41(σ2x2+y22)exp(2σ2x2+y2)
  • 高斯拉普拉斯边缘检测具体步骤如下:
    第一步:构建窗口大小围 H × W H\times W H×W、标准差为 σ \sigma σ的LoG卷积核。
    L o G H × W = [ ▽ 2 g a u s s ( w − W − 1 2 , h − H − 1 2 , σ ] 0 ≤ h ≤ H , 0 ≤ w ≤ W LoG_{H\times W}=[\bigtriangledown^2gauss(w-\frac{W-1}{2},h-\frac{H-1}{2},\sigma]_{0\leq h\leq H,0\leq w \leq W} LoGH×W=[2gauss(w2W1,h2H1,σ]0hH,0wW
    其中 H H H W W W均为奇数,且 H = W H=W H=W,锚点位置 ( H − 1 2 , W − 1 2 ) (\frac{H-1}{2},\frac{W-1}{2}) (2H1,2W1)
    第二步:图像矩阵与 L o G H × W LoG_{H\times W} LoGH×W核卷积,结果记为I_Cov_LoG。
    第三步:边缘二值化显示。
  • 对于高斯拉普拉斯核的尺寸,一般取 ( 6 ∗ σ + 1 ) × ( 6 ∗ σ + 1 ) (6*\sigma+1)\times(6*\sigma+1) (6σ+1)×(6σ+1)。标准差越大,边缘尺度越大,会失去更多图像边缘细节。

9.高斯差分(DoG)边缘检测

10.Marr-Hildreth边缘检测

  • Marr-Hildreth边缘检测方法相对于高斯差分和高斯拉普拉斯边缘检测,细化了最后的阈值处理过程,可以获得更加详细的边缘信息。
    第一步:构建窗口大小围 H × W H\times W H×W的高斯拉普拉斯核或者高斯差分卷积核。
    第二步:图像矩阵与 L o G H × W LoG_{H\times W} LoGH×W核或者 D o G H × W DoG_{H\times W} DoGH×W卷积。
    第三步:寻找过零点位置,即为边缘位置。
  • 过零点: f ( x ) f(x) f(x)突变, f ′ ( x ) f^{'}(x) f(x)最大值, f ′ ′ ( x ) f^{''}(x) f(x)为0。

猜你喜欢

转载自blog.csdn.net/weixin_44496838/article/details/102990083