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

2025-05-27 0 105

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

1.点运算

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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43
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版本可以做一些简单的卷积运算。以中值滤波为例:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214
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,即不可以

?

1

2

3

4

5

6

7
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虽然我没用过,但从介绍来说,应该可以处理一些更为复杂的图像处理

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

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 C++ HLSL实现简单的图像处理功能 https://www.kuaiidc.com/73718.html

相关文章

发表评论
暂无评论