graphic.DrawImage()を使ったのグラフの加工方法をDOBON.NET様記事から学習してます。
●やりたいこと
スキーターンの全測定データを大きなBITMAPに展開してから、表示したい部分だけ切り取って所定位置へ平行移動してから回転してターンのラインを水平に並べて正規化してみたい。
=>そうすることで、ターンの各種パラメータ値と視認した形状が一致してターン同士の
比較など、解析が一目瞭然になることを目的としてます。
●今回は、四角を平行四辺形への自由変形です。
画像の加工は、四角の領域単位で行います。切取りも四角で、変形も四角を平行四辺形に自由に変形します。四角を平行四辺形に自由に変形することで、回転と平行移動が実現できます。.NETには、各種画像変形手段がありますが、何種類もコマンドを覚えても結果は、同じなので、一番シンプルな平行四辺形への変形方法さえ覚えれば、あとは、視覚したい形状を計算してそのように平行四辺形を作ればいいので、2次元では万能の使い方で、3次元もある程度扱えると思います。
●学習教材はDOBON.NET様のhttps://dobon.net/vb/dotnet/graphics/skewing.html
画像を傾けて表示する
四角を平行四辺形に自由変形する方法です。
DOBON.NET様の場合、jpgから読み込んで変形させるものです。
本家MSの解説記事も丁寧です。
https://docs.microsoft.com/ja-jp/dotnet/desktop/winforms/advanced/how-to-rotate-reflect-and-skew-images?view=netframeworkdesktop-4.8
●私の学習プログラム
前回の大きなグラフから必要な部分を矩形切取りするプログラムから
矩形切り取ったグラフを更に、変形させる機能を追加したものです。
マウスで矩形の上左と上右と下左の3点を指定することで自由変形させて平行四辺形を作ります
元の矩形の形状を変更せずに傾かせれば回転させたことになります。平行移動は、
そのまま3点に移動したい座標をいれれば移動します。つまり、矩形の3点を指定するだけで
回転と移動ができてしまいますので、シンプルで万能な画像加工命令となります。
●このプログラムのダウンロード
半日くらいの学習でできてますが、BITMAPとGraphic.ImageとPictureBoxの関係がこんがらがってしまう点が付きまといますが、プログラムをいじりながら動作実験すれば、グラフィックの動きが肌で感じることができるので、考えるより触って覚えたほうがいいです。
ソリューションファイルのZIPはこれです。100行で70kBしかありません。
Dobon_bitmapRotateTrans_01
ソースはGISTにアップしておきますが、ソースだけだとFORMを作らないと動作しませんので、ソリューションのZIPをダウンロードしたほうが学習が進みます。https://gist.github.com/dj1711572002/9594e6922e402261dbd7d160f4412dcb
●画像関係でわからなくなる点
BITMAPとGraphicsとImageとPictureBoxがあってごちゃごちゃになってしまいます。
=>MSのリンクは下記です
BITAMAPは、文字通りビットで画像を表したクラスです。
Graphicsは、フォームで画像を加工するためにクラスです。
Imageは、小孫クラスでBITMAPとmetafileに機能ををて提供する抽象的な基本クラス
pictureboxイメージを表示するために使用する Windows ピクチャ ボックス コントロールを表します
自分流に理解したメモを残しておきます。
’BITMAPの定義 ’ここでは、canvasという410×210ドットの矩形領域のbitmapを定義してます。Dim canvas As New Bitmap(410, 210) ’Graphicsの定義=>ここでは指定した Image(canvas) の新しい Graphics (g)を作成してます。 ’BITMAPがあるのに更にGraphics gとは何だと思っていたのですが、 ’BITMAPに点を打ったり、線や丸や四角を描画する加工をするためにGraphicsがあります。 ‘Graphicsは、画像そのものではなく加工するための一時作業場所です。 ‘ですので、加工が終わったらg.dispose()で解放してしまいますが、加工結果の画像は ’canvasに残ってますので大丈夫です。Dim g As Graphics = Graphics.FromImage(canvas) |
●Graphics.DrawImage()
画像(image)を矩形で加工する命令です。
’ここでは、totalPlotという大きなグラフのBITMAPから、srcRect矩形領域で切り取って ‘desRect領域に書き込みます。g.DrawImage(totalPlot, desRect, srcRect, GraphicsUnit.Pixel) |
●矩形を変形させる
DrawImage(Image, Point[])
指定した Image を指定した場所に指定した形状とサイズで描画します。
Dim canvas3 As New Bitmap(600, 400) Dim g3 As Graphics = Graphics.FromImage(canvas3) ‘上記gで切り取ったとの同じ画像をcnavas3に書きこんでおきます。 ’変形前の形を比較用に書き込む g3.DrawImage(totalPlot, desRect, srcRect, GraphicsUnit.Pixel)‘canvasを変形して傾いた画像をg3(canvas3)へ描画する ’canvas3でなくcanvasを使っているのがcanvas3がcanvasより大きいので平行四辺形の計算 ’で縮小されてしまうためcanvasサイズで平行四辺形を作らない元図形と縮尺が違ってしまうか ‘canvas3は、変形した図形を全部表示するために600,400とcanvas(410,210)より大きくした g3.DrawImage(canvas, destinationPoints) |
上記destinationPointsは、3点のポイント構造体で指定されてます。
‘======四角画像を変形表示させる位置を指定する=======
‘元の画像の左上の位置を(ulx, uly)にする ‘元の画像の右上の位置を(urx, ury)にする ‘元の画像の左下の位置を(llx, lly)にする Dim destinationPoints() As Point destinationPoints = New Point() {New Point(ulx, uly),New Point(urx, ury),New Point(llx, lly)} |
最後に
graphics.Dispose()
メモリーを食うので、使い終わったらこまめに開放してやらないとプログラムが遅くなる
‘Graphicsオブジェクトのリソースを解放する g.Dispose() g3.Dispose()‘PictureBox2に表示する ‘gで大きなtotalPlotを切り取った画像canvasをPictureBox2へ書き込むPictureBox2.Image = canvas‘g3で作っグラフィックcanvas3をPictureBox3へ書き込むPictureBox3.Image = canvas3 |
※2021年11月21日追記 DrawImgeの応用で、リアルタイムグラフをbitmap処理して拡大縮小、カーソルを自由に動かすことができるようになりました。
●以後
この学習プログラムをいじりながら、グラフィックを手で覚えていきます。