C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: Regionデータのバイナリデータ化について


(過去ログ 77 を表示中)

[トピック内 19 記事 (1 - 19 表示)]  << 0 >>

■45554 / inTopicNo.1)  Regionデータのバイナリデータ化について
  
□投稿者/ にわか雨 (6回)-(2010/01/14(Thu) 17:13:42)

分類:[VB.NET/VB2005 以降] 

質問させて頂きます。
何かアドバイス頂けたらと思います。

作成PG概要----------------------------------------
○CSVファイル取込(県ごとの在庫データCSV)
 ↓
○地図画面表示
※CSVの在庫データの数値によって地図内の県に対する色を変える。
----------------------------------------------------

PGは完成したのですが一つ問題があります。
47都道府県のクリッピング領域を取得するのにものすごく時間がかかっています。
各県のRegionデータをバイナリ保存できたら読み込み後すぐに利用可能だと思い下記のコードを作成したのですが
エラーが発生してしまいます。
--------------------------------------------------------------------------------------------
Dim img(19) As Image 'Image宣言
Dim rgn() As Region = New Region(19) {} 'Region宣言
Dim x As Integer

'都道府県毎のクリッピング領域を取得
x = 0
While x < 20

'県毎のimageを取得
img(x) = Image.FromFile("D:\画像データ\" & kenmei(x) & "972×1191.bmp")

'imageを基にRegionを作成(imgファイルの黒以外のピクセルを透明にする関数)
rgn(x) = CreateRegionFromImage(img(x), Color.White)

'保存先のファイル名
Dim fileName As String = "D:\画像データ\" & kenmei(x) & "972×1191.obj"

      'Regionデータをバイナリファイルとして保存
Dim fs As New FileStream(fileName, FileMode.Create, FileAccess.Write)
Dim bf As New BinaryFormatter
bf.Serialize(fs, rgn(x))
fs.Close()

x = x + 1
End While
--------------------------------------------------------------------------------------------
エラー内容:
アセンブリ 'System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' の型 'System.Drawing.Region' はシリアル化可能として設定されていません。


バイナリファイルにする方法を教えていただけないでしょうか?
引用返信 編集キー/
■45555 / inTopicNo.2)  Re[1]: Regionデータのバイナリデータ化について
□投稿者/ .SHO (1123回)-(2010/01/14(Thu) 18:00:11)
No45554 (にわか雨 さん) に返信

質問の答えではないのですが…

これってたいして速くならないんじゃないでしょうか?
実測で、CreateRegionFromImage() が、もの凄く時間がかかってるんですか?

一つの県の画像が 972X1191 って、ものすごくでかい地図??
でも、20回のループだと47都道府県の話とあわないし…

引用返信 編集キー/
■45558 / inTopicNo.3)  Re[2]: Regionデータのバイナリデータ化について
□投稿者/ にわか雨 (7回)-(2010/01/14(Thu) 18:18:13)
No45555 (.SHO さん) に返信
> ■No45554 (にわか雨 さん) に返信
>
> 質問の答えではないのですが…
>
> これってたいして速くならないんじゃないでしょうか?
> 実測で、CreateRegionFromImage() が、もの凄く時間がかかってるんですか?
>
> 一つの県の画像が 972X1191 って、ものすごくでかい地図??
> でも、20回のループだと47都道府県の話とあわないし…
>
ご返信ありがとうございます。
CreateRegionFromImage()に時間がかかっています。
はい!!ものすごくでかい地図です。
ループは47回です。ごめんなさい。PGが間違っています。

CreateRegionFromImage()で取得したデータをバイナリファイルで保存し、
今後実行するときはそのバイナリファイルからリージョンを取得的な・・・
むつかしいのでしょうか・・・?

引用返信 編集キー/
■45559 / inTopicNo.4)  Re[1]: Regionデータのバイナリデータ化について
□投稿者/ たくボン (315回)-(2010/01/14(Thu) 18:31:53)
2010/01/14(Thu) 18:48:10 編集(投稿者)

No45554 (にわか雨 さん) に返信
> PGは完成したのですが一つ問題があります。
> 47都道府県のクリッピング領域を取得するのにものすごく時間がかかっています。
> 各県のRegionデータをバイナリ保存できたら読み込み後すぐに利用可能だと思い下記のコードを作成したのですが
> エラーが発生してしまいます。
> エラー内容:
> アセンブリ 'System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' の型 'System.Drawing.Region' はシリアル化可能として設定されていません。

RegionはSerializable属性が付与されていないから。

http://msdn.microsoft.com/ja-jp/library/system.drawing.region(VS.80).aspx

RegionDataを保存するなら、

Using fs As New FileStream("C:\temp\hoge.obj", FileMode.Create, FileAccess.Write)
fs.Write(Me.Region.GetRegionData().Data, 0, Me.Region.GetRegionData().Data.Length)
End Using

(コードを修正)
引用返信 編集キー/
■45560 / inTopicNo.5)  Re[3]: Regionデータのバイナリデータ化について
□投稿者/ たくボン (316回)-(2010/01/14(Thu) 18:37:24)
No45558 (にわか雨 さん) に返信
> ■No45555 (.SHO さん) に返信
>>■No45554 (にわか雨 さん) に返信
>>一つの県の画像が 972X1191 って、ものすごくでかい地図??
>>でも、20回のループだと47都道府県の話とあわないし…
>>
> ご返信ありがとうございます。
> CreateRegionFromImage()に時間がかかっています。
> はい!!ものすごくでかい地図です。

うーん、でかくはないと思うけどなぁ。
この前作った画像処理では約7000*5000の画像をマスク処理やビット走査してたけど、そんな遅くはなかったですよ。

Region作成時のビット走査はBitmapData使ってます?
引用返信 編集キー/
■45561 / inTopicNo.6)  Re[3]: Regionデータのバイナリデータ化について
□投稿者/ .SHO (1124回)-(2010/01/14(Thu) 18:43:31)
No45558 (にわか雨 さん) に返信

> はい!!ものすごくでかい地図です。

県の大きさはそれぞれ違うわけだから、972×1191って一番大きな県(北海道?)に
合わせてるんですよね?たぶん。

県毎に適切な大きさに合わせてやれば速くなるんじゃないですかね?
リージョンで保存するにしても。

引用返信 編集キー/
■45562 / inTopicNo.7)  Re[4]: Regionデータのバイナリデータ化について
□投稿者/ みきぬ (710回)-(2010/01/14(Thu) 18:54:29)
> 県の大きさはそれぞれ違うわけだから、972×1191って一番大きな県(北海道?)に
> 合わせてるんですよね?たぶん。
>
私は日本地図の大きさなのかと思った。


質問とは関係ないけど、そこは While よりは For ループを使ったほうが…。
引用返信 編集キー/
■45563 / inTopicNo.8)  Re[1]: Regionデータのバイナリデータ化について
□投稿者/ とっちゃん (448回)-(2010/01/14(Thu) 18:58:05)
とっちゃん さんの Web サイト
No45554 (にわか雨 さん) に返信
> 'imageを基にRegionを作成(imgファイルの黒以外のピクセルを透明にする関数)
> rgn(x) = CreateRegionFromImage(img(x), Color.White)
この CreateRegionFromImage というのは、自作ですか?
.NET Framework のメソッドにはこの名前のものはみあたりません。
CMFCToolBarImages に同名のものがありますが、VBからはどうやっても利用できないので関係ないし。。。


> バイナリファイルにする方法を教えていただけないでしょうか?
バイナリファイルにする方法は、たくボンさんが書いてますけど。。。復元できるのかな?ぱっと見出来そうには見えませんでしたけど。。。


ま、それはともかく、画面サイズ程度のリージョンを作るのに明らかにボトルネックといえる時間がかかるのは
なにか別の要因が働いているものと思います。
リージョンを作るデータが相当複雑だとしたらそれなりに時間がかかりますが。。。

あ。。。実行してるハードウェアのスペックはどの程度ですか?
リージョンはメモリを食うので、もしかしてスワップしてたりするんじゃ?
引用返信 編集キー/
■45564 / inTopicNo.9)  Re[5]: Regionデータのバイナリデータ化について
□投稿者/ .SHO (1125回)-(2010/01/14(Thu) 19:03:38)
No45562 (みきぬ さん) に返信

> 私は日本地図の大きさなのかと思った。

なるほど!そうなのかも。。。
だとしたら、相当無駄だわ…orz
引用返信 編集キー/
■45566 / inTopicNo.10)  Re[2]: Regionデータのバイナリデータ化について
□投稿者/ みきぬ (711回)-(2010/01/14(Thu) 19:13:38)
> バイナリファイルにする方法は、たくボンさんが書いてますけど。。。復元できるのかな?ぱっと見出来そうには見えませんでしたけど。。。
>
↓やり方まではわかんないけど、できそうだという情報源
http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200912/09120012.txt

あ、バイト列をファイルに読み書きするなら、File.WriteAllBytes() とか File.ReadAllBytes() を使うほうが楽かも。

> ま、それはともかく、画面サイズ程度のリージョンを作るのに明らかにボトルネックといえる時間がかかるのは
> なにか別の要因が働いているものと思います。
> リージョンを作るデータが相当複雑だとしたらそれなりに時間がかかりますが。。。
>
たぶん「imgファイルの黒以外のピクセルを透明にする」ところに時間がかかってるんじゃないかしら。


引用返信 編集キー/
■45567 / inTopicNo.11)  Re[3]: Regionデータのバイナリデータ化について
□投稿者/ たくボン (318回)-(2010/01/14(Thu) 19:56:11)
No45566 (みきぬ さん) に返信
>>バイナリファイルにする方法は、たくボンさんが書いてますけど。。。復元できるのかな?ぱっと見出来そうには見えませんでしたけど。。。
>>
> ↓やり方まではわかんないけど、できそうだという情報源
> http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200912/09120012.txt

うーん、復元はVBからだと難しいかも。
API使うって方法も選択肢の1つかも。

http://blog.livedoor.jp/junki560/archives/16573730.html

> たぶん「imgファイルの黒以外のピクセルを透明にする」ところに時間がかかってるんじゃないかしら。

これは俺もそう思う。
引用返信 編集キー/
■45568 / inTopicNo.12)  Re[4]: Regionデータのバイナリデータ化について
□投稿者/ にわか雨 (8回)-(2010/01/14(Thu) 20:54:14)
みなさんご返信ありがとうございます。

・Region作成時のビット走査はBitmapDataを使っています。

・972×1191は日本地図の大きさです。
 都道府県(47種類のbipmap)も同じ大きさを使っています。
 該当都道府県の部分のみ黒で塗って領域データを取得しています。

・そこは While よりは For ループを使ったほうが…
 ↑なぜですか!!?まさかForの方が早いとか。

・実行してるハードウェアのスペックはきっとそこまで関係ないと思われます。
 サーバ上でもXP上でも同じ速さでした。

・CreateRegionFromImageは自作です。というか他サイトから盗んできました^^
 コレに時間がかかっているのはたしかです。
 下記に記述致します。


------------------------------------------------------
Private Function CreateRegionFromImage(ByVal sourceImage As Bitmap, ByVal transparencyColor As Color) As Region

' 画像からリージョンを作成する
Dim imageBound As New Rectangle(0, 0, sourceImage.Width, sourceImage.Height)
Dim imageRegion As New Region

' リージョンを空領域にする
imageRegion.MakeEmpty()

' イメージを走査する
For y As Integer = imageBound.Y To imageBound.Height - 1

Dim opaqueBound As Rectangle = New Rectangle(0, y, 0, 1)
Dim isTransparentLast As Boolean = False
Dim isTransparentCurr As Boolean = False

For x As Integer = imageBound.X To imageBound.Width - 1
' 色を取得
Dim pixelColor As Color = sourceImage.GetPixel(x, y)
' 各コンポーネントが透過色と等しい場合、透過させる
isTransparentCurr = (transparencyColor.R = pixelColor.R) And (transparencyColor.G = pixelColor.G) And (transparencyColor.B = pixelColor.B)
' 現在の点を透過させる場合
If isTransparentCurr Then
' 直前の点を透過させるか
If isTransparentLast Then
' 透明領域のまま
Else
' 透明領域になった
If 0 < opaqueBound.Width Then imageRegion.Union(opaqueBound)
End If

Else
' 直前の点を透過させるか
If isTransparentLast Then
' 不透明領域になった
opaqueBound.X = x
opaqueBound.Width = 1
Else
' 不透明領域のまま
opaqueBound.Width = x - opaqueBound.X + 1
End If
End If

' 現在の状態を保存
isTransparentLast = isTransparentCurr

Next x
' 最後の点が不透明領域だった場合
If Not isTransparentLast AndAlso Not isTransparentCurr Then imageRegion.Union(opaqueBound)
Next y
Return imageRegion

End Function
------------------------------------------------------
とりあえずたくボンさんの方法であたってみます。
何か他に情報ありましたらお願いします。

今この関数を一つの県が通るのに2秒ほどかかります。
47×2で100秒ほどかかってしまうのですが
これはもしかして「ものすごく遅」くはない??ですか・・まさかの
引用返信 編集キー/
■45569 / inTopicNo.13)  Re[4]: Regionデータのバイナリデータ化について
□投稿者/ .SHO (1126回)-(2010/01/14(Thu) 20:55:53)
保存は、

1.GetRegionData()で、RegionDataを取得
2.RegionData の Data プロパティからバイト配列を取得
3.バイト配列をファイルに保存

復元は、ファイルからバイト配列を読み込んで RegionData を作成し
Region作成時のコンストラクタに渡してやる。

これで、出来そうな気がします。(未確認)

引用返信 編集キー/
■45575 / inTopicNo.14)  Re[5]: Regionデータのバイナリデータ化について
□投稿者/ みきぬ (712回)-(2010/01/14(Thu) 22:54:06)
2010/01/17(Sun) 15:13:31 編集(投稿者)
ところで、画像の加工はフリーソフトとか使ってやるのはだめ?
都道府県のところ以外をてきとーな1色で塗りつぶした画像ファイルを用意すれば、
その部分を透明にするのは↓の方法でできそう。
http://www.atmarkit.co.jp/fdotnet/dotnettips/602bmpmaketransparent/bmpmaketransparent.htmlNo45568 (にわか雨 さん) に返信
> ・そこは While よりは For ループを使ったほうが…
>  ↑なぜですか!!?まさかForの方が早いとか。
> 
んなこたーないけど、

x = 0
While x < 47
    ' ...
    x = x + 1
End While

よりも

For x = 0 To 46
    ' ...
Next

のがわかりやすくない?

-----
ループの終了条件の数値を間違えていたので、こっそり修正。

引用返信 編集キー/
■45584 / inTopicNo.15)  Re[6]: Regionデータのバイナリデータ化について
□投稿者/ .SHO (1127回)-(2010/01/15(Fri) 08:23:13)
> ところで、画像の加工はフリーソフトとか使ってやるのはだめ?
> 都道府県のところ以外をてきとーな1色で塗りつぶした画像ファイルを用意すれば、
> その部分を透明にするのは↓の方法でできそう。
> http://www.atmarkit.co.jp/fdotnet/dotnettips/602bmpmaketransparent/bmpmaketransparent.html

やり方はともかく、私もリージョン保存の手段を取るよりも
別の高速化の手段を検討した方がいいと思いますね。

CreateRegionFromImageは、汎用的に複雑な図形にも対応可能に
出来てるので重すぎる。

すべての県に対して日本地図全体の大きさの画像を持つのも無駄。
これじゃぁ、描画する時も重くないですか?
引用返信 編集キー/
■45585 / inTopicNo.16)  Re[5]: Regionデータのバイナリデータ化について
□投稿者/ たくボン (319回)-(2010/01/15(Fri) 09:29:22)
No45569 (.SHO さん) に返信
> 復元は、ファイルからバイト配列を読み込んで RegionData を作成し
> Region作成時のコンストラクタに渡してやる。
>
> これで、出来そうな気がします。(未確認)

すっかりRegionのコンストラクタ見てなかったです。今、確認したら復元できました。
ただ、読込時のファイルサイズで気になる部分があったのでわかったら書き込みします。

でも、とりあえずGetPixelをやめてBitmapData、色の比較の条件式を変更すれば高速になると思う。
引用返信 編集キー/
■45586 / inTopicNo.17)  Re[7]: Regionデータのバイナリデータ化について
□投稿者/ なちゃ (352回)-(2010/01/15(Fri) 09:31:55)
とりあえずGetPixel止めるだけでもかなり変わるかも。

引用返信 編集キー/
■45588 / inTopicNo.18)  Re[8]: Regionデータのバイナリデータ化について
□投稿者/ たくボン (320回)-(2010/01/15(Fri) 09:47:01)
No45586 (なちゃ さん) に返信
> とりあえずGetPixel止めるだけでもかなり変わるかも。

かなり劇的に変わると思うなぁ。GetPixelとかは遅くて使い物にならないし。

あと復元の時はこんな感じになった。

ちょっとRegionDataを作成する時に一旦別のRegionのRegionDataを割り当ててるけど、この辺は確実な資料が見当たらなかったんでMSの資料でやってたような一旦別Regionを割り当ててやってみてる。(いらん処理かもしれんけど)

Dim rgn As New Region
Dim rgndat As RegionData
Using fs As New FileStream("C:\temp\hoge.obj", FileMode.Open, FileAccess.Read)
    Dim buf(fs.Length - 1) As Byte
    fs.Read(buf, 0, buf.Length)
    rgndat = rgn.GetRegionData
    rgndat.Data = buf
End Using
Dim rgn2 As New Region(rgndat)
Me.Region = rgn2

引用返信 編集キー/
■45592 / inTopicNo.19)  Re[9]: Regionデータのバイナリデータ化について
□投稿者/ にわか雨 (9回)-(2010/01/15(Fri) 12:24:09)
No45588 (たくボン さん) に返信
> ■No45586 (なちゃ さん) に返信
>>とりあえずGetPixel止めるだけでもかなり変わるかも。
>
> かなり劇的に変わると思うなぁ。GetPixelとかは遅くて使い物にならないし。
>
> あと復元の時はこんな感じになった。
>
> ちょっとRegionDataを作成する時に一旦別のRegionのRegionDataを割り当ててるけど、この辺は確実な資料が見当たらなかったんでMSの資料でやってたような一旦別Regionを割り当ててやってみてる。(いらん処理かもしれんけど)
>
> Dim rgn As New Region
> Dim rgndat As RegionData
> Using fs As New FileStream("C:\temp\hoge.obj", FileMode.Open, FileAccess.Read)
> Dim buf(fs.Length - 1) As Byte
> fs.Read(buf, 0, buf.Length)
> rgndat = rgn.GetRegionData
> rgndat.Data = buf
> End Using
> Dim rgn2 As New Region(rgndat)
> Me.Region = rgn2


みなさんありがとうございます!!!
たくボンさんの方法で記述したところRegiondataのファイル化と復元に成功しました☆
表示スピードは100秒以上から3秒以内になりました。

本当にありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -