数学建模社区-数学中国

标题: 用C++ Builder对图像进行特殊效果处理 [打印本页]

作者: 韩冰    时间: 2005-1-26 12:49
标题: 用C++ Builder对图像进行特殊效果处理
<>
$ k" u& o# {/ u2 o2 l周新栋
1 q4 U9 S9 ]# g/ h/ f$ o* { </P>4 O, j$ O) d5 r# X9 Z0 Z
<>     </P>4 P3 J/ m1 v7 n% i: r0 l1 K
<>3 H1 G1 E! E0 j  ?* w
--- 在Windows编程中图像处理相对比较复杂,好在C++ Builder提供了一些图形类,它们通过对Windows中的图形对象进行包装,从而大大简化了图像操作的难度。下面就通过对图像进行柔化、锐化、浮雕效果等几个特殊效果处理来具体说明一下。 </P>
( f' ~, {+ A' Q) W<>---- 一、准备工作 位图图形实际上是像素的二维数组,它记录了每个像素的颜色信息,而TCanvas类提供了Pixels属性,用它可以存取指定像素的颜色值,通过这个属性将位图图形的部分或全部像素的颜色值进行相应的变换处理,就可以实现图像的特殊效果处理。在Windows中颜色是根据红、绿、蓝三种颜色的饱和度来定义的,在这里我们要将像素颜色值的红、绿、蓝分量从像素值中分离出来,分别加以保存,所以需要定义一个结构来存放颜色分量: </P>2 M/ ]+ P6 S+ \# c3 e
<>struct rgb_str{1 t$ m7 P$ {' }; E4 ?/ \  ~. `
unsigned char r_color;
( p. O" Z6 M% k  ?* Gunsigned char g_color;$ Y/ J6 \6 t7 p9 T+ b1 M7 @7 J$ m
unsigned char b_color;};6 X5 F, S6 |6 L9 U% c! F
rgb_str rgb[2000][2000];</P>
3 h8 \% z) W' Q, \) D9 H<>建立全局变量:Graphics::TBitmap *bitmap;- l3 r5 l8 g( Y' N
//用来存放变换后的位图
+ W4 `) [7 i% N8 h% o& Dint i,j,width,height;</P>, k$ {/ t2 o( K0 ]0 m1 c+ n
<>---- 在窗体上放置一个TImage组件和OpenPictureDialog组件,将TImage的AutoSize属性设为true,将OpenPictureDialog的Filter设为*.bmp。当用户选择Open命令后,打开相应的对话框,让用户选择要处理的图像文件,然后程序将图像的所有像素的颜色分量保存到rgb数组中: </P>6 f4 L% J- h& H: ^3 _) M
<>void __fastcall TForm1::mnuFileOpenClick+ |3 G9 j0 _& L$ i8 H; A$ B
(TObject *Sender)- H: w. p1 A9 D6 V9 c
{
* F; r. F6 H, b" F% r" ]TColor color;) t( B: O2 O, ^" `7 U. K8 C1 G$ z
if(OpenPictureDialog1- &gt;Execute()){
" k% n/ B- S0 B/ a2 f$ GImage1- &gticture-&gt;LoadFromFile2 w5 C2 C! X! o1 ~# x0 X8 n
        (OpenPictureDialog1- &gt;FileName);! F* }# d5 m( L/ z, f
width=Image1- &gticture- &gt;Width;# C, y- b0 Z3 D/ Y8 A
height=Image1-&gticture-&gt;Height;) u! n" r) O9 o- n
for(i=0;i&lt; width-1;i++)/ m* `5 s; o: V* U4 ?. w# s# f% x
for(j=0;j&lt; height-1;j++){; m2 H, ~% F7 Z7 p& g$ Q
color=Image1- &gt;Canvas-&gtixels[j];
- ]! V- W, m; k. i: F3 V1 y" ]rgb[j].r_color=GetRValue(color);
2 v  Q  p* k! T3 trgb[j].g_color=GetGValue(color);6 _& {' K2 G) W9 h! |
rgb[j].b_color=GetBValue(color);
* _9 ?# P: [0 D% t}
, |# W9 S: ]% ]; O' @1 J, z$ wbitmap=new Graphics::TBitmap;) i+ o$ m( k( ]
bitmap- &gt;Width=width;! M6 c% F+ p0 w
bitmap- &gt;Height=height;( h+ l' ^. O# o
}. H" h% f  n5 ^/ ]# k
}</P>
6 h5 A9 T& J3 L3 K6 v<>
: H/ R8 U# K& y- Q# j0 K1 u( U  O3 }---- 二、图像的柔化处理 </P>7 O9 [" K! O1 M: t# k8 q7 t: N
<>---- 柔化就是对图像进行平滑处理,减少相邻像素间的颜色差别,一般选用3*3像素块,将中间的像素值改成这9个像素的平均像素值,从而达到柔化效果。其代码如下: </P>+ N2 ?, ?2 v! [! ?
<>void __fastcall TForm1::btnSmoothClick! o4 o- N( q2 [. w3 B0 W, E! e' C
(TObject *Sender)
& G6 i% Z8 V( x+ T' _{
% K) s& K. W+ Z: P( O8 @int red,green,blue;
3 @1 Z( r$ Z: Ifor(i=1;i&lt; width-2;i++)
# I, \  B. A1 c( z. E( xfor(j=1;j&lt; height-2;j++){
) O+ M; v) p2 J9 o$ m% N6 b  z* h  z2 Lred=rgb[i-1][j-1].r_color+rgb[j-1].r
4 P! n0 O5 t7 L4 D        _color+rgb[i+1][j-1].r_color+9 B7 B! |5 N2 O0 w5 B; V
rgb[i-1][j].r_color+rgb[j].r4 K0 [1 i# ?3 y6 Y) y  a0 ~- z
            _color+rgb[i+1][j].r_color+</P>
  y+ V- ?" k! W<>            rgb[i-1][j+1].r_color+rgb[j+1].r8 L3 G5 u, [. o, _
            _color+rgb[i+1][j+1].r_color;
. u$ G$ A* F1 r' z5 F5 h, T& ?green=rgb[i-1][j-1].g_color+rgb[j-1].g
4 m* m; e' y- g        _color+rgb[i+1][j-1].g_color+* s0 m5 V" a! A0 a4 N
rgb[i-1][j].g_color+rgb[j].g- E8 \8 ~! t9 v: g! P$ z5 J9 E
            _color+rgb[i+1][j].g_color++ b/ Q3 t! d& T0 |; O
rgb[i-1][j+1].g_color+rgb[j+1].g0 @3 g& a4 n# ~$ e( p+ {" T
            _color+rgb[i+1][j+1].g_color;! x% @2 m; Y& m
blue=rgb[i-1][j-1].b_color+rgb[j-1].b& k3 U( q5 d% L7 y$ ?
        _color+rgb[i+1][j-1].b_color+* V" l9 U' z5 [  v. m
rgb[i-1][j].b_color+rgb[j].b
% V" l- {6 [- Y# A; @7 U8 X3 O7 z  g            _color+rgb[i+1][j].b_color+
  _) q& P+ g/ E5 @9 o5 `& X& Brgb[i-1][j+1].b_color+rgb[j+1].b3 v! q) ^% K  p6 m" T7 z' E
            _color+rgb[i+1][j+1].b_color;, ^8 l3 d. Y3 M8 E0 K
bitmap- &gt;Canvas- &gtixels[j]" ]# O( I$ s6 P* s' D% b8 R' k' P
        =RGB(red/9,green/9,blue/9);
; \- b' p" ~( s; _0 X4 P% ^2 p}
( Q  V/ ?) X6 k1 oImage1- &gticture- &gt;Bitmap- &gt;Assign(bitmap);! e' U* }0 f7 D- J* ?
}</P>, b( o- U2 G) ?7 I8 l
<>---- 三、图像的锐化处理 </P>
1 W! s, D# {) l5 c8 I4 b<>---- 图像的锐化处理正好与柔化处理相反,它的目的是突出图像的变化部分,这里采用的算法是将要处理的像素与它左对角线的像素之间的差值乘上一个锐化度数,然后再加上原先的像素值:new_value=original_value+degree*difference,你可以通过改变degree的值来调节锐化效果。这里需要注意的是得到的像素新值可能会超出颜色值的有效范围(0-255),所以程序要检验结果的有效性,为此需定义两个函数: </P>0 S# ]4 C- b1 f! S% }* m" |/ k+ @5 Z/ \( C
<>int min(int value1,int value2)" w5 \# i! `* i# f
{( p; t& }0 o, E" m) p
if(value1 &gt;value2)return value2;
9 l' T6 K- _1 J. v$ K7 f* O2 lelse return value1;
) w  m$ `  b2 ?. a2 @$ J}
& @, o0 [4 b4 W0 r9 nint max(int value1,int value2). f/ Q$ D" `# D5 K* s" c3 F
{1 ^7 d% j; ?% g/ b6 Z% _: o" Q
if(value1 &gt;value2)return value1;
$ Y) H! B9 y; v8 t. Melse return value2;
# b: V: A. j8 w9 G* K}</P>
% i+ d7 U1 \$ P4 c<>锐化处理的代码如下:</P>
0 }( _7 L3 O$ k' O0 A% f<>void __fastcall TForm1::btnSharpeClick& `' g. ^8 a7 F
(TObject *Sender)
: W/ i  Q) z' ^5 x/ R{5 ^* p* P8 f* U* f& m' ~8 S& _
float degree=0.3;
& C5 [& w6 R, Q# V' s9 N, u1 M) ^! aint red,green,blue;
6 s0 N& N6 _+ Y  Afor(i=1;i&lt; width-1;i++)7 w* L5 u7 B0 A) q8 z1 q" ^
for(j=1;j&lt; height-1;j++){
$ n3 l! z8 m* x* r$ ~& sred=rgb[j].r_color+degree*(rgb[j].r& v, {8 E% P  ^' V
        _color-rgb[i-1][j-1].r_color);$ _# y# ^- |- S/ L) I: I: o' G0 X
green=rgb[j].g_color+degree*(rgb[j].g
% {/ Q" m7 S7 |9 t        _color-rgb[i-1][j-1].g_color);7 ]: C6 g$ U& m; f2 }
blue=rgb[j].b_color+degree*(rgb[j].b
3 b; L9 O  Q4 m% C        _color-rgb[i-1][j-1].b_color);
' C9 w: S( R3 j0 yred=min(255,max(0,red));
) S/ _  W2 M, n6 w9 h5 ^7 O# D2 Wgreen=min(255,max(0,green));4 y8 `6 @4 ~$ e5 ]
blue=min(255,max(0,blue));! @: ?% x$ p5 ], z+ g) M  e
bitmap- &gt;Canvas-&gtixels[j]=RGB
. a* S5 l& v2 J& A/ t# N. G        (red,green,blue);
9 C; J& e8 F$ L- B( b4 v  U- m}7 c: ^8 p% j7 ~6 `) n4 ^1 h$ P
Image1- &gticture- &gt;Bitmap- &gt;Assign(bitmap);1 `2 o  @; o9 S: H
}</P>
( \; l6 P, s" P( C6 M<>
+ d& }, h& J6 Q1 H( F3 ]---- 四、图像的浮雕效果实现 </P>
1 o$ j3 Q. y8 S8 M+ O5 c5 H<>---- 浮雕效果就是只将图像的变化部分突出出来,而相同颜色部分则被淡化,使图像出现纵深感,从而达到浮雕效果,这里采用的算法是将要处理的像素取值为与处于对角线上的另一个像素间的差值,这样只有颜色变化区才会出现色彩,而颜色平淡区因差值几乎为零则变成黑色,你可以通过加上一个常量来增加一些亮度:new_value=difference+const_value,具体代码如下: </P>
2 L/ Y& D. m) S1 A5 Z5 r; \- {$ X<>void __fastcall TForm1::btnEmbossClick
; u2 N5 E0 g- H+ F( D& G+ c8 W(TObject *Sender)
" A. Y5 J+ X/ g- W/ g{
4 X" V: u3 J. G7 X  a! A2 |5 Wint red,green,blue;
8 q; [# G0 v" O: I% jconst int const_value=128;
) D: F, T7 P" d' r4 p/ wfor(i=0;i&lt; width-2;i++)
' A- l& [. x- @: r% Q7 _; gfor(j=0;j&lt; height-2;j++){* ~' C3 a5 {) `+ c0 K% W$ x
red=abs(rgb[j].r_color-rgb[i+1][j+1].r
: p% T4 e$ _( @        _color+const_value);2 n! e) m  Y* R% y' l3 b# c+ J/ F
green=abs(rgb[j].g_color-rgb[i+1][j+1].g
% Q0 J% p2 o) C; a- g  W        _color+const_value);  x  }. L" w* {  _* G
blue=abs(rgb[j].b_color-rgb[i+1][j+1].b_
, T5 p, C  ~0 R2 G: r4 C2 Y        color+const_value);
9 a* S, N( r# m0 [bitmap- &gt;Canvas- &gtixels[j]=RGB( a% ~  q( X7 v$ f  A2 k2 K; ]+ N
        (red,green,blue);
$ \' H9 m, Y& r* X6 `, |6 ?' L}
, Y' M4 z) d; ~Image1- &gticture- &gt;Bitmap- &gt;Assign(bitmap);- \) m- i. m8 Q3 B
}</P>; o, }& ]3 d; i1 I  c) V5 \
<P>---- 上面介绍了图像处理中的几个常见操作,所采用的算法相对比较简单,感兴趣的朋友可以举一返三,通过改进上述算法,达到更好的特殊效果。以上代码在C++ Builder3、Pwin98下编译、运行通过。
% f4 B3 Z4 Z+ F. C& b% L7 `: K</P>




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5