RenderMonkey在数字图像处理中的应用

 http://blog.csdn.net/xoyojank/article/details/1809424

 

大家可以拿来做<<数字图像处理>>这门课的实验, 呵呵, 这样就不用自己去实现框架了, 而且速度也快^_^
 
第一步, 这样来创建一个模板程序:
如图
我们先来认识一下左边有些什么:
base: 这是一个纹理(-_-图形学的术语…), 在这里我们就把它当成我们要处理的图像, 注意图像的长宽都是2的n次幂. 双击可以打对话框更换.
Stream Mapping: 不用管它, 保持默认值就好.
ScreenAlignedQuad: 其实只是一个正方形网格而已, 做为base纹理的骨架.( 又来了, 图形学-_-).暂且把它当成画板吧, 不用动它.
Single Pass: 进行绘制的地方
       ScreenAlignedQuad: 又一个…看见有个小剪头了没? 上面那个同名东的引用.
       Render State: 设置了一些渲染的参数, 不用管它.
       Vertex Shader: 里面写了怎么把ScreenAlignedQuad画到屏幕上, 这种支画板的活我们不关心.
       Pixel Shader像素级的处理, 这就是我们要发挥我们想像力的地方了!
       Texture0: 上面那幅图的引用.
       Stream Mapping: 也是上面的那个”不明物体”的引用.
 
下面让我们打开Pixel Shader看看都有什么:
是不是看着很像C语言啊? 我再来XX两句:
sampler2D  Texture0;
定义一个叫Texture0的图, 见上面的介绍. 注意保持名字的一致, 不然程序就找不到要处理的图像啦.
float4  ps_main( float2 texCoord : TEXCOORD0 ) : COLOR
所谓的float4就是由4个float组成的一个结构, 像这样:float4(x,y,z,w), 如果当成颜色值的话, 就是这样float4(r,g,b,a). 不要问我RGBA是啥, 图像处理时讲的……..
ps_main就是函数名, 括号里是参数
这里的texCoord就是我们要处理的当前像素的坐标值. 细心的可能看到它是float2格式的, 嗯, 没错, 实际上它就是一个float2(x,y) 型的结构. 不过有一点一定要注意: 这里的坐标单位不是基于像素的, 而是基于纹理坐标系的(别扔我…我解释一下就是了)
召唤一幅图:
图上的一格代表一个像素, 括号里面就是传统的像素坐标, 下面批示的就是纹理坐标.
聪明的你一眼就能看出来, 纹理坐标各轴上范围是[0,1], 相当于把原来的像素级的坐标除以了图像的宽度(高度).
 
来, 我们操刀上阵, 修改一下:
双击base换张彩图:
把PixelShader做如下修改:

sampler2D Texture0;
 
float4 ps_main(  float2 texCoord : TEXCOORD0 ) : COLOR
{
   // 当前像素在图像中的颜色值
   float4 color = tex2D( Texture0, texCoord );
   // 转换 RGB 为强度值
   float intensity = color.r * 0.299 + color.g * 0.587 + color.b * 0.184;
  
   return float4(intensity,intensity,intensity,1);
}

效果:
成黑白的了, 简单不?
(RGB到强度转换为什么那样转见课本. 你想偷懒的话直接(R+G+B)/3好了……)
 
 
 
空间域图像处理
 
在空间域图像处理中, 通常都是基于模板的算法. 即通过当前像素周围像素的颜色值来决定当前像素的颜色值. 下面举例说明:
 
1.       模糊
一目了然, 就是把当前像素的颜色用上下左右4个像素的颜色值的和的平均值来代替, 这样就模糊了….
那么, 怎么用RenderMonkey来实现呢?
从前边我们知道, 可以用texCoord.x, texCoord.y来表示像素的坐标, 然后用tex2D()函数来查找图像中指定坐标的颜色值. 不过要注意, 坐标的单位不是像素, 而是纹理坐票, 每个像素对应这里的图像宽度或高度的倒数. 所以, 我们先引入这两个值:
加入完毕后, 左边显示两个float值
 
好了, 这样一来, Color=(S1+S2+S3+S4)/4中的S1的颜色值就可以这样取到:
float4 colorS1 =  tex2D( Texture0, texCoord + float2(0,-fInverseViewportWidth) );
       为了计算方便, 我们把模板定义成一个滤波器数组:
const  float4 samples[4] = {
-1.0, 0.0, 0, 0.25,
1.0, 0.0, 0, 0.25,
0.0, .0, 0, 0.25,
0.0 -1.0, 0, 0.25
};
这样颜色的计算就可以通过一个for循环来玩成:
   for(int i = 0; i < 4; i++)
   {
       texColor += samples[i].w * tex2D(
          Texture0, TexCoord +
          float2(samples[i].x*fInverseViewportWidth, samples[i].y*fInverseViewportHeight)
       ); 
   }
效果:
以下是整个PixelShader的代码:
sampler Texture0;              // 源图像
float fInverseViewportWidth;     // 宽度的倒数
float fInverseViewportHeight;     // 高度的倒数
const  float4 samples[4] = {      // 滤波器
   -1, 0, 0, 0.25,
    1, 0, 0, 0.25,
    0, 1, 0, 0.25,
    0,-1, 0, 0.25
};
 
float4 ps_main( float2 TexCoord : TEXCOORD0
               ) : COLOR0
{   
   float4 texColor = (float4)0;    // 初始化颜色值
  
   for(int i = 0; i < 4; i++)
   {
       texColor += samples[i].w * tex2D(
          Texture0, TexCoord +
          float2(samples[i].x*fInverseViewportWidth, samples[i].y*fInverseViewportHeight)
       ); 
   }
  
   return texColor;
}
 
明白了上面的程序, 那么其它效果就很好做了.
 
2.       边缘检测和锐化
相似的, 边缘检测的滤波器可以这样写:
 
const  float4 samples[6] = {
-1.0, 1.0, 0, 1.0,
0.0, 1.0, 0, 2.0,
1.0, 1.0, 0, 1.0,
-1.0, -1.0, 0, -1.0,
0.0, -1.0, 0, -2.0,
1.0, -1.0, 0, -1.0
};
效果:
锐化滤波器:
const  float4 samples[5] = {
0.0, 0.0, 0, 11.0/3.0,
0.0, 1.0, 0, -2.0/3.0,
0.0, -1.0, 0, -2.0/3.0,
-1.0, 0.0, 0, -2.0/3.0,
1.0, 0.0, 0, -2.0/3.0
};
效果:
 
有了这些基础, 相信一般的图像处理算法都没什么问题了. 如果需要更多的数学函数的支持, 可以参照这里:
Intrinsic Functions (DirectX HLSL):
这篇文章不错, 同时也推荐一下:
Direct3D 提高篇 :HLSL 编程实现 PhotoShop 滤镜效果 :
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值