本文叙述了几种实现图像锐化的方式,包括拉普拉斯滤波,加权均值滤波,形态学梯度和顶帽底帽变换。本文的特色在于,大致证明了这几种方式可以实现图像锐化的原因。
更新记录
本文持续更新!如文中有错误,或你对本文有疑问或建议,欢迎留言或发邮件至quarrying#qq.com!
2016年01月08日,发布博文。
2016年04月28日,更新博文。
参考
J.S. Lee, Digital image enhancement and noise filtering by use of local statistics, IEEE Transactions on Pattern Analysis and Machine Intelligence, 2(2):165-168, 1980.
https://en.wikipedia.org/wiki/Unsharp_masking
https://en.wikipedia.org/wiki/Erosion_(morphology)
https://en.wikipedia.org/wiki/Dilation_(morphology)
https://en.wikipedia.org/wiki/Opening_(morphology)
https://en.wikipedia.org/wiki/Closing_(morphology)
https://en.wikipedia.org/wiki/Top-hat_transform
https://en.wikipedia.org/wiki/Mathematical_morphology
https://en.wikipedia.org/wiki/Morphological_Gradient
相关代码
拉普拉斯滤波和加权均值滤波(主要是高斯滤波)实现图像锐化的代码比较常见,于是只给出如下代码。
代码一,形态学梯度实现图像锐化
#include <cv.h>
#include <highgui.h>
// 除了kcvMorphologicalSharpenLike
// factor为正值时,会有锐化效果,为负值时,会有模糊效果。
void kcvMorphologicalSharpenInt(const IplImage* src, IplImage* dst,
double factor, IplConvKernel* element)
{
cvErode(src, dst, element, 1);
cvSub(src, dst, dst);
cvAddWeighted(src, 1, dst, factor, 0, dst);
}
void kcvMorphologicalSharpenExt(const IplImage* src, IplImage* dst,
double factor, IplConvKernel* element)
{
cvDilate(src, dst, element, 1);
cvSub(dst, src, dst);
cvAddWeighted(src, 1, dst, -factor, 0, dst);
}
void kcvMorphologicalSharpen(const IplImage* src, IplImage* dst,
double factor1, double factor2, IplConvKernel* element)
{
IplImage* tmp = cvCreateImage(cvGetSize(src), 8, src->nChannels);
kcvMorphologicalSharpenInt(src, tmp, factor1, element);
cvErode(src, dst, element, 1);
cvSub(src, dst, dst);
cvAddWeighted(tmp, 1, dst, factor2, 0, dst);
cvReleaseImage(&tmp);
}
void kcvMorphologicalSharpenLike(const IplImage* src, IplImage* dst,
double factor, IplConvKernel* element)
{
IplImage* tmp = cvCreateImage(cvGetSize(src), 8, src->nChannels);
cvDilate(src, tmp, element, 1);
cvErode(src, dst, element, 1);
cvSub(tmp, dst, dst);
cvAddWeighted(src, 1, dst, factor, 0, dst);
cvReleaseImage(&tmp);
}
int main()
{
IplImage* src = cvLoadImage("lena.jpg", 1);
IplImage* dst = cvCloneImage(src);
IplConvKernel* element = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT, 0);
int64 t1, t2;
cvShowImage("src", src);
t1 = cvGetTickCount();
kcvMorphologicalSharpenInt(src, dst, 1, element);
t2 = cvGetTickCount();
printf("kcvMorphologicalSharpenInt %f ms
", (t2 - t1) / (1000 * cvGetTickFrequency()));
cvShowImage("kcvMorphologicalSharpenInt", dst);
t1 = cvGetTickCount();
kcvMorphologicalSharpenExt(src, dst, 1, element);
t2 = cvGetTickCount();
printf("kcvMorphologicalSharpenExt %f ms
", (t2 - t1) / (1000 * cvGetTickFrequency()));
cvShowImage("kcvMorphologicalSharpenExt", dst);
t1 = cvGetTickCount();
kcvMorphologicalSharpen(src, dst, 1, 1, element);
t2 = cvGetTickCount();
printf("kcvMorphologicalSharpen %f ms
", (t2 - t1) / (1000 * cvGetTickFrequency()));
cvShowImage("kcvMorphologicalSharpen", dst);
t1 = cvGetTickCount();
kcvMorphologicalSharpenLike(src, dst, 1, element);
t2 = cvGetTickCount();
printf("kcvMorphologicalSharpenLike %f ms
", (t2 - t1) / (1000 * cvGetTickFrequency()));
cvShowImage("kcvMorphologicalSharpenLike", dst);
t1 = cvGetTickCount();
kcvMorphologicalSharpenLike(src, dst, -1, element);
t2 = cvGetTickCount();
printf("kcvMorphologicalSharpenLike 2 %f ms
", (t2 - t1) / (1000 * cvGetTickFrequency()));
cvShowImage("kcvMorphologicalSharpenLike 2", dst);
cvWaitKey(0);
cvDestroyAllWindows();
cvReleaseImage(&src);
cvReleaseImage(&dst);
return 0;
}
代码二,顶帽底帽变换实现图像锐化
close all
I = imread('lena.jpg');
imshow(I)
se = strel('disk', 3);
topHat = imtophat(I, se);
botHat = imbothat(I, se);
J = imadd(I, 1.5 * topHat);
figure, imshow(J);
J = imsubtract(I, 1.5 * botHat);
figure, imshow(J);
J = imsubtract(imadd(I, topHat), botHat);
figure, imshow(J)
J = imadd(imadd(I, topHat), botHat);
figure, imshow(J)
J = imsubtract(imsubtract(I, topHat), botHat);
figure, imshow(J)
正文
