PowerShellからLucene.netを使ってみる

| 2009年11月17日火曜日
@ITのこの記事を見て使ってみたくなったのでさわってみた。
お試しなので単純にできるように、テキストファイル限定で中身を全文検索してファイル名を返すようにしようと思う。

まずは、DLLをダウンロードしてくる。場所は記事に書かれているところから飛べるのでそこから落としてくる。
落としてくるのは、Lucene.Netと記事の筆者が作成された日本語用のDLLがあるのでそちらも落としてる。

記事ではLucene.Net.Analysys.Ja.JapaneseAnalyereを使用しているけど、TokenStreamメソッドを使おうとすると下の例外が出て使えなかった。

"2" 個の引数を指定して "TokenStream" を呼び出し中に例外が発生しました: "保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。"
発生場所 行:1 文字:37
+ $tokenStream = $analyzer.TokenStream <<<< ("",$stringReader)
+ CategoryInfo : NotSpecified: (:) []、MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodTargetInvocation

できればJapaneseAnalyereを使って見たかったがしかたがない。今回はLuceneで全文検索をすることが目的なので、代わりにLucene.Net.Analysis.CJK.CJKAnalyzerの方を使う。
今度時間のある時に調べてみよう。N-gramより形態素解析の方が面白そうだからね。

Lucene.netを試してる時に、PowerShellからDLLのインナークラスの使い方がわからなかった。
「Lucene.Net.Documents.Field.Store.YES」と「Lucene.Net.Documents.Field.Index.TOKENIZED」は、ソースをみる限りでは、Lucene.Net.Documents.Fieldクラスのインナークラスみたいだけど、.(ドット)でつないだのではアクセスできなかった。
例外を出してその内容からわかった使い方は以下

[Lucene.Net.Documents.Field+Store]::YES
[Lucene.Net.Documents.Field+Index]::TOKENIZED

+(プラス)ってなんだ??
よくわからんが、インナークラスを使う時は+(プラス)でつなげるようだ。
一応、小さいインナークラスのDLLを作って試したけど、どうやらそうらしい。
しかし、これはildasmでDLLをみてもぱっと見わかんないな。
まぁDLLを読み込んだあとならPowerShellのTab補完が効くか効かないかで判断できるけど…in Actionに載ってたかなぁ…?

自分の試したサンプル下に貼っておく。
サンプルを実行するのに必要なDLLは下の二つなので、適当なフォルダにコピーしておく。

・Lucene.Net.dll
・Lucene.Net.Analysis.CJK.dll

そのフォルダに移動してから、サンプルをコピー&ペーストしてPowerShellに読み込ませる。
(たぶん、単純にコピーすると行番号までついてくるのでメモ帳にでも貼って番号を削除してからコピーして貼り付ければいい)

使い方は、

インデックスフォルダとインデックスファイルのベースの作成する。
> Create-LuceneIndex -IndexPath C:\LuceneIndex

インデックスファイルに指定したファイルを追加する。インデックスに追加されるのは、ファイル名(フルパス)とテキストファイルの中身。
追加するファイルを渡す引数の型は「System.IO.FileInfo」なので、「ls」の結果を変数に詰めて渡すか。フルパスを書く必要がある。
> Add-LuceneDocument -IndexPath C:\LuceneIndex -file c:\hoge\foo.txt

検索する。ファイルのフルパスが返ってくる。
> Find-LuceneDocument -IndexPath C:\LuceneIndex -word foo

インデックスを削除する。
> Remove-LuceneDocument -IndexPath C:\LuceneIndex -file c:\hoge\foo.txt

他にも追加と削除を組み合わせて更新用の関数なんかもあれば便利だと思う。
このサンプルのままで日本語も検索できるから、あと実際の業務で使おうと思ったら、クローラとOffice系のファイルの読み込みが必要かな。
Office系のファイルの読み込みならAdd-LuceneDocument関数内の

$contents = Get-Content $file

の部分を変更して、xDoc2txtなどを使う必要があると思う。
まぁPowerShellならクローラは簡単だと思うし、拡張子を見て$contentに入れる中身を変えるのも難しくないだろう。

ちょっと長いけど、サンプル↓
  1. [void][System.Reflection.Assembly]::LoadFrom((Join-Path $pwd Lucene.Net.dll))
  2. [void][System.Reflection.Assembly]::LoadFrom((Join-Path $pwd Lucene.Net.Analysis.CJK.dll))
  3. # 元となるインデックスを作成する
  4. function Create-LuceneIndex([string]$indexPath) {
  5. # インデックスが存在した場合はフォルダを削除して作り直す
  6. if (Test-Path $indexPath) {
  7. if ([Lucene.Net.Index.IndexReader]::IndexExists($indexPath)) {
  8. [void][System.IO.Directory]::Delete($indexPath, $true)
  9. [void][System.IO.Directory]::CreateDirectory($indexPath)
  10. }
  11. }
  12. $indexWriter = New-Object Lucene.Net.Index.IndexWriter($indexPath, ( New-Object Lucene.Net.Analysis.CJK.CJKAnalyzer ), $true)
  13. $indexWriter.Close()
  14. }
  15. # インデックスにファイルを追加する
  16. function Add-LuceneDocument([string]$indexPath, [System.IO.FileInfo]$file) {
  17. # Documentオブジェクトの作成
  18. $document = New-Object Lucene.Net.Documents.Document
  19. # Fieldオブジェクトの作成
  20. $fileName = $file.FullName
  21. $contents = Get-Content $file
  22. $fieldFileName = New-Object Lucene.Net.Documents.Field("filename", $fileName, [Lucene.Net.Documents.Field+Store]::YES, [Lucene.Net.Documents.Field+Index]::TOKENIZED)
  23. $fieldContents = New-Object Lucene.Net.Documents.Field("contents", $contents, [Lucene.Net.Documents.Field+Store]::YES, [Lucene.Net.Documents.Field+Index]::TOKENIZED)
  24. # Documentオブジェクトにフィールドを追加
  25. $document.Add($fieldFileName)
  26. $document.Add($fieldContents)
  27. $indexWriter = New-Object Lucene.Net.Index.IndexWriter($indexPath, ( New-Object Lucene.Net.Analysis.CJK.CJKAnalyzer ), $false)
  28. # インデックスにDocumentオブジェクトを追加
  29. $indexWriter.AddDocument($document)
  30. # インデックスを最適化する
  31. $indexWriter.Optimize()
  32. $indexWriter.Close()
  33. }
  34. # インデックスからファイルを削除する
  35. function Remove-LuceneDocument([string]$indexPath, [System.IO.FileInfo]$file) {
  36. # アナライザの準備
  37. $analyzer = New-Object Lucene.Net.Analysis.CJK.CJKAnalyzer
  38. # ファイル名を対象にクエリを作成
  39. $queryPsr = New-Object Lucene.Net.QueryParsers.QueryParser("filename", $analyzer)
  40. $word = $file.Name
  41. $query = $queryPsr.Parse($word)
  42. # インデックスからヒットするものを探す
  43. $searcher = New-Object Lucene.Net.Search.IndexSearcher($indexPath)
  44. $hits = $searcher.Search($query)
  45. $target = $file.FullName
  46. # ヒットしたものをインデックスから削除する
  47. $indexReader = [Lucene.Net.Index.indexReader]::Open($indexPath)
  48. for ($i = 0; $i -lt $hits.Length(); $i++) {
  49. $doc = $hits.Doc($i)
  50. # ファイルのフルパスと一致するものだけを削除する
  51. if ($doc.Get("filename") -eq $target) {
  52. $indexReader.DeleteDocument($hits.Id($i))
  53. }
  54. }
  55. $indexReader.Close()
  56. }
  57. # インデックスから検索する
  58. function Find-LuceneDocument([string]$indexPath, [string]$word) {
  59. # アナライザの準備
  60. $analyzer = New-Object Lucene.Net.Analysis.CJK.CJKAnalyzer
  61. # ファイルの中身を対象にクエリを作成
  62. $queryPsr = New-Object Lucene.Net.QueryParsers.QueryParser("contents", $analyzer)
  63. $query = $queryPsr.Parse($word)
  64. # インデックスからヒットするものを探す
  65. $searcher = New-Object Lucene.Net.Search.IndexSearcher($indexPath)
  66. $hits = $searcher.Search($query)
  67. # Lucene.Net.Documents.Documentの配列を作成してヒットしたものを詰める
  68. [Lucene.Net.Documents.Document[]]$docments = New-Object Lucene.Net.Documents.Document[]($hits.Length())
  69. for ($i = 0; $i -lt $hits.Length(); $i++) {
  70. $docments[$i] = $hits.Doc($i)
  71. }
  72. return ($docments | % { $_.Get("filename") })
  73. }

PowerShellで動画の輪郭検出をしてみる

| 2009年11月14日土曜日
OpenCVSharpを使用してWebカメラから動画をキャプチャーしながら輪郭検出をしてみる。
静止画と同じではつまらないので、円の中の4点を赤色にして、その4点の座標を緑の字でウィンドウ上に表示させてみる。
  1. [void][System.Reflection.Assembly]::LoadFrom((Join-Path $pwd OpenCvSharp.dll))
  2. $camera = [OpenCvSharp.CvCapture]::FromCamera(0)
  3. $window = New-Object OpenCvSharp.CvWindow("SampleCapture")
  4. $threshold = 128 # 白色か黒色かのしきい値
  5. $smooth = 5 # 値が大きいほどぼかしが強い
  6. $font = New-Object OpenCvSharp.CvFont([OpenCvSharp.FontFace]::HersheyComplex, 0.7, 0.7)
  7. $point1 = New-Object OpenCvSharp.CvPoint(10,20)
  8. $point25 = New-Object OpenCvSharp.CvPoint(10,45)
  9. $point50 = New-Object OpenCvSharp.CvPoint(10,70)
  10. $point75 = New-Object OpenCvSharp.CvPoint(10,95)
  11. $colorString = [OpenCvSharp.CvColor]::Green
  12. $colorPoint = [OpenCvSharp.CvColor]::Red
  13. $colorLine = [OpenCvSharp.CvColor]::Blue
  14. $size = New-Object OpenCvSharp.CvSize(15, 15)
  15. # この値が大きいほど輪郭が狭まる
  16. $tremCriteria = New-Object OpenCvSharp.CvTermCriteria(300)
  17. $alpha = [System.Single]0.45
  18. $beta = [System.Single]0.35
  19. $gamma = [System.Single]0.2
  20. $srcSize = New-Object OpenCvSharp.CvSize($camera.FrameWidth, $camera.FrameHeight)
  21. $srcIplImage = New-Object OpenCvSharp.IplImage( $srcSize, [OpenCvSharp.BitDepth]::U8, 1)
  22. $dstIplImage = New-Object OpenCvSharp.IplImage( $srcSize, [OpenCvSharp.BitDepth]::U8, 1)
  23. # ポイントを配列で初期化 全部ゼロで初期化される
  24. [OpenCvSharp.CvPoint[]]$contour = New-Object OpenCvSharp.CvPoint[](100)
  25. # ウィンドウの中心点を取得
  26. $center = New-Object OpenCvSharp.CvPoint(($srcSize.Width / 2), ($srcSize.Height / 2))
  27. while ( [OpenCvSharp.CvWindow]::WaitKey(10) -lt 0 ) {
  28. $iplImage = $camera.QueryFrame()
  29. # 中心点を元にポイントの初期値を設定
  30. for ($i = 0; $i -lt $contour.Length; $i++) {
  31. $x = [int]($center.X * [System.Math]::Cos(2 * [System.Math]::PI * $i / $contour.Length) + $center.X)
  32. $y = [int]($center.Y * [System.Math]::Sin(2 * [System.Math]::PI * $i / $contour.Length) + $center.Y)
  33. $p = New-Object OpenCvSharp.CvPoint($x, $y)
  34. $contour.Set($i, $p)
  35. }
  36. # グレースケールに変換
  37. [OpenCvSharp.Cv]::CvtColor($iplImage, $srcIplImage, [OpenCvSharp.ColorConversion]::BgraToGray)
  38. # ぼかす
  39. $srcIplImage.Smooth($srcIplImage, [OpenCvSharp.SmoothType]::Blur, $smooth)
  40. # 二値化
  41. $srcIplImage.Threshold($dstIplImage, $threshold, 255, [OpenCvSharp.ThresholdType]::Binary)
  42. # 領域検知
  43. $dstIplImage.SnakeImage($contour, $alpha, $beta, $gamma, $size, $tremCriteria, $true)
  44. # 領域中の4点の座標を取得
  45. $str1 = [String]::Format("1 : (x = {0}, y = {1})", $contour.Get(1).X, $contour.Get(1).Y)
  46. $str25 = [String]::Format("25 : (x = {0}, y = {1})", $contour.Get(25).X, $contour.Get(25).Y)
  47. $str50 = [String]::Format("50 : (x = {0}, y = {1})", $contour.Get(50).X, $contour.Get(50).Y)
  48. $str75 = [String]::Format("75 : (x = {0}, y = {1})", $contour.Get(75).X, $contour.Get(75).Y)
  49. # ポイントを線で結んで描写
  50. for ($i = 0; $i -lt ($contour.Length - 1); $i++) {
  51. # 選んだ4点だけ 赤 それ以外は 青
  52. if ($i -eq 1 -or $i -eq 25 -or $i -eq 50 -or $i -eq 75) {
  53. $iplImage.Line($contour[$i], $contour[($i + 1)], $colorPoint, 6)
  54. } else {
  55. $iplImage.Line($contour[$i], $contour[($i + 1)], $colorLine, 3)
  56. }
  57. }
  58. # 最初の点と最後の点を結ぶ
  59. $iplImage.Line($contour[($contour.Length -1)], $contour[0], $colorLine, 3)
  60. # 座標をウィンドウに描写
  61. $iplImage.PutText($str1, $point1, $font, $colorString)
  62. $iplImage.PutText($str25, $point25, $font, $colorString)
  63. $iplImage.PutText($str50, $point50, $font, $colorString)
  64. $iplImage.PutText($str75, $point75, $font, $colorString)
  65. $window.Image = $iplImage
  66. # 連続でループするとCPUをたくさん喰うので3秒間をあける
  67. Start-Sleep 3
  68. }
  69. $iplImage.Dispose()
  70. $srcIplImage.Dispose()
  71. $dstIplImage.Dispose()
  72. $window.Dispose()
  73. $camera.Dispose()

PowerShellで静止画の輪郭検出をしてみる

|
OpenCVSharpを使用して画像の中の輪郭?色の境界?を検出する。
処理のイメージは、画像の中心からいっぱいに一つの丸を描いて輪郭が出てくるまで徐々に狭めていく。
どれくらいまで敏感に輪郭に反応するかは、

$tremCriteria = New-Object OpenCvSharp.CvTermCriteria(270)

の値を大きくすれば、よりはっきりと囲まれる。
  1. [void][System.Reflection.Assembly]::LoadFrom((Join-Path $pwd OpenCvSharp.dll))
  2. # グレースケールで読み込む
  3. $srcIplImage = [OpenCvSharp.Cv]::LoadImage((Join-Path $pwd "src.jpg"), [OpenCvSharp.LoadMode]::GrayScale)
  4. $dstIplImage = New-Object OpenCvSharp.IplImage($srcIplImage.Size, [OpenCvSharp.BitDepth]::U8, 3)
  5. [OpenCvSharp.CvPoint[]]$contour = New-Object OpenCvSharp.CvPoint[] 100
  6. # 中心点
  7. $center = New-Object OpenCvSharp.CvPoint(($srcIplImage.Width / 2), ($srcIplImage.Height / 2))
  8. # 全体をかこむ丸を作る
  9. for ($i = 0; $i -lt $contour.Length; $i++) {
  10. $contour[$i] = New-Object OpenCvSharp.CvPoint([int]($center.X * [System.Math]::Cos(2 * [System.Math]::PI * $i / $contour.Length) + $center.X), [int]($center.Y * [System.Math]::Sin(2 * [System.Math]::PI * $i / $contour.Length) + $center.Y))
  11. }
  12. $size = New-Object OpenCvSharp.CvSize(15, 15)
  13. $tremCriteria = New-Object OpenCvSharp.CvTermCriteria(270)
  14. $alpha = [System.Single]0.45
  15. $beta = [System.Single]0.35
  16. $gamma = [System.Single]0.2
  17. # 輪郭を検出
  18. $srcIplImage.SnakeImage($contour, $alpha, $beta, $gamma, $size, $tremCriteria, $true)
  19. [OpenCvSharp.Cv]::CvtColor($srcIplImage, $dstIplImage, [OpenCvSharp.ColorConversion]::GrayToRgb)
  20. # 赤で輪郭を描く
  21. $color = [OpenCvSharp.CvColor]::Red
  22. for ($i = 0; $i -lt ($contour.Length - 1); $i++) {
  23. $dstIplImage.Line($contour[$i], $contour[($i + 1)], $color, 2)
  24. }
  25. $dstIplImage.Line($contour[($contour.Length -1)], $contour[0], $color, 2)
  26. $dstIplImage.SaveImage((Join-Path $pwd "dst.jpg"))
  27. $srcIplImage.Dispose()
  28. $dstIplImage.Dispose()

PowerShellで動画の差分をとってみる

| 2009年11月13日金曜日
OpenCVSharpを使用してWebカメラからキャプチャーして、差分を動画で表示する。

処理は、静止画の時とほぼ同じ。
一応より差分を分かりやすくするためにぼかしを入れている。
  1. [void][System.Reflection.Assembly]::LoadFrom((Join-Path $pwd OpenCvSharp.dll))
  2. # カメラの情報を取得
  3. $camera = [OpenCvSharp.CvCapture]::FromCamera(0)
  4. $window = New-Object OpenCvSharp.CvWindow("SampleCapture")
  5. while ( [OpenCvSharp.CvWindow]::WaitKey(10) -lt 0 ) {
  6. $iplImage = $camera.QueryFrame()
  7. $srcIplImage = New-Object OpenCvSharp.IplImage( $iplImage.Size, [OpenCvSharp.BitDepth]::U8, 1)
  8. # グレースケールに変換
  9. [OpenCvSharp.Cv]::CvtColor($iplImage,$srcIplImage, [OpenCvSharp.ColorConversion]::BgraToGray)
  10. $dstIplImage1 = New-Object OpenCvSharp.IplImage( $srcIplImage.Size, [OpenCvSharp.BitDepth]::U8, 1)
  11. # ぼかし
  12. $srcIplImage.Smooth($srcIplImage, [OpenCvSharp.SmoothType]::Blur, 5)
  13. # 白黒に変換
  14. $srcIplImage.Threshold($dstIplImage1, 128, 255, [OpenCvSharp.ThresholdType]::Binary)
  15. # 差分出力先
  16. $dstIplImage2 = New-Object OpenCvSharp.IplImage($dstIplImage1.Size, $dstIplImage1.Depth, $dstIplImage1.NChannels)
  17. if ($tempIplImage -ne $null) {
  18. # 差分をとる
  19. [OpenCvSharp.Cv]::AbsDiff($dstIplImage1, $tempIplImage, $dstIplImage2)
  20. # 差分を表示する
  21. $window.Image = $dstIplImage2
  22. }
  23. # 今回の元データをTempに入れる
  24. $tempIplImage = $dstIplImage1
  25. }
  26. $iplImage.Dispose()
  27. $srcIplImage.Dispose()
  28. $dstIplImage1.Dispose()
  29. $dstIplImage2.Dispose()
  30. $tempIplImage.Dispose()
  31. $window.Dispose()
  32. $camera.Dispose()

PowerShellで静止画の差分をとる

|
OpenCVSharpを使用して二つの画像から差分をとって保存してみる。

同じ背景の画像を撮影して、一回目に撮ったものと二回目に撮ったものの差分をとる。
差分画像は、違う部分に色が付いていて、まったく同じ部分は黒で表示される。
ただ、それをそのまま見てもわかりにくかったので、二極化して白黒にした。
白黒にすると差分の部分だけが白くなるので見た目にわかりやすい。

ここでは、差分処理がどう動くのかを知りたかったので、差分画像を保存してから、それを読み込んで白黒にしてみた。
そのまま保存した画像と比較して見るとわかりやすいと思う。
  1. [void][System.Reflection.Assembly]::LoadFrom((Join-Path $pwd OpenCvSharp.dll))
  2. # 背景画像
  3. $srcIplImage1 = [OpenCvSharp.Cv]::LoadImage((Join-Path $pwd "a.jpg"))
  4. # 背景の前に何か写した画像
  5. $srcIplImage2 = [OpenCvSharp.Cv]::LoadImage((Join-Path $pwd "b.jpg"))
  6. # 差分出力先
  7. $dstIplImage1 = New-Object OpenCvSharp.IplImage($srcIplImage1.Size, $srcIplImage1.Depth, $srcIplImage1.NChannels)
  8. # 差分をとる
  9. [OpenCvSharp.Cv]::AbsDiff($srcIplImage1, $srcIplImage2, $dstIplImage1)
  10. # 差分の画像を保存 変わらなかったところは黒
  11. $dstIplImage1.SaveImage((Join-Path $pwd "c.jpg"))
  12. $srcIplImage1.Dispose()
  13. $srcIplImage2.Dispose()
  14. $dstIplImage1.Dispose()
  15. # 2極化して白黒にした方がわかりやすい
  16. # 差分の部分だけが白くなる
  17. $srcIplImage3 = [OpenCvSharp.Cv]::LoadImage( (Join-Path $pwd "c.jpg"), [OpenCvSharp.LoadMode]::GrayScale)
  18. $dstIplImage2 = New-Object OpenCvSharp.IplImage( $srcIplImage3.Size, $srcIplImage3.Depth, 1)
  19. $srcIplImage3.Threshold($dstIplImage2, 128, 255, [OpenCvSharp.ThresholdType]::Binary)
  20. $dstIplImage2.SaveImage((Join-Path $pwd "d.jpg"))
  21. $srcIplImage3.Dispose()
  22. $dstIplImage2.Dispose()

PowerShellでタスクトレイアイコンにバルーンウィンドウを表示してみる

| 2009年11月11日水曜日
PowerShellでタスクトレイアイコンにバルーンウィンドウを表示させる。
あんまり使うことはないかもしれないけど、PowerShell 2.0からはバックグラウンドで処理を実行できるようになったので、それの終了を知らせるのには役に立つかもしれない。

下のコードを「Show-BalloonTip.ps1」という名前でパスの通ったところにおいて

> Show-BalloonTip -title ジョブ -body 処理が終了しました。 -toolTipIcon Info

っと実行する。ToolTipIconは「Info」「Warning「Error「None」の4つのアイコン(なにも表示されないのも含めて)を表示させることができる。

表示時間を1ミリ秒にしているけど、うちの環境では1ミリ秒でも長いこと表示されっぱなしになってた(笑)

-- Show-BalloonTip.ps1 --
  1. param([int]$timeout = 1, [string]$tilte = "件名", [string]$body = "本文", [string]$toolTipIcon = "Info")
  2. [Void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
  3. $notifyIcon = New-Object System.Windows.Forms.NotifyIcon
  4. # PowerShell.exeからアイコンを抽出する System.Drawing.Icon型
  5. $powerShellExe = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
  6. $icon = [System.Drawing.Icon]::ExtractAssociatedIcon($powerShellExe)
  7. $notifyIcon.Icon = $icon
  8. $notifyIcon.Visible = $true
  9. # 引数は、 表示時間(ミリ秒) 件名 本文 件名の前のアイコン(System.Windows.Forms.ToolTipIcon列挙体)
  10. $notifyIcon.ShowBalloonTip($timeout, $tilte, $body, $toolTipIcon)

wgetの使い方メモ

| 2009年11月7日土曜日
テキストファイルに一行毎に書かれたURLで同じフォルダ内にないファイルを三秒間隔をあけてダウンロードする。

> wget -nc -nv -w 3 -t 1 -i list.txt

たまにうまくいかない時があったので、PowerShellを使って一個づつダウンロードする場合。

> cat list.txt | % { wget $_ }

PowerShellでHTMLファイルから画像のURLを取り出す

|
ワンライナーでできるのは便利。
なんとなく、もっと短くできそうな気がするけど、今の俺ではこの長さ。

正規表現の部分を変えれば、「zip」だけを返したりも出来る。ここでは、JPEG、GIF、PNG、BMPをマッチさせている。
抜きたかったHTMLでしかテストしてないから、上手くいかないサイトもあるかも。
  1. Get-Content foo.html | % { if ( $_ -match "http://.*\.(jpg|jpeg|gif|png|bmp)") { $Matches.Values | % { $_.Split("`"") | % { if ($_ -match "\.(jpg|jpeg|gif|png|bmp)") { return $_ }}}}}
ついでに、某大きな掲示板用
本文に”ttp://~~~/~~~”が普通なので、最初にばっさりHTMLのタグを消してしまってから処理している。
  1. (Get-Content foo.html) -replace "<.*?>","" | % { if ( $_ -match "ttp://.*\.(jpg|jpeg|gif|png|bmp)") { $Matches.values | % { $_.Split() | % { if ($_ -match "\.(jpg|jpeg|gif|png|bmp)") { return $_.Replace("ttp://","http://") }}}}}

PowerShellで画像の色をカウントする

| 2009年11月6日金曜日
OpenCVSharpを使用して画像の白、黒、赤、青、緑、黄色、マゼンタ、シアン、その他の色に該当する色を数えてみる。
下のコードには、その色に該当するかについて、あそびをまったく入れていないのでほとんどが、その他の色になってしまう。
けど、今回は、白黒画像をカウントする事が目的で、白と黒だけちゃんと取れればよかっただけなのでこれで良しとする。
今度、ある程度まともな条件で取得できるようにしよう。
あと、この方法だとかなり遅いので、なにか別な取得方法がないかについても調べておこう。
  1. [void][System.Reflection.Assembly]::LoadFrom((Join-Path $pwd OpenCvSharp.dll))
  2. $iplImage = [OpenCvSharp.Cv]::LoadImage((Join-Path $pwd "foo.jpg"))
  3. for ($x = 0; $x -lt $iplImage.Width; $x++) {
  4. for ($y = 0; $y -lt $iplImage.Height; $y++) {
  5. # CvColor型にキャスト
  6. $cvColor = [OpenCvSharp.CvColor]$iplImage.Get2D($y, $x)
  7. $count++
  8. switch ($cvColor) {
  9. {$_ -eq [OpenCvSharp.CvColor]::White} {
  10. $white++
  11. break
  12. }
  13. {$_ -eq [OpenCvSharp.CvColor]::Black} {
  14. $black++
  15. break
  16. }
  17. {$_ -eq [OpenCvSharp.CvColor]::Red} {
  18. $red++
  19. break
  20. }
  21. {$_ -eq [OpenCvSharp.CvColor]::Blue} {
  22. $blue++
  23. break
  24. }
  25. {$_ -eq [OpenCvSharp.CvColor]::Green} {
  26. $green++
  27. break
  28. }
  29. {$_ -eq [OpenCvSharp.CvColor]::Yellow} {
  30. $yellow++
  31. break
  32. }
  33. {$_ -eq [OpenCvSharp.CvColor]::Magenta} {
  34. $magenta++
  35. break
  36. }
  37. {$_ -eq [OpenCvSharp.CvColor]::Cyan} {
  38. $cyan++
  39. break
  40. }
  41. default {
  42. $other++
  43. }
  44. }
  45. }
  46. }
  47. Write-Host White = ($white / $count).ToString("00.0%")
  48. Write-Host Black = ($black / $count).ToString("00.0%")
  49. Write-Host Red = ($red / $count).ToString("00.0%")
  50. Write-Host Blue = ($blue / $count).ToString("00.0%")
  51. Write-Host Green = ($green / $count).ToString("00.0%")
  52. Write-Host Yellow = ($yellow / $count).ToString("00.0%")
  53. Write-Host Magenta = ($magenta / $count).ToString("00.0%")
  54. Write-Host Cyan = ($cyan / $count).ToString("00.0%")
  55. Write-Host Other = ($other / $count).ToString("00.0%")
  56. $iplImage.Dispose()