Home > 日常 > AlphaCompose(画像合成)

AlphaCompose(画像合成)

  • 2008-10-04 (土) 17:17
  • 日常
  • 投稿者:hitotsu
WebカメラキャプチャーソフトWebCameraSnapに新機能を組み込むための実験。
新機能は、テンプレート画像とキャプチャー画像のリアルタイム合成。

指定した背景画像に画像を合成するのにかかる時間を調査。
まず、GDI+のDrawImageを試してみることにする。
定常的に50ms程度で処理ができれば問題ないだろう。

————————–
処理の手順は以下のとおり

(1)背景画像を読み込み(これがキャプチャー画像に相当)
PictureBox1に表示
(2)合成画像を読み込むBitmapオブジェクトに格納
(3)背景の上に合成画像を合成、この時に指定したα値で合成する
合成画像をPictureBox1に表示
————————–

[実験結果]
800×600ピクセルの画像合成が30ms程度で完了しているので、DrawImageを採用しようと思う。
DrawImageは少しクセがあるように感じた。

Bitmapオブジェクトを取得するのにSystem.Drawing.Image.FromStream()を使っていたが、
必ずDrawImage実行時にOutOfMemoryExceptionが発生する。
なお、Bitmap.FromFile()を利用してオブジェクトを取得した場合は発生しない。

結局、New Bitmap()や縮小処理で新規作成したBitmapオブジェクトを利用するようにして、
この問題は発生しなくなった。原因追求は行っていないが何か理由があるのだろう。




[作成したプログラム]



Public Class Form1
Public bg_file As String = "C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water lilies.jpg"
Public pic_file As String = "C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Sunset.jpg"
Public pic_bmp As Bitmap = Nothing
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
TrackBar1.Value = 40
End Sub
' ファイルからイメージを読み込む
Public Function draw_picture(ByVal fname As String) As Bitmap
Dim fs As System.IO.FileStream = New System.IO.FileStream(fname, System.IO.FileMode.Open, System.IO.FileAccess.Read)
Dim img As Image = Nothing
Try
img = System.Drawing.Image.FromStream(fs)
Catch ex As Exception
MessageBox.Show(ex.Message)
img = Nothing
Finally
fs.Close()
End Try
Return CType(img, Bitmap)
End Function
' orgをwidth x heightのイメージにして返します
Function trans_compose_image(ByVal org As Image, ByVal width As Integer, ByVal height As Integer) As Image
Dim compose As Bitmap = New Bitmap(width, height)
Using g As Graphics = Graphics.FromImage(compose)
g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
g.DrawImage(org, 0, 0, width, height)
End Using
Return compose
End Function
' 背景画像bgに透明度alphaで前景画像imgを合成します
' imgにSystem.Drawing.Image.FromStream()で取得したImageを指定するとOutOfMemoryExceptionが発生するようです
' 引数imgはNew Bitmap(FromStream())で生成したオブジェクトを渡してください
Sub compose_picture(ByVal bg As Bitmap, ByVal img As Bitmap, ByVal alpha As Single)
Dim g As Graphics = Graphics.FromImage(bg)
'ColorMatrixオブジェクトの作成
Dim cm As New System.Drawing.Imaging.ColorMatrix()
'ColorMatrixの行列の値を変更してアルファ値を変更
cm.Matrix00 = 1
cm.Matrix11 = 1
cm.Matrix22 = 1
cm.Matrix33 = alpha
cm.Matrix44 = 1
'ImageAttributesオブジェクトの作成
Dim ia As New System.Drawing.Imaging.ImageAttributes()
'ColorMatrixを設定する
ia.SetColorMatrix(cm)
'ImageAttributesを使用して画像を描画
g.DrawImage(img, New Rectangle(0, 0, bg.Width, bg.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia)
'リソースを開放する
g.Dispose()
End Sub
' PictureBox1に背景画像を表示
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim start_ As Integer = System.Environment.TickCount
If Not System.IO.File.Exists(bg_file) Then
Return
End If
Dim bg_bmp As Bitmap
bg_bmp = draw_picture(bg_file)
If Not PictureBox1.Image Is Nothing Then
PictureBox1.Image.Dispose()
PictureBox1.Image = Nothing
End If
PictureBox1.Image = bg_bmp
Dim end_ As Integer = System.Environment.TickCount
Label4.Text = "所要時間:" & (end_ - start_) & "(ミリ秒)"
End Sub
' 合成画像ファイルの読み込み、偏倍処理を毎回していると時間がかかるので、合成画像ファイル名の変更、キャプチャーサイズの変更があった時だけ
' 合成画像を生成するようにする
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim start_ As Integer = System.Environment.TickCount
If Not pic_bmp Is Nothing Then
pic_bmp.Dispose()
pic_bmp = Nothing
End If
If Not System.IO.File.Exists(pic_file) Then
Return
End If
If PictureBox1.Image Is Nothing Then
Return
End If
Dim dis_bmp As Bitmap
dis_bmp = draw_picture(pic_file)
If True Then
' 合成画像を出力先のサイズにあわせる場合
Dim dis_bmp2 As Bitmap
dis_bmp2 = trans_compose_image(dis_bmp, PictureBox1.Image.Width, PictureBox1.Image.Height)
dis_bmp.Dispose()
pic_bmp = dis_bmp2
Else
' サイズを変更しない場合
pic_bmp = New Bitmap(dis_bmp) ' dis_bmpをDrawImage()にそのまま渡すとOutOfMemoryExceptionが発生します。Bitmapを生成しておきます。
End If
Dim end_ As Integer = System.Environment.TickCount
Label4.Text = "所要時間:" & (end_ - start_) & "(ミリ秒)"
End Sub
' 表示画像に指定画像を合成
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim start_ As Integer = System.Environment.TickCount
Dim src_bmp As Bitmap = PictureBox1.Image
If pic_bmp Is Nothing Then Return
compose_picture(PictureBox1.Image, pic_bmp, TrackBar1.Value / 100.0F)
PictureBox1.Image = src_bmp
Dim end_ As Integer = System.Environment.TickCount
Label4.Text = "所要時間:" & (end_ - start_) & "(ミリ秒)"
End Sub
End Class