OpenCV实现USM锐化与测试
OpenCV实现USM锐化
【转】http://www.programdevelop.com/4964391/
USM (Unsharp masking) is a common operation of image processing. From the Internet search a bit, there are basically three different ways. Only 2 lines of code, there are hundreds of the most complex line. These three methods below summary records for later use.
最简单的方法:
cv::GaussianBlur(frame, image, cv::Size(0, 0), 3); cv::addWeighted(frame, 1.5, image, -0.5, 0, image);
Followed by the simple method, derived from "only want to hear a good story" programdevelop.com blog.
常用photoshop的一般都会用到usm (unsharp mask)锐化,它的原理非常简单,使用opencv进行实现只需要4行代码
最终实现效果如下:
double sigma = 3; int threshold = 0; float amount = 1; imgsrc = imread("thankyou.jpg"); GaussianBlur(imgsrc, imgblurred, cv::size(0,0), sigma, sigma) #对于图形size(0,0)效果最好。why?看高斯滤波原理
#GaussianBlur(imgsrc, imgblurred, cv::size(5,5), sigma, sigma)
#GaussianBlur(imgsrc, imgblurred, size(), sigma, sigma) lowcontrastmask = abs(imgsrc-imgblurred)<threshold; imgdst = imgsrc*(1+amount)+imgblurred*(-amount); imgsrc.copyTo(imgdst, lowcontrastmask); imshow("SUM", imgdst);
GaussianBlur(imgsrc, imgblurred, cv::size(5,5), sigma, sigma)的USM效果
GaussianBlur(imgsrc, imgblurred, cv::size(0,0), sigma, sigma)的USM效果
==================================================
原图像 锐化结果
使用photoshop进行处理的效果如下:
参数:数量131% 半径2.2像素 阈值0色阶
基本上效果还是类似的,通过调节参数可以达到基本一致的效果~~~哈哈
一个简单的usm算法~~~研究了好多天~~~~
不过看到满意的结果还是挺有成就感的
==========原文来自http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E7%89%9B/4663.shtml====
最复杂的方法:
void UnsharpMask(const IplImage* src, IplImage* dst, float amount=80, float radius=5, uchar threshold=0, intcontrast=100) { if(!src)return ; int imagewidth = src->width; int imageheight = src->height; int channel = src->nChannels; IplImage* blurimage = cvCreateImage(cvSize(imagewidth,imageheight), src->depth, channel); IplImage* DiffImage = cvCreateImage(cvSize(imagewidth,imageheight), 8, channel); // IplImage* highcontrast = cvCreateImage(cvSize(imagewidth,imageheight), 8, channel); AdjustContrast(src, highcontrast, contrast); // cvSmooth(src, blurimage, CV_GAUSSIAN, radius); // for (int y=0; y<imageheight; y++) { for (int x=0; x<imagewidth; x++) { CvScalar ori = cvGet2D(src, y, x); CvScalar blur = cvGet2D(blurimage, y, x); CvScalar val; val.val[0] = abs(ori.val[0] - blur.val[0]); val.val[1] = abs(ori.val[1] - blur.val[1]); val.val[2] = abs(ori.val[2] - blur.val[2]); cvSet2D(DiffImage, y, x, val); } } // for (int y=0; y<imageheight; y++) { for (int x=0; x<imagewidth; x++) { CvScalar hc = cvGet2D(highcontrast, y, x); CvScalar diff = cvGet2D(DiffImage, y, x); CvScalar ori = cvGet2D(src, y, x); CvScalar val; for (int k=0; k<channel; k++) { if (diff.val[k] > threshold) { // = *(1-r) + *r val.val[k] = ori.val[k] *(100-amount) + hc.val[k] *amount; val.val[k] /= 100; } else { val.val[k] = ori.val[k]; } } cvSet2D(dst, y, x, val); } } cvReleaseImage(&blurimage); cvReleaseImage(&DiffImage); } //?contrast[-255,255] void AdjustContrast(const IplImage* src, IplImage* dst, int contrast) { if (!src)return ; int imagewidth = src->width; int imageheight = src->height; int channel = src->nChannels; // CvScalar mean = {0,0,0,0}; for (int y=0; y<imageheight; y++) { for (int x=0; x<imagewidth; x++) { for (int k=0; k<channel; k++) { CvScalar ori = cvGet2D(src, y, x); for (int k=0; k<channel; k++) { mean.val[k] += ori.val[k]; } } } } for (int k=0; k<channel; k++) { mean.val[k] /= imagewidth * imageheight; } // if (contrast <= -255) { //-255???RGB??1?? for (int y=0; y<imageheight; y++) { for (int x=0; x<imagewidth; x++) { cvSet2D(dst, y, x, mean); } } } else if(contrast > -255 && contrast <= 0) { //(1)nRGB = RGB + (RGB - Threshold) * Contrast / 255 // -2550? //?nRGBR?G?B?RGBR?G?B?Threshold?Contrast? for (int y=0; y<imageheight; y++) { for (int x=0; x<imagewidth; x++) { CvScalar nRGB; CvScalar ori = cvGet2D(src, y, x); for (int k=0; k<channel; k++) { nRGB.val[k] = ori.val[k] + (ori.val[k] - mean.val[k]) *contrast /255; } cvSet2D(dst, y, x, nRGB); } } } else if(contrast >0 && contrast <255) { //0255?(2)?(1)? //(2)?nContrast = 255 * 255 / (255 - Contrast) - 255 //nContrast?Contrast? CvScalar nRGB; int nContrast = 255 *255 /(255 - contrast) - 255; for (int y=0; y<imageheight; y++) { for (int x=0; x<imagewidth; x++) { CvScalar ori = cvGet2D(src, y, x); for (int k=0; k<channel; k++) { nRGB.val[k] = ori.val[k] + (ori.val[k] - mean.val[k]) *nContrast /255; } cvSet2D(dst, y, x, nRGB); } } } else { // 255????8? //?????? for (int y=0; y<imageheight; y++) { for (int x=0; x<imagewidth; x++) { CvScalar rgb; CvScalar ori = cvGet2D(src, y, x); for (int k=0; k<channel; k++) { if (ori.val[k] > mean.val[k]) { rgb.val[k] = 255; } else { rgb.val[k] = 0; } } cvSet2D(dst, y, x, rgb); } } } }