1.腐蚀原理
图像的腐蚀过程一般也是通过结构元素模板操作,有点类似于卷积运算,其具体过程:将结构模板在图像上滑动,如果结构模板对应为1的点遇到图像上不为1的点(此时图像已经被二值化了,如果是彩色图像,可以通过和阈值比大小),那么该点的像素值可以被设置为0;还有一种腐蚀方法:依次对结构元素模板中所有为1的位置对应的像素进行检测,取出其中的最小值min,将当前结构元素所在位置的像素值置为min。腐蚀的作用是消除物体的边界点和消除一些小东西。
/*采用二值图算法,定义阈值K,对于灰度大于k的像素认为存在,否则认为不存在, 二值图腐蚀处理*/
QImage* MainWindow::Erosiontiongary(QImage* image, int k)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[7][7] = {
{ 0,0,0,1,0,0,0 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 1,1,1,1,1,1,1 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 0,0,0,1,0,0,0 } };
int sizeKernel = 7;
QColor color;
QColor Rcolor;
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int r = 0;
int g = 0;
int b = 0;
int hr = 1;
int hg = 1;
int hb = 1;
Rcolor = QColor(image->pixel(x, y));
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() < k && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j] && hr == 1)
{
hr = 0;
}
while (color.green() < k && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j] && hg == 1)
{
hg = 0;
}
while (color.blue() < k && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j] && hb == 1)
{
hb = 0;
}
}
}
if (hr == 0)
{
r = 0;
}
else
{
r = color.red();
}
if (hg == 0)
{
g = 0;
}
else
{
g = color.green();
}
if (hb == 0)
{
b = 0;
}
else
{
b = color.blue();
}
newImage->setPixel(x, y, qRgb(r, g, b));
}
}
return newImage;
}
/*采用最小描述算法,腐蚀处理*/
QImage* MainWindow::Erosiontionrgb(QImage* image)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[7][7] = {
{ 0,0,0,1,0,0,0 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 1,1,1,1,1,1,1 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 0,0,0,1,0,0,0 } };
int sizeKernel = 7;
QColor color;
QColor Rcolor;
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 255;
int kg = 255;
int kb = 255;
Rcolor = QColor(image->pixel(x, y));
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() < kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() < kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() < kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage->setPixel(x, y, qRgb(kr, kg, kb));
}
}
return newImage;
}
2.膨胀原理
图像的膨胀过程一般也是通过结构元素模板操作,有点类似于卷积运算,其具体过程:将结构模板在图像上滑动,如果结构模板任意有一个对应为1的点遇到图像上为1的点(此时图像已经被二值化了,如果是彩色图像,可以通过和阈值比大小),那么该点的像素值可以被设置为1;还有一种腐蚀方法:依次对结构元素模板中所有为1的位置对应的像素进行检测,取出其中的最大值max,将当前结构元素所在位置的像素值置为max。腐蚀的作用是扩展物体的边界点和连接临近区域。
/*采用二值图算法,定义阈值K,对于灰度大于k的像素认为存在,否则认为不存在, 二值图膨胀处理*/
QImage* MainWindow::Dilationgary(QImage* image, int k)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[7][7] = {
{ 0,0,0,1,0,0,0 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 1,1,1,1,1,1,1 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 0,0,0,1,0,0,0 } };
int sizeKernel = 7;
QColor color;
QColor Rcolor;
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int r = 0;
int g = 0;
int b = 0;
int hr = 1;
int hg = 1;
int hb = 1;
Rcolor = QColor(image->pixel(x, y));
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() >= k && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j] && hr == 1)
{
hr = 0;
}
while (color.green() >= k && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j] && hg == 1)
{
hg = 0;
}
while (color.blue() >= k && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j] && hb == 1)
{
hb = 0;
}
}
}
if (hr == 0)
{
r = color.red();
}
else
{
r = 0;
}
if (hg == 0)
{
g = color.green();
}
else
{
g = 0;
}
if (hb == 0)
{
b = color.blue();
}
else
{
b = 0;
}
newImage->setPixel(x, y, qRgb(r, r, r));
}
}
return newImage;
}
/*采用最大描述算法,膨胀处理*/
QImage* MainWindow::Dilationrgb(QImage* image)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[7][7] = {
{ 0,0,0,1,0,0,0 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 1,1,1,1,1,1,1 },
{ 0,1,1,1,1,1,0 },
{ 0,1,1,1,1,1,0 },
{ 0,0,0,1,0,0,0 } };
int sizeKernel = 7;
QColor color;
QColor Rcolor;
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 0;
int kg = 0;
int kb = 0;
Rcolor = QColor(image->pixel(x, y));
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() > kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() > kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() > kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage->setPixel(x, y, qRgb(kr, kg, kb));
}
}
return newImage;
}
3.腐蚀与膨胀的简单应用
图像内边界提取:将原图像进行腐蚀,然后再与原图像进行异或运算
图像外边界提取:将原图像进行膨胀,然后再与原图像进行异或运算
空心图像提取:分别结合两次内外边界提取
/*提取二值图的内边界*/
QImage*MainWindow::SideInner(QImage* image)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[3][3] = {
{ 1,1,1 },
{ 1,1,1 },
{ 1,1,1 }
};
int sizeKernel = 3;
QColor color;
QColor newcolor;
int r = 0;
int g = 0;
int b = 0;
/*腐蚀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 255;
int kg = 255;
int kb = 255;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() < kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() < kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() < kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*end*/
for (int y = 0; y<image->height(); y++)
{
for (int x = 0; x<image->width(); x++)
{
color = QColor(image->pixel(x, y));
newcolor = QColor(newImage->pixel(x, y));
if (color.red() != newcolor.red())
{
r = 255;
}
else
{
r = 0;
}
if (color.green() != newcolor.green())
{
g = 255;
}
else
{
g = 0;
}
if (color.blue() != newcolor.blue())
{
b = 255;
}
else
{
b = 0;
}
newImage->setPixel(x, y, qRgb(r, g, b));
}
}
return newImage;
}
/*提取二值图的外边界*/
QImage*MainWindow::SideOutter(QImage* image)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[3][3] = {
{ 1,1,1 },
{ 1,1,1 },
{ 1,1,1 }
};
int sizeKernel = 3;
QColor color;
QColor newcolor;
int r = 0;
int g = 0;
int b = 0;
/*膨胀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 0;
int kg = 0;
int kb = 0;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() > kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() > kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() > kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*end*/
for (int y = 0; y<image->height(); y++)
{
for (int x = 0; x<image->width(); x++)
{
color = QColor(image->pixel(x, y));
newcolor = QColor(newImage->pixel(x, y));
if (color.red() != newcolor.red())
{
r = 255;
}
else
{
r = 0;
}
if (color.green() != newcolor.green())
{
g = 255;
}
else
{
g = 0;
}
if (color.blue() != newcolor.blue())
{
b = 255;
}
else
{
b = 0;
}
newImage->setPixel(x, y, qRgb(r, g, b));
}
}
return newImage;
}
/*提取双线空心文字*/
QImage*MainWindow::SideIO(QImage* image)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
QImage* newImage1 = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
QImage* newImage2 = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[3][3] = {
{ 1,1,1 },
{ 1,1,1 },
{ 1,1,1 }
};
int sizeKernel = 3;
QColor color;
QColor newcolor;
int r = 0;
int g = 0;
int b = 0;
/*第一次腐蚀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 255;
int kg = 255;
int kb = 255;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() < kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() < kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() < kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*end*/
/*第二次腐蚀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 255;
int kg = 255;
int kb = 255;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(newImage->pixel(x + i, y + j));
while (color.red() < kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() < kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() < kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage1->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*end end*/
/*二次腐蚀相减*/
for (int y = 0; y<image->height(); y++)
{
for (int x = 0; x<image->width(); x++)
{
color = QColor(newImage->pixel(x, y));
newcolor = QColor(newImage1->pixel(x, y));
if (color.red() != newcolor.red())
{
r = 255;
}
else
{
r = 0;
}
if (color.green() != newcolor.green())
{
g = 255;
}
else
{
g = 0;
}
if (color.blue() != newcolor.blue())
{
b = 255;
}
else
{
b = 0;
}
newImage->setPixel(x, y, qRgb(r, g, b));
}
}
/*第一次膨胀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 0;
int kg = 0;
int kb = 0;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() > kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() > kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() > kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage1->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*end*/
/*第二次膨胀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 0;
int kg = 0;
int kb = 0;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(newImage1->pixel(x + i, y + j));
while (color.red() > kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() > kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() > kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage2->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*end*/
/*二次膨胀相减*/
for (int y = 0; y<image->height(); y++)
{
for (int x = 0; x<image->width(); x++)
{
color = QColor(newImage1->pixel(x, y));
newcolor = QColor(newImage2->pixel(x, y));
if (color.red() != newcolor.red())
{
r = 255;
}
else
{
r = 0;
}
if (color.green() != newcolor.green())
{
g = 255;
}
else
{
g = 0;
}
if (color.blue() != newcolor.blue())
{
b = 255;
}
else
{
b = 0;
}
newImage1->setPixel(x, y, qRgb(r, g, b));
}
}
/*复合提取内外边界*/
for (int y = 0; y<image->height(); y++)
{
for (int x = 0; x<image->width(); x++)
{
color = QColor(newImage1->pixel(x, y));
newcolor = QColor(newImage->pixel(x, y));
if (color.red() > newcolor.red())
{
r = color.red();
}
else
{
r = newcolor.red();
}
if (color.green() > newcolor.green())
{
g = color.green();
}
else
{
g = newcolor.green();
}
if (color.blue() > newcolor.blue())
{
b = color.blue();
}
else
{
b = newcolor.blue();
}
newImage->setPixel(x, y, qRgb(r, g, b));
}
}
delete newImage1;
delete newImage2;
return newImage;
}
4.腐蚀与膨胀的扩展应用
开运算:先腐蚀,后膨胀,可以进行消噪,选择性保留符合结构模板的几何特征
闭运算:先膨胀,后腐蚀,连接临近区域和填充细缝,通过选择结构模板可以让填充的内容具有一定几何特征
/*二值化的开运算*/
QImage* MainWindow::Opening(QImage* image)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
QImage* newImage1 = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[7][7] = {
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 } };
int sizeKernel = 7;
QColor color;
/*腐蚀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 255;
int kg = 255;
int kb = 255;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() < kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() < kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() < kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*膨胀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 0;
int kg = 0;
int kb = 0;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(newImage->pixel(x + i, y + j));
while (color.red() > kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() > kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() > kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage1->setPixel(x, y, qRgb(kr, kg, kb));
}
}
delete newImage;
return newImage1;
}
/*二值化的闭运算*/
QImage* MainWindow::Closing(QImage* image)
{
QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
QImage* newImage1 = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
int kernel[7][7] = {
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1 } };
int sizeKernel = 7;
QColor color;
/*膨胀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 0;
int kg = 0;
int kb = 0;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(image->pixel(x + i, y + j));
while (color.red() > kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() > kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() > kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage->setPixel(x, y, qRgb(kr, kg, kb));
}
}
/*腐蚀操作*/
for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
{
for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
{
int kr = 255;
int kg = 255;
int kb = 255;
for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
{
for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
{
color = QColor(newImage->pixel(x + i, y + j));
while (color.red() < kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kr = color.red();
}
while (color.green() < kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kg = color.green();
}
while (color.blue() < kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
{
kb = color.blue();
}
}
}
newImage1->setPixel(x, y, qRgb(kr, kg, kb));
}
}
delete newImage;
return newImage1;
}
5.参考资料:
数字图像处理——技术详解与Visual C++实践(左飞等著),写代码与写博客的时间相差两年,至于还参考其他的资料不,我已经忘记了,如若需要,我可以补上去