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()

0 コメント: