質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Kinect

Kinect(キネクト)はマイクロソフトから発売されたジェスチャー・音声認識によって 操作ができるデバイスです。

Q&A

解決済

1回答

1021閲覧

KINECTから得られたビットマップのデータを、保存したいです

keisuke1995

総合スコア16

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Kinect

Kinect(キネクト)はマイクロソフトから発売されたジェスチャー・音声認識によって 操作ができるデバイスです。

0グッド

0クリップ

投稿2018/02/19 09:03

以下のように、KINECTから深度画像とRGB画像を取得するプログラムを作成しました。
imageRgb.Sourceと、imageDepth.Sourceがビットマップ型の画像データなのですが、どうすれば保存できるのかが知りたいです。よろしくお願いいたします。

C#

1using System; 2using System.Diagnostics; 3using System.IO; 4using System.Threading; 5using System.Windows; 6using System.Windows.Media; 7using System.Windows.Media.Imaging; 8using System.Windows.Shapes; 9using System.Collections.Generic; 10using System.Drawing; 11using System.Linq; 12using System.Text; 13using System.Threading.Tasks; 14using System.Windows.Controls; 15using System.Windows.Data; 16using System.Windows.Documents; 17using System.Windows.Input; 18using System.Windows.Navigation; 19using OpenCvSharp; 20using OpenCvSharp.Extensions; 21 22using Microsoft.Kinect; 23 24namespace KINECT_depth 25{ 26 /// <summary> 27 /// MainWindow.xaml の相互作用ロジック 28 /// </summary> 29 public partial class MainWindow : Window 30 { 31 32 33 /// <summary> 34 /// コンストラクタ 35 /// </summary> 36 public MainWindow() 37 { 38 try 39 { 40 InitializeComponent(); 41 42 // Kinectが接続されているかどうかを確認する 43 if (KinectSensor.KinectSensors.Count == 0) 44 { 45 throw new Exception("Kinectを接続してください"); 46 } 47 48 // Kinectの動作を開始する 49 StartKinect(KinectSensor.KinectSensors[0]); 50 51 52 } 53 catch (Exception ex) 54 { 55 MessageBox.Show(ex.Message); 56 Close(); 57 } 58 } 59 60 61 62 /// <summary> 63 /// Kinectの動作を開始する 64 /// </summary> 65 /// <param name="kinect"></param> 66 private void StartKinect(KinectSensor kinect) 67 { 68 // RGBカメラを有効にして、フレーム更新イベントを登録する 69 kinect.ColorStream.Enable(); 70 kinect.ColorFrameReady += 71 new EventHandler<ColorImageFrameReadyEventArgs>(kinect_ColorFrameReady); 72 73 // 距離カメラを有効にして、フレーム更新イベントを登録する 74 kinect.DepthStream.Enable(); 75 kinect.DepthFrameReady += 76 new EventHandler<DepthImageFrameReadyEventArgs>(kinect_DepthFrameReady); 77 78 // Kinectの動作を開始する 79 kinect.Start(); 80 81 // defaultモードとnearモードの切り替え 82 comboBoxRange.Items.Clear(); 83 foreach (var range in Enum.GetValues(typeof(DepthRange))) 84 { 85 comboBoxRange.Items.Add(range.ToString()); 86 } 87 88 comboBoxRange.SelectedIndex = 0; 89 } 90 91 /// <summary> 92 /// Kinectの動作を停止する 93 /// </summary> 94 /// <param name="kinect"></param> 95 private void StopKinect(KinectSensor kinect) 96 { 97 if (kinect != null) 98 { 99 if (kinect.IsRunning) 100 { 101 // フレーム更新イベントを削除する 102 kinect.ColorFrameReady -= kinect_ColorFrameReady; 103 kinect.DepthFrameReady -= kinect_DepthFrameReady; 104 105 // Kinectの停止と、ネイティブリソースを解放する 106 kinect.Stop(); 107 kinect.Dispose(); 108 109 imageRgb.Source = null; 110 imageDepth.Source = null; 111 } 112 } 113 } 114 115 /// <summary> 116 /// RGBカメラのフレーム更新イベント 117 /// </summary> 118 /// <param name="sender"></param> 119 /// <param name="e"></param> 120 void kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e) 121 { 122 try 123 { 124 // RGBカメラのフレームデータを取得する 125 using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) 126 { 127 if (colorFrame != null) 128 { 129 // RGBカメラのピクセルデータを取得する 130 byte[] colorPixel = new byte[colorFrame.PixelDataLength]; 131 colorFrame.CopyPixelDataTo(colorPixel); 132 133 // ピクセルデータをビットマップに変換する 134 imageRgb.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96, 135 PixelFormats.Bgr32, null, colorPixel, colorFrame.Width * colorFrame.BytesPerPixel); 136 137 } 138 } 139 } 140 catch (Exception ex) 141 { 142 MessageBox.Show(ex.Message); 143 } 144 } 145 146 /// <summary> 147 /// 距離カメラのフレーム更新イベント 148 /// </summary> 149 /// <param name="sender"></param> 150 /// <param name="e"></param> 151 readonly int Bgr32BytesPerPixel = PixelFormats.Bgr32.BitsPerPixel / 8; 152 153 void kinect_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e) 154 { 155 try 156 { 157 // Kinectのインスタンスを取得する 158 KinectSensor kinect = sender as KinectSensor; 159 if (kinect == null) 160 { 161 return; 162 } 163 164 // 距離カメラのフレームデータを取得する 165 using (DepthImageFrame depthFrame = e.OpenDepthImageFrame()) 166 { 167 if (depthFrame != null) 168 { 169 // 距離データを画像化して表示 170 imageDepth.Source = BitmapSource.Create(depthFrame.Width, 171 depthFrame.Height, 96, 96, PixelFormats.Bgr32, null, 172 ConvertDepthColor(kinect, depthFrame), 173 depthFrame.Width * Bgr32BytesPerPixel); 174 } 175 } 176 } 177 catch (Exception ex) 178 { 179 MessageBox.Show(ex.Message); 180 } 181 } 182 183 /// <summary> 184 /// 距離データをカラー画像に変換する 185 /// </summary> 186 /// <param name="kinect"></param> 187 /// <param name="depthFrame"></param> 188 /// <returns></returns> 189 private byte[] ConvertDepthColor(KinectSensor kinect, 190 DepthImageFrame depthFrame) 191 { 192 ColorImageStream colorStream = kinect.ColorStream; 193 DepthImageStream depthStream = kinect.DepthStream; 194 195 // 距離カメラのピクセルごとのデータを取得する 196 short[] depthPixel = new short[depthFrame.PixelDataLength]; 197 depthFrame.CopyPixelDataTo(depthPixel); 198 199 // 距離カメラの座標に対応するRGBカメラの座標を取得する(座標合わせ) 200 ColorImagePoint[] colorPoint = 201 new ColorImagePoint[depthFrame.PixelDataLength]; 202 kinect.MapDepthFrameToColorFrame(depthStream.Format, depthPixel, 203 colorStream.Format, colorPoint); 204 205 byte[] depthColor = new byte[depthFrame.PixelDataLength * Bgr32BytesPerPixel]; 206 for (int index = 0; index < depthPixel.Length; index++) 207 { 208 // 距離カメラのデータから、距離を取得する 209 int distance = depthPixel[index] >> DepthImageFrame.PlayerIndexBitmaskWidth; 210 211 // 変換した結果が、フレームサイズを超えることがあるため、小さいほうを使う 212 int x = Math.Min(colorPoint[index].X, colorStream.FrameWidth - 1); 213 int y = Math.Min(colorPoint[index].Y, colorStream.FrameHeight - 1); 214 215 // 動作が遅くなる場合、MapDepthFrameToColorFrame を外すと速くなる場合が 216 // あります。外す場合のx,yはこちらを使用してください。 217 //int x = index % depthFrame.Width; 218 //int y = index / depthFrame.Width; 219 220 int colorIndex = ((y * depthFrame.Width) + x) * Bgr32BytesPerPixel; 221 222 // 対象より遠ければ色付け 223 if (distance >= 500) 224 { 225 depthColor[colorIndex] = 0; 226 depthColor[colorIndex + 1] = 0; 227 depthColor[colorIndex + 2] = 255; 228 } 229 else 230 { 231 depthColor[colorIndex] = 0; 232 depthColor[colorIndex + 1] = 0; 233 depthColor[colorIndex + 2] = 0; 234 } 235 236 } 237 238 return depthColor; 239 } 240 241 /// <summary> 242 /// 距離カメラの通常/近接モード変更イベント 243 /// </summary> 244 /// <param name="sender"></param> 245 /// <param name="e"></param> 246 private void comboBoxRange_SelectionChanged(object sender, 247 System.Windows.Controls.SelectionChangedEventArgs e) 248 { 249 try 250 { 251 KinectSensor.KinectSensors[0].DepthStream.Range = 252 (DepthRange)comboBoxRange.SelectedIndex; 253 } 254 catch (Exception) 255 { 256 comboBoxRange.SelectedIndex = 0; 257 } 258 } 259 260 261 /// <summary> 262 /// Windowsが閉じられるときのイベント 263 /// </summary> 264 /// <param name="sender"></param> 265 /// <param name="e"></param> 266 private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 267 { 268 StopKinect(KinectSensor.KinectSensors[0]); 269 } 270 } 271} 272

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

BitmapEncoderはどうでしょうか。変換してFileStreamで保存します。
こちらのページが参考になるかもしれません。
C#で描いた画像をファイルに保存してみた
BitmapSourceクラスをbitmapとして保存する
MSDN

投稿2018/02/20 02:47

編集2018/02/20 04:44
ooa

総合スコア213

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keisuke1995

2018/02/20 19:05

回答ありがとうございます。参考にしたサイトによると、 // BitmapSourceを保存する using (Stream stream = new FileStream("test.png", FileMode.Create)) { PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(imageDepth.Source)); encoder.Save(stream); } を // 距離データを画像化して表示 imageDepth.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, 96, 96, PixelFormats.Bgr32, null, ConvertDepthColor(kinect, depthFrame), depthFrame.Width * Bgr32BytesPerPixel); の下に追加することになりますかね?
ooa

2018/02/21 01:43

そこですとDepthFrameReadyのイベント発火のたびに保存されるので (そういう意図ならいいのですが) 保存したいタイミング(キーを押すなど)でやったほうがいいのではないかと思います。
keisuke1995

2018/02/22 06:41

すいません。できませんでした。 「System.Windows.Media.ImageSourceからSystem.Uriへ変換することはできません。」というエラーが出ます。
keisuke1995

2018/02/22 06:58

解決しました! encoder.Frames.Add(BitmapFrame.Create(imageDepth.Source));ではなく、 encoder.Frames.Add(BitmapFrame.Create((BitmapSource)imageDepth.Source));とするべきでした。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問