源地址:http://www.cnblogs.com/easymind223/archive/2012/07/03/2575277.html

 常用Photoshop的玩家都知道Unsharp Mask(USM)锐化,它是一种增强图像边缘的锐化算法,原理在此处,如果你想使用这个算法,强烈推荐看一下。本文进行一下简单的介绍,USM锐化一共分为三步,第一步生成原始图片src的模糊图片和高对比度图片,记为blur和contrast.第二,把src和blur作差,得到一张差分图片,记为diff,它就是下图的UnsharpMask。然后把src和contras按一定的比例相加,这个比例由diff控制,最终得到锐化图片。USM有一个缺点,锐化后最大和最小的像素值会超过原始图片,如下图红色虚线和白色实线所示。

 
代码如下:
void MyTreasureBox::UnsharpMask(const IplImage* src, IplImage* dst, float amount, float radius, uchar threshold, int contrast)
{
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);
}

其中用到一个调整图像对比度的函数

void MyTreasureBox::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++)
{
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
// 当增量大于-255且小于0时,直接用上面的公式计算图像像素各分量
//公式中,nRGB表示调整后的R、G、B分量,RGB表示原图R、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)
{
//当增量大于0且小于255时,则先按下面公式(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);
}
}
}
}

USM锐化之openCV实现,附赠调整对比度函数的更多相关文章

  1. OpenCV实现USM锐化与测试

    OpenCV实现USM锐化 [转]http://www.programdevelop.com/4964391/ USM (Unsharp masking) is a common operation ...

  2. C#调用GDI+1.1中的函数实现高斯模糊、USM锐化等经典效果。

    http://www.cnblogs.com/Imageshop/archive/2012/12/13/2815712.html 在GDI+1.1的版本中,MS加入不少新的特性,其中的特效类Effec ...

  3. 【Python】把文件名命名成canlendar.py竟然导致无法使用canlendar模块 附赠2020年月历

    这个bug困扰了我一阵,直到在 http://www.codingke.com/question/15489 找到了解决问题的钥匙,真是没想到居然是这个原因导致的. 下面是出错信息,可以看到只要目录下 ...

  4. 【SQL】靠谱的TRIM函数,附赠过程一枚

    SQL中有LTRIM和RTRIM这两个函数分别用于去除字符串的首.尾空格,缺乏常见的能同时去除首尾的TRIM函数,另外,这俩函数都只对[空格]有效,所以如果首尾是制表符.换行符等等[空白],它们是不处 ...

  5. SSE图像算法优化系列十六:经典USM锐化中的分支判断语句SSE实现的几种方法尝试。

    分支判断的语句一般来说是不太适合进行SSE优化的,因为他会破坏代码的并行性,但是也不是所有的都是这样的,在合适的场景中运用SSE还是能对分支预测进行一定的优化的,我们这里以某一个算法的部分代码为例进行 ...

  6. atitit  opencv apiattilax总结 约500个函数 .xlsx

    atitit  opencv apiattilax总结 约500个函数 .xlsx 1.1. CxCore中文参考手册 1 1.2. 机器学习中文参考手册  knn  svm  1 1.3. CvAu ...

  7. Python: PS 图像调整--对比度调整

    本文用 Python 实现 PS 里的图像调整–对比度调整.具体的算法原理如下: (1).nRGB = RGB + (RGB - Threshold) * Contrast / 255 公式中,nRG ...

  8. opencv:USM锐化

    USM:unsharp mask 对小的细节干扰小,对大的细节进行锐化 Mat dst; Mat blur_image; GaussianBlur(src, blur_image, Size(3, 3 ...

  9. hibernate内部测试题(附赠答案)

    一.选择题(共25题,每题2.5分,选择一项或多项,漏选错选不得分) 1.在Hibernate中,以下关于主键生成器说法错误的是( ). A.increment可以用于类型为long.short或by ...

随机推荐

  1. K&amp;R练习题6-1统计关键词出现的次数

    这道练习题训练了: 1.结构体数组 2.二分查找 3.指针操作 ---- 都不难.但非常基础,我认为非常好,做完了记到博客上来,题目见k&R,实现例如以下: /* * Practice of ...

  2. Swift - .plist文件数据的读取和存储

    每次在Xcode中新建一个iOS项目后,都会自己产生一个.plist文件,里面记录项目的一些配置信息.我们也可以自己创建.plist文件来进行数据的存储和读取. .plist文件其实就是一个XML格式 ...

  3. cocos2d-x环境的搭建之xcode-本人亲历成功搭建!

    cocos2d-x环境的搭建之xcode-本人亲历成功搭建! 写给大家的前言,在学习cocos2d-x的时候自己走了很多的弯路,也遇到了很多很多问题,不管是简单的还是困难的现在都慢慢的一步一步克服了, ...

  4. premake在Ubuntu和GCC环境下创建简单的C++工程

    由于premake基于lua脚本,为了方便编辑lua脚本,我在emacs24中利用package system安装了lua-mode. 然后创建config.lua文件,填入下面这段,主要来自:htt ...

  5. Android手势识别 Camera 预览界面上显示文字 布局注意事项(merge布局)

    通常在Surfaceview作为预览视频帧的载体,有时需在上面显示提示文字.曾经我弄的都好好的.今天忽然发现叠加的TextView不管咋弄都出不来文字了,跟Surfaceview一起放在FrameLa ...

  6. Java学习——何为JNDI

    曾记得在做机房收费系统的时候就接触到了API,由于它的功能非常强大,可是自己对它却不怎么了解.所以当时是又爱又怕.现在,一路走来才明确,事实上它就是一组接口.仅仅要我们去了解它就会发现.它事实上也没想 ...

  7. MFC类中获得其它类指针

    当用VC++的Application Wizard生成除了CDialog Basiced以外的应用程序时,将自动产生视图类.文档类.主帧窗口类.应用程序类等等.一般来说,程序的核心数据及操作在文档类中 ...

  8. C# 验证识别基类

    原文C# 验证识别基类 网上找了些代码 自己又改了下 先放出来了 处理简单的验证码足够了 001 using System; 002 using System.Collections.Generic; ...

  9. Windows8 Metro快捷键 | Win8迷

    Windows8 Metro快捷键 | Win8迷   Win + Q : 打开 搜索面板 Win + C : 打开屏幕右侧的Charms简化菜单 Win + 空格 : 切换输入语言和键盘布局  

  10. kernel hexdump分析 (2.0)

    有的时候print_hex_dump_bytes循环打印很多信息的时候(大于1K) 用UART串口打印的信息总是会有丢失,估计是printk缓冲区的问题把,具体原因不是太清楚 于是自己写了个比较笨的d ...