本文叙述了几种实现图像锐化的方式,包括拉普拉斯滤波,加权均值滤波,形态学梯度和顶帽底帽变换。本文的特色在于,大致证明了这几种方式可以实现图像锐化的原因。
更新记录
本文持续更新!如文中有错误,或你对本文有疑问或建议,欢迎留言或发邮件至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)
正文