图像锐化,是使图像边缘更加清晰的一种图像处理方法,说白了就是让图像的边缘看起来更加清晰明了。其原理主要就是利用图像的高频分量来实现的,将原图像的高频分量提取出来,再和原图像按一定规则叠加起来,最终得到的图像就是锐化后的图像。提取高频分量可以有如下两种方式:
数字图像处理中关于图像增强算法有两种常用的技术:非锐化掩蔽和高提升滤波
图中g表示锐化后的图像,f表示原图像,k表示锐化系数,m为高频分量图像。
其原理如上面所说,步骤如下:
传统的锐化算法通过获取高频分量然后与原图像叠加做锐化,这种方法虽然效果很明显,但是容易出现噪声增强的现象,而且很容易在图像纹理的边缘处产生明亮的伪边缘,如下图所示:
可以看出,在lena的帽子处和头发边缘均有一定的白色伪边缘产生,而且锐化后的图像还出现了许多噪声,使得图像的整体锐化效果变得很差。
USM锐化算法得到的图像容易出现噪声及伪边缘,那么,如果能够做到只针对图像中的边缘部分做锐化处理,是不是就可以在保证锐化效果的前提下最大程度的保留原图中的非噪声信息呢?要实现这个功能,我们需要设置一个阈值,将原图像与滤波后得到的高频分量图像做差值,再与阈值比较,即可得到想要的效果。具体步骤如下:
经过以上几步简单操作就可以得到优化后的USM锐化图像了,改良后的USM锐化的图像效果如下图所示:
上图最右边的图像即为优化后的USM锐化图像,对比未优化的USM锐化图像可以看出,在提高锐化效果的基础上尽可能的降低了噪声和伪边缘现象。
本文中实现的锐化算法使用OpenCV4.1.0版本,VS2017环境,实验代码如下:
// USM_SharpenFilter.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
#define SharpenFactor 1 //锐化系数
#define SharpenThs 30 //锐化阈值
void ImproveUSM(Mat src, Mat BlurImg, int Threshold, float Factor)
{
Mat DiffMask, dst;
DiffMask = Mat::zeros(src.rows, src.cols, src.type());
if (src.channels() == 1) //灰度单通道
{
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
int Value_diff = abs(src.at<uchar>(i, j) - BlurImg.at<uchar>(i, j));
if (Value_diff < Threshold) //小于阈值说明非边缘,不需要锐化
DiffMask.at<uchar>(i, j) = 1;
else
DiffMask.at<uchar>(i, j) = 0;
}
}
}
else if (src.channels() == 3) //三通道BGR
{
int Value_diff[3] = {
0 };
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
for (int k = 0; k < 3; k++)
{
Value_diff[k] = abs(src.at<Vec3b>(i, j)[k] - BlurImg.at<Vec3b>(i, j)[k]);
if (Value_diff[k] < Threshold) //小于阈值说明非边缘,不需要锐化
DiffMask.at<Vec3b>(i, j)[k] = 1;
else
DiffMask.at<uchar>(i, j) = 0;
}
}
}
}
addWeighted(src, 1 + Factor, BlurImg, -Factor, 0, dst); //将两幅图按权重系数融合,dst = src + Factor(src - BlurImg)
src.copyTo(dst, DiffMask); //将src中DiffMask对应的非0部分复制到dst中
imshow("ImproveUSM", dst);
}
int main()
{
int Ths = SharpenThs;
float Fac = SharpenFactor;
Mat src = imread(".//lena.jpg");
if (src.empty())
{
printf("could not load image...\n");
return -1;
}
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
Mat blur_img, USMsharpen_img, sharpen_img, sharpen_kernel;
sharpen_kernel = (Mat_<float>(3, 3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
filter2D(src, sharpen_img, CV_32F, sharpen_kernel);
convertScaleAbs(sharpen_img, sharpen_img);
imshow("sharpen", sharpen_img);
GaussianBlur(src, blur_img, Size(9, 9), 0, 0);
addWeighted(src, 1 + Fac, blur_img, -Fac, 0, USMsharpen_img);
imshow("USMsharpen", USMsharpen_img);
//使用自己写的改进版本的USM锐化
ImproveUSM(src, blur_img, Ths, Fac);
waitKey(0);
return 0;
}