概念及推导
锐化处理的主要目的是突出灰度的过度部分。其中的拉普拉斯算子是通过二阶微分来实现对图像的锐化处理的。
拉普拉斯算子是一种最简单的各项同性的微分算子,各向同性的滤波器旋转不变,也就是说原图像旋转后进行滤波处理给出的结果于先对图像滤波之后再旋转的结果相同。
对于一个二维图像,拉普拉斯算子的定义为:
当我们要以离散形式描述上面公式时,先引出一阶、二阶微分的差分形式:
由上面的二阶差分可以得到Laplace算子的离散形式为:
此时的公式是使用下面的滤波模板来实现的,这显示一个以90°为增量进行旋转的各向同性结果。
在对原图进行拉普拉斯算子滤波后,可以将原图和拉普拉斯图像叠加在一起,通过这样的简单方法可以复原背景特征并保留拉普拉斯锐化处理的效果。次方式可由下面公式表示:
当使用模板中心像素大于0时,则常数c=1,如果模板中心像素小于0时,则常数c=-1。
代码与结果
void cv::Laplacian( InputArray _src,
OutputArray _dst,
int ddepth,
int ksize = 1,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT )
参数情况:
src —– 源图片
dst —– 与src相同大小和相同通道数的目标图像。
ddepth —– 目标图像的所需深度。
ksize —– 用于计算二阶导数滤波器的孔径大小,大小必须是正面和奇数。
scale —– 计算的拉普拉斯算子值的可选比例因子。
delta —– 在将结果存储在dst之前添加到结果中的可选增量值。
borderType —– 像素外推方法。
从此函数的源码可知,当ksize=1时,使用的拉普拉斯算子为:
而当ksize=3时,使用的拉普拉斯算子为:
ksize为其他数时将使用其他处理(我看不懂)。
使用配置:opencv4.3 + Visual_Studio2019 + Qt5.9.8
部分代码如下:
void QtMainWindow1::on_takelaplacian_clicked()
{
if (getImage == false) { return; }
Mat src, dst, gray_dst;
//初始ed_img为RGB或灰度图片
if (ed_img.type() == CV_8UC3)
{
cvtColor(ed_img, src, COLOR_RGB2BGR); //RGB转回BGR
}
else if (ed_img.type() == CV_8UC1)
{
ed_img.copyTo(src); //灰度图直接复制
}
GaussianBlur(src, dst, Size((ui->comboBox->currentIndex()+1)*2+1, \
(ui->comboBox->currentIndex() + 1) * 2 + 1), 0, 0); //高斯模糊
if (ed_img.type() == CV_8UC3)
{
cvtColor(dst, gray_dst, COLOR_BGR2GRAY);
cvtColor(dst, dst, COLOR_BGR2GRAY);
}
else if (ed_img.type() == CV_8UC1)
{
dst.copyTo(gray_dst);
}
//Laplacian算子是一种二阶导数算子,对噪声比较敏感,因此常需要配合高斯滤波一起使用。
//提取图像中的边缘信息
Laplacian(gray_dst, dst, CV_16S, ui->comboBox_2->currentIndex() * 2 + 1, 1, 0); //拉普拉斯变换
Mat abs_dst, abs_dsted;
Mat df;
convertScaleAbs(dst, abs_dst); //求绝对值
if (src.type() == CV_8UC3)
{
cvtColor(abs_dst, abs_dsted, COLOR_GRAY2BGR);
addWeighted(abs_dsted, -1, src, 1, 0, df);
}
else
{
addWeighted(abs_dst, -1, src, 1, 0, df);
}
namedWindow("叠加");
imshow("叠加", df);
namedWindow("原图");
imshow("原图", src);
//ui->statusBar->showMessage(QString::number(src_gray.type()));
qato_img = QImage((const unsigned char*)(abs_dst.data), abs_dst.cols, \
abs_dst.rows, abs_dst.step, QImage::Format_Indexed8);
qato_img = qato_img.scaled(qmai_img.size() * rnum, Qt::KeepAspectRatioByExpanding, \
Qt::SmoothTransformation);
ui->ImageArea->setPixmap(QPixmap::fromImage(qato_img));
}
上面为实现主要功能的代码
程序执行结果:
读入的原始图像:
QT界面显示边缘信息:
经过叠加的图像: