C++ HLSL实现简单的图像处理功能

由于对于dxva2解码得到的数据不宜copy回内存给CPU处理,所以最好的办法是在GPU上直接进行处理。D3D的像素着色器能够对像素直接进行操作,实现点运算极其简单方便,简单的卷积运算效果也非常好。但D3D9的限制也很多,对于过于复杂的图像处理则显得有些不能胜任。

1.点运算

点运算用HLSL非常容易实现,几乎是公式怎么写,代码就怎么写。以RGB转灰度图显示为例:

texture Tex0 ;
int iFlag = 0 ;
float aValue= 0.0 ;
float bValue= 0.0 ;
sampler2D YTex =
sampler_state
{
  Texture = <Tex0> ;
  MipFilter = LINEAR ;
  MinFilter = LINEAR ;
  MagFilter = LINEAR ;

  AddressU = CLAMP ;
  AddressV = CLAMP ;
};
struct PS_INPUT
{
  float2 uvCoords0 : TEXCOORD0 ;
};
float4 Main( PS_INPUT input ) : COLOR0
{
  float4 yuvColor ;
  //rgb to gray 不知道是不是这么显示的,姑且这么认为
  float gray = tex2D( YTex, input.uvCoords0 ).r * 0.299 + tex2D( YTex, input.uvCoords0 ).g * 0.587 + tex2D( YTex, input.uvCoords0 ).b * 0.114 ;
  float s = 0 ;
  if(iFlag == 0)
  {
    s = aValue * gray + bValue/255 ;
  }
  else if(iFlag == 1)
  {
    s = aValue * log(1+gray) ;
  }
  else if(iFlag == 2)
  {
    s = aValue * pow(abs(gray),bValue) ;
  }
  yuvColor.r = s ;
  yuvColor.g = s ;
  yuvColor.b = s ;
  yuvColor.a = 1.0 ;
  return yuvColor ;
}

点运算如此简单是因为GPU是并行运算的,我个人认为可以看成是每一个像素点(BGRA)对应一个线程,这大概就是OpenCL中所谓的数据并行。这是一个非常简单的程序,指令数少,程序结构也很简单,shader 的版本用2.0就可以轻松编过。

2.卷积运算举例

指令数较多的情况2.0版本的shader就搞不定了,上3.0版本可以做一些简单的卷积运算。以中值滤波为例:

texture Tex0 ;
matrix WorldMatrix;
matrix ViewMatrix;
matrix ProjMatrix;
sampler2D YTex =
sampler_state
{
  Texture = <Tex0> ;
  MipFilter = LINEAR ;
  MinFilter = LINEAR ;
  MagFilter = LINEAR ;
  AddressU = CLAMP ;
  AddressV = CLAMP ;
};
struct VS_INPUT
 {
  float4 pos  : POSITION;
  float4 color : COLOR0;
  float2 tex  : TEXCOORD0;
 };
//
struct VS_OUTPUT
 {
  float4 pos   : POSITION;
  float4 color  : COLOR0;
  float2 tex   : TEXCOORD0;
 };
float2 g_v4ScreenSize;
int ksize = 1 ;
float fLeft = -1.0f ;
float fTop = -1.0f ;
float fRight = -1.0f ;
float fBottom = -1.0f ;
//--------------------------------- BurTechnique --------------------------------------
VS_OUTPUT MainVS_Screen( VS_INPUT In )
{
  VS_OUTPUT Out = ( VS_OUTPUT )0;
  float4x4 matWorldView = mul(WorldMatrix,ViewMatrix);
  float4x4 matProject = mul(matWorldView,ProjMatrix);
  Out.pos = mul(In.pos,matProject);
  Out.tex = In.tex;
  Out.color = In.color;
  return Out;
}
float4 MainPS_Screen( VS_INPUT In ) : COLOR0
{
  float4 outColor = tex2D( YTex, In.tex ).rgba ;
  if(ksize <= 1 || ksize%2 == 0)
  {
    return outColor ;
  }
  if( ksize > 11 || ksize < 3)
  {
    return outColor ;
  }
  if(!(In.tex.x < fRight && In.tex.y < fBottom && In.tex.x > fLeft && In.tex.y > fTop))
  {
    return outColor ;
  }
  // 纹理大小
  float2 TexSize = float2( g_v4ScreenSize.x , g_v4ScreenSize.y );
  float x_off = 1.0f / TexSize.x;
  float y_off = 1.0f / TexSize.y;
  float2 fX0Y0 = In.tex - float2(x_off * ksize/2, y_off*ksize/2) ;
  float3 sum = {0.0f, 0.0f, 0.0f} ;
  if(ksize >= 3)
  {
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*2)).rgb;
  }
  if(ksize >= 5)
  {
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*4)).rgb;
  }
  if(ksize >= 7)
  {
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*6)).rgb;
  }
  if(ksize >= 9)
  {
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*8)).rgb;
  }
  if(ksize >= 11)
  {
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 9, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*0)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*1)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*2)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*3)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*4)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*5)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*6)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*7)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*8)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 10, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*9)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 0, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 1, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 2, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 3, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 4, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 5, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 6, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 7, y_off*10)).rgb;
    sum += tex2D( YTex , fX0Y0 + float2(x_off * 8, y_off*10)).rgb;
  }
  outColor = float4(sum/(ksize*ksize),1.0f);
  return outColor ;
}
//--------------------------- 技术---------------------------
technique BurTechnique
{
  pass P0
  {
    LightEnable[0] = false;
    VertexShader = compile vs_3_0 MainVS_Screen();
    PixelShader = compile ps_3_0 MainPS_Screen();
  }
}

由于3.0版本的shader似乎不允许pixel shader单独出现,所以我从点运算用像素着色器实现改为用特效来实现。HLSL语法中有if语句,也有for语句,可是这个程序却不厌其烦的把所有的都给列出来来,而没有使用for循环。这是因为在实际使用中发现有一些限制,比如if语句的if(A>B),A与B中必须有一个是常量,就像上面见到的那种形式;for循环中间的判断也是如此,只是在第二层j循环中可以是第一层循环的i,即不可以

 for(int i=0;i<ksize;i++)
{
  for(int j=0;j<ksize1;j++)
    {
  ..........
    }
}

以上代码的ksize与ksize1都必须为常数,例外的情况是ksize1可以为第一层循环的 i 。这个问题不知道后续版本的shader有没有,反正我当前使用的版本有。

另外有一个需要注意的地方是指令数,2.0版本的shader支持的指令数相当少,3.0版本则要多好多,我最长写到了400多条快500条时才导致编译失败。 还有一个需要提醒的是3.0版本的shader只支持D3D 9.0C以后的。如果要求做更为复杂的图像处理,可以的话建议上D3D11,compute shader虽然我没用过,但从介绍来说,应该可以处理一些更为复杂的图像处理。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

(0)

相关推荐

  • VC++中图像处理类CBitmap的用法

    VC++中图像处理类CBitmap的用法 class CBitmap : public CGdiObject { DECLARE_DYNAMIC(CBitmap) public: static CBitmap* PASCAL FromHandle(HBITMAP hBitmap); // Constructors CBitmap(); BOOL LoadBitmap(LPCTSTR lpszResourceName); BOOL LoadBitmap(UINT nIDResource); BOO

  • c++图像处理:24位真彩图颜色变换实例

    实例如下: #include<iostream> #include<Windows.h> using namespace std; bool isred(BYTE r,BYTE g,byte b){ if(r>g&&r>b) return true; else return false; } void red2green(BYTE& r,BYTE& g,BYTE& b){ BYTE tmp=r; r=g; g=tmp; } int

  • C++ HLSL实现简单的图像处理功能

    由于对于dxva2解码得到的数据不宜copy回内存给CPU处理,所以最好的办法是在GPU上直接进行处理.D3D的像素着色器能够对像素直接进行操作,实现点运算极其简单方便,简单的卷积运算效果也非常好.但D3D9的限制也很多,对于过于复杂的图像处理则显得有些不能胜任. 1.点运算 点运算用HLSL非常容易实现,几乎是公式怎么写,代码就怎么写.以RGB转灰度图显示为例: texture Tex0 ; int iFlag = 0 ; float aValue= 0.0 ; float bValue= 0

  • Angularjs制作简单的路由功能demo

    从官网下载了最新版本的Angularjs 版本号:1.3.15 做一个简单的路由功能demo 首页:index.html <!DOCTYPE html > <html> <head> <meta charset="utf-8" /> <title>测试</title> <script src="./js/angular.min.js"></script> <scri

  • 使用Angular.js实现简单的购物车功能

    先给大家分享实现代码,在代码下面有效果图展示,大家可以两者结合参考下,废话不多说了,具体代码如下所示: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="http://code.angularjs.org/1.2.5/angular.min.js"></script

  • React Native实现简单的登录功能(推荐)

    React Native 简介: React Native 结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生应用.在 JavaScript 中用 React 抽象操作系统原生的 UI 组件,代替 DOM 元素来渲染等. React Native 使你能够使用基于 JavaScript 和 React 一致的开发体验在本地平台上构建世界一流的应用程序体验.React Native 把重点放在所有开发人员关心的平台的开发效率上

  • PowerShell实现简单的grep功能

    在PowerShell中,无法像*nix中一样使用grep命令,直接对一个目录下的所有文件进行内容查找,下面的PS脚本针对目录和文件进行了区分,借用Select-String命令,实现了内容查找,并显示查找到的文件和匹配内容所在行号. 使用的时候,只需要在shell中,输入: "命令所在目录"\grep.ps1 "需要查找的字符串" "需要查找的路径" param($str, $path=".\") #输入参数,默认在当前目录

  • jQuery实现简单日期格式化功能示例

    本文实例讲述了jQuery实现简单日期格式化功能.分享给大家供大家参考,具体如下: 代码如下,引入jquery后直接后加入以下代码刷新可测试 Date.prototype.Format = function (fmt) { //author: meizz var o = { "M+": this.getMonth() + 1, //月份 "d+": this.getDate(), //日 "h+": this.getHours(), //小时 &

  • jQuery实现简单的计时器功能实例分析

    本文实例讲述了jQuery实现简单的计时器功能.分享给大家供大家参考,具体如下: 在写项目的过程中遇到要前端60秒发送验证码的业务需求,于是用到计时器的功能: setInterval(function xxx(){ //业务逻辑 },隔多少时间执行一次) 60秒计时思路: 1.设置秒数:60s 2.设置内容:实时改变,秒数+内容 3.结束后:去掉按钮的disable,内容恢复原来样子 //计时器60秒 function timeInterval(){ $("#code_send_btn"

  • Vue组件BootPage实现简单的分页功能

    有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更一篇文章,分享一个自己编写的一个Vue的小组件,名叫BootPage. 不了解Vue.js的童鞋可以移步我的上一篇文章<浅谈Vue.js>了解一下. BootPage组件简介  其实也不是啥高大上的组件了,相反确实一个简单的表格分页组件而已,主要是自己最近项目中需要一个表格分页组件,而Vue官方组件库里分页组件都功能太强大或者没有适合我的,所以就自己写了一个凑合着用,或许有人和我一样需要这样

  • 使用Lucene实现一个简单的布尔搜索功能

    什么是lucene Lucene是apache软件基金会jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言). Lucene是一个全文搜索框架,而不是应用产品.因此它并不像www.baidu.com 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品. 在布尔查询的对象中,包含一个子句的集合,各个子句间都是如

  • Java简单验证身份证功能示例

    本文实例讲述了Java简单验证身份证功能.分享给大家供大家参考,具体如下: package org.cxy.csdn.example; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import javax.xml.bind.Validator; /** * 身份证验证的工具(支持5位或18位省份证)<br/> * 身份证号码结构: * <ol> * <li>17位数

随机推荐