1. 图像锐化和增强
图像锐化是一种突出和加强图像中景物的边缘和轮廓的技术,使图像变得更加清晰。它通过增强图像的高频分量来减少图像中的模糊,增强图像细节边缘和轮廓,增强灰度反差,便于后期对目标的识别和处理。
图像增强是改善图像质量的技术,包括图像锐化、去噪、对比度增强、色彩增强等。图像锐化是图像增强中的一种重要技术。
图像锐化和图像增强的区别在于,图像锐化侧重于突出图像中的细节,而图像增强则可以包括更广泛的操作,以满足不同的应用需求。
以下简单总结了图像锐化和图像增强之间的区别:
特征 | 图像锐化 | 图像增强 |
---|---|---|
目的 | 增强图像的边缘和细节 | 改善图像的整体质量 |
方法 | 增强图像的高频分量 | 可以包括锐化、去噪、对比度增强、色彩调整等多种操作 |
应用 | 适用于需要突出图像细节的场景,例如医学图像处理、遥感图像分析等 | 适用于需要改善图像质量的各种场景,例如照片编辑、视频处理等 |
2. 图像锐化方法
图像锐化的方法主要有以下两种:
-
空间域方法:在空间域上直接对图像进行处理。常用的空间域锐化方法包括: a. 锐化滤波器:利用锐化滤波器对图像进行卷积运算,增强图像的边缘和细节。常用的锐化滤波器包括 Prewitt 算子、Roberts 算子、Laplace 算子等。
b. USM 锐化:USM(Unsharpen Mask)锐化是一种常用的锐化方法,它先对图像进行高斯滤波,然后用原图像减去高斯滤波后的图像,再将结果乘以一个系数,最后将结果加到原图像中。
-
频域方法:将图像变换到频域,然后对高频分量进行增强,再将图像变换回空间域。常用的频域锐化方法包括高通滤波等。
3. 拉普拉斯锐化和 USM 锐化
3.1 拉普拉斯锐化
在该系列的第八篇和第十篇文章中,都曾经介绍过拉普拉斯算子,它是二阶导数的边缘算子。
之前我们曾介绍过二阶导数的 Laplace 算子可以通过差分 近似来简化,其公式为:
<math xmlns="http://www.w3.org/1998/Math/MathML"> ∇ 2 f ( x , y ) = f ( x + 1 , y ) + f ( x − 1 , y ) + f ( x , y + 1 ) + f ( x , y − 1 ) − 4 f ( x , y ) \nabla^2f(x,y)= f(x+1,y)+f(x-1,y)+ f(x,y+1)+f(x,y-1)-4f(x,y) </math>∇2f(x,y)= f(x+1,y)+f(x−1,y)+f(x,y+1)+f(x,y−1)−4f(x,y)
它的 4 邻域卷积核:
它的 8 邻域卷积核:
拉普拉斯锐化通过增强图像中的二阶导数来突出边缘。
拉普拉斯锐化的基本原理:当邻域的中心像素灰度低于它所在邻域内的其他像素的平均灰度时,此中心像素的灰度应该进一步降低;当高于时进一步提高中心像素的灰度,从而实现图像锐化处理。
拉普拉斯的锐化公式: <math xmlns="http://www.w3.org/1998/Math/MathML"> g ( x , y ) = f ( x , y ) + c [ ∇ 2 f ( x , y ) ] g(x,y)=f(x,y)+c[\nabla^2f(x,y)] </math>g(x,y)=f(x,y)+c[∇2f(x,y)]
其中,f(x,y) 表示原图,g(x,y) 表示锐化后的图像。
对于 4 邻域卷积核:
<math xmlns="http://www.w3.org/1998/Math/MathML"> g ( x , y ) = f ( x , y ) − ∇ 2 f ( x , y ) = 5 f ( x , y ) − f ( x + 1 , y ) − f ( x − 1 , y ) − f ( x , y + 1 ) − f ( x , y − 1 ) g(x,y)=f(x,y) - \nabla^2f(x,y)= 5f(x,y)-f(x+1,y)-f(x-1,y)-f(x,y+1)-f(x,y-1) </math>g(x,y)=f(x,y)− ∇2f(x,y)= 5f(x,y)−f(x+1,y)−f(x−1,y)−f(x,y+1)−f(x,y−1)
用模板表示如下:
<math xmlns="http://www.w3.org/1998/Math/MathML"> [ 0 − 1 0 − 1 5 − 1 0 − 1 0 ] \begin{bmatrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1 & 0 \end{bmatrix} </math> 0−10−15−10−10
对于 8 邻域卷积核:
<math xmlns="http://www.w3.org/1998/Math/MathML"> g ( x , y ) = f ( x , y ) − ∇ 2 f ( x , y ) = 9 f ( x , y ) − f ( x − 1 , y − 1 ) − f ( x , y − 1 ) − f ( x + 1 , y − 1 ) − f ( x − 1 , y ) − f ( x + 1 , y ) − f ( x − 1 , y + 1 ) − f ( x , y + 1 ) − f ( x + 1 , y + 1 ) g(x,y)=f(x,y) - \nabla^2f(x,y) = 9f(x,y)- f(x-1,y-1)-f(x,y-1)-f(x+1,y-1)-f(x-1,y)-f(x+1,y)-f(x-1,y+1)-f(x,y+1)-f(x+1,y+1) </math>g(x,y)=f(x,y)− ∇2f(x,y)= 9f(x,y)−f(x−1,y−1)−f(x,y−1)−f(x+1,y−1)−f(x−1,y)−f(x+1,y)−f(x−1,y+1)−f(x,y+1)−f(x+1,y+1)
用模板表示如下:
<math xmlns="http://www.w3.org/1998/Math/MathML"> [ − 1 − 1 − 1 − 1 9 − 1 − 1 − 1 − 1 ] \begin{bmatrix} -1 & -1 & -1 \\ -1 & 9 & -1 \\ -1 & -1 & -1 \end{bmatrix} </math> −1−1−1−19−1−1−1−1
拉普拉斯锐化可以有效地增强图像的边缘和细节,但它也会放大图像中的噪声。因此,在锐化图像之前,通常需要先进行去噪处理。
下面的例子,通过 8 邻域拉普拉斯算子对图像进行锐化
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main() {
Mat src = imread(".../girl.jpg");
imshow("src", src);
int height = src.rows;
int width = src.cols;
int border = 1;
Mat dst(height, width, CV_8UC3);
for (int i = border; i < height - border; i++) {
for (int j = border; j < width - border; j++) {
for (int k = 0; k < 3; k++) {
int sum = 9 * src.at<Vec3b>(i, j)[k] - src.at<Vec3b>(i - 1, j - 1)[k] - src.at<Vec3b>(i - 1, j)[k]
- src.at<Vec3b>(i - 1, j + 1)[k] - src.at<Vec3b>(i, j - 1)[k] - src.at<Vec3b>(i, j + 1)[k]
- src.at<Vec3b>(i + 1, j - 1)[k] - src.at<Vec3b>(i + 1, j)[k] - src.at<Vec3b>(i + 1, j + 1)[k];
dst.at<Vec3b>(i, j)[k] = saturate_cast<uchar>(sum);
}
}
}
imshow("laplaceSharp", dst);
waitKey(0);
return 0;
}
当然,上述代码中拉普拉斯锐化的实现也可以用 filter2D()
函数实现。
3.2 USM 锐化
USM 锐化(Unsharp Mask Sharpening),它通过增强图像的边缘和细节来使图像变得更加清晰。
USM 锐化的工作原理是:
- 对原图像进行高斯模糊处理,得到模糊后的图像。
- 将原图像减去模糊后的图像,得到残差图像。
- 将残差图像乘以一个锐化因子 ,得到增强后的残差图像。
- 将增强后的残差图像与原图像进行叠加,得到锐化后的图像。
USM 锐化具有以下特点:
- 可以有效地增强图像的边缘和细节。
- 具有较强的控制性,用户可以通过调整锐化因子、半径和阈值等参数来控制锐化效果。
- 可能会放大图像中的噪声。
USM 锐化通常具有以下三个参数:
- 锐化因子(Amount):控制锐化效果的强度。值越大,锐化效果越明显。
- 阈值(Threshold):控制哪些像素会被锐化。值越大,只有灰度值差异较大的像素才会被锐化,可以减少噪声的影响。
- 半径(Radius):控制锐化范围的大小。值越大,锐化范围越大,边缘越模糊。
下面的例子,实现了一个 USM 锐化。
cpp
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
void unsharpMask(const Mat& src, Mat& dst, int radius, int threshold, int amount) {
int height = src.rows;
int width = src.cols;
GaussianBlur(src, dst, cv::Size(radius, radius), 2, 2);
for (int h = 0; h < height; ++h) {
for (int w = 0; w < width; ++w) {
int b = src.at<Vec3b>(h, w)[0] - dst.at<Vec3b>(h, w)[0];
int g = src.at<Vec3b>(h, w)[1] - dst.at<Vec3b>(h, w)[1];
int r = src.at<Vec3b>(h, w)[2] - dst.at<Vec3b>(h, w)[2];
if (abs(b) > threshold) {
b = src.at<Vec3b>(h, w)[0] + amount * b / 100;
dst.at<Vec3b>(h, w)[0] = saturate_cast<uchar>(b);
}
if (abs(g) > threshold) {
g = src.at<Vec3b>(h, w)[1] + amount * g / 100;
dst.at<Vec3b>(h, w)[1] = saturate_cast<uchar>(g);
}
if (abs(r) > threshold) {
r = src.at<Vec3b>(h, w)[2] + amount * r / 100;
dst.at<Vec3b>(h, w)[2] = saturate_cast<uchar>(r);
}
}
}
}
int main() {
Mat src = imread(".../girl.jpg");
imshow("src", src);
Mat dst = Mat(src.size(), src.type());
unsharpMask(src,dst, 181, 0, 90);
imshow("usm", dst);
waitKey(0);
return 0;
}
4. 总结
本文简单介绍了图像锐化和增强的含义以及他们之间的区别。
详细介绍了2种锐化方式,拉普拉斯锐化通常适用于需要快速锐化图像的场景,例如对模糊的图像进行简单的锐化处理。USM 锐化通常适用于需要对锐化效果进行精细控制的场景,例如对照片进行锐化处理。当然,也可以将两种方法结合使用,例如先使用拉普拉斯锐化进行快速锐化,然后再使用 USM 锐化进行精细调整。