VB.NET2005 TIPS / グラフィックス系 |
G0501 画像の線形変換 |
最終更新:2006/11/12 再掲 |
●解説
画像に対して、上下、左右の反転、回転、拡大・縮小、移動などを行う。
→線形変換とは?:直線は直線となり、平行線は平行線のままとなり、複数の物のサイズ比は保たれる ような変換のこと
|
|
回転 |
回傾斜 |
●原理
原画の三つの角の座標がどのようになるかをポイント配列で指定する。配列の順序で原画のポイント位置が下図のように決まっている。左右反転の場合は下図のように、各配列に新しい座標値を指定すれば良い。
基準点が三点であることは、任意の平行四辺形が新しい画像の外形となることを示す。非平行な四辺形は不可能である。つまり、非線形変換はできない。縦、横のサイズも任意である。等倍の場合は縦横とも原画と同じにするだけの話。もうお分かりと思うが、これにて、反転、移動、拡大、縮小、傾斜、回転の全てを一度に指示できる。
●方法
例えば、po(3) As PointF で、
po(0):原画の左上端の新しい具体的な座標
po(1):原画の右上端の新しい具体的な座標
po(2):原画の左下端の新しい具体的な座標
をそれぞれ指定する。
1.左右反転
po(0)、po(2)をpo(1)より右の座標とする。
2.上下反転
po(2)をpo(0)、po(1)より上にする。
3.拡大、縮小
アスペクト比を保つなら、縦横比を保った矩形とする。
4.傾斜
p(2)をともに左右どちらかにシフトすれば、横方向の傾斜となる。P(1)を上下に動かせば縦方向の傾斜となる。
5.回転
回転中心を決めて、回転後の座標を求め指定する。このとき、元の座標値群を回転のアフィン変換する。D1001参照方。
●補間
傾斜、回転、拡大、縮小では補間を施す。少なくともBilinearとするのが良い。
●実例
○例1:拡大(縮小)
gはGraphics、Xc,Ycはgの中心座標とする。picOrgに原画がImageとして存在するものとする。
Dim CR As Single = 1.56
Dim PW As Single = picOrg.Image.Widht * CR
Dim PH As Single = picOrg.Image.Height * CR
Dim rec As RectangleF = New RectangleF(Xc - PW / 2, Yc - PH / 2, PW, PH)
g.InterpolationMode = InterpolationMode.Bilinear
g.DrawImage(picOrg.Image, rec)
○例2:回転
gはGraphics、Xc,Ycは画像回転中心座標とする。picOrgに原画がImageとして存在するものとする。
Dim d As Single , RotPs(2)
As PointF
d = (回転角度:度単位)
Dim PW As Single = picOrg.Image.Widht
Dim PH As Single = picOrg.Image.Height
Dim rec As RectangleF = New RectangleF(Xc - PW / 2, Yc - PH / 2, PW, PH)
‘回転前の画像位置
AffineOne(rec.X, rec.Y, Xc, Yc, RotPs(0).X,
RotPs(0).Y, d)
‘回転後の左上端座標
AffineOne(rec.Right, rec.Y, Xc, Yc, RotPs(1).X, RotPs(1).Y, d)
‘回転後の右上端座標
AffineOne(rec.X, rec.Bottom, Xc, Yc, RotPs(2).X, RotPs(2).Y, d)
‘回転後の左下端座標
g.InterpolationMode = InterpolationMode.Bilinear
g.DrawImage(picOrg.Image, RotPs)
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
Public Sub AffineOne(ByVal X As Single, ByVal Y
As Single, ByVal Xc As Single, ByVal Yc As Single, ByRef aX As Single, ByRef aY
As Single, ByVal d As Single)
Dim A As Double = Radian(d)
aX = (X - Xc) * Cos(A) - (Y - Yc) * Sin(A) + Xc
aY = (X - Xc) * Sin(A) + (Y - Yc) * Cos(A) + Yc
End Sub
Private Function Radian(ByVal A
As Double) As Double
Return PI / 180 * A
End Function
|