アプリ版:「スタンプのみでお礼する」機能のリリースについて

Visual C++のWindowsフォームアプリケーションで、Kinectの映像を録画したONI形式のファイルを再生し、そこから骨格情報を抽出しようと考えています。
ファイルを再生するまでは成功したのですが、骨格情報を抽出するコードを追加するとうまくいかなくなってしまいました。

button13をクリックするとONIファイルを読み込んで表示するようにします。以下にその部分のコードを示します。

System::Void Form1::button13_Click(System::Object^ sender, System::EventArgs^ e){
XnStatus nRetVal = XN_STATUS_OK;
int nType = 0; // ノードのタイプ
char* filePath; // ファイル名

// [ファイルを開く]ダイアログ
openFileDialog1->Filter = "ONIファイル(*.oni)|*.oni";
if (openFileDialog1->ShowDialog() != Windows::Forms::DialogResult::OK) {
return;
}
else {
// ファイル名を取得
filePath = (char*)Marshal::StringToHGlobalAnsi(openFileDialog1->FileName).ToPointer();
}

//----------
// Kinect初期化
context.Init();

// プレイヤーの作成
nRetVal = context.OpenFileRecording(filePath, player);
if (nRetVal != XN_STATUS_OK) {
MessageBox::Show("ファイルを開くことができません");
return;
}

// 再生終了コールバックを登録
XnCallbackHandle hCallback;
player.RegisterToEndOfFileReached(OnEndOfFileReached, NULL, hCallback);



//----------
// RGBカメラ
context.FindExistingNode(XN_NODE_TYPE_IMAGE, image);
if (image.IsValid() == true){
nType = 1;
}

// 奥行き情報
context.FindExistingNode(XN_NODE_TYPE_DEPTH, depth);
if (depth.IsValid() == true) {
nType = 2;
}
//ユーザー
context.FindExistingNode(XN_NODE_TYPE_USER, user);
if (user.IsValid() == true) {
nType = 3;
}

// ノードの確認
switch (nType){
case 1:
generator = image;
break;
case 2:
generator = depth;
break;
case 3:
generator = user;
break;
default:
MessageBox::Show("有効なノードが見つかりません");
return;
}

//ユーザー検出コールバック関数を登録
XnCallbackHandle hUserCallbacks;
user.RegisterUserCallbacks(
User_NewUser, User_LostUser, NULL, hUserCallbacks);

//ポーズ検出コールバック関数を登録
XnCallbackHandle hPoseCallbacks;
user.GetPoseDetectionCap().RegisterToPoseCallbacks(
Pose_Detected, NULL, NULL, hPoseCallbacks);

//キャリブレーションコールバック関数を登録
XnCallbackHandle hCalibrationCallbacks;
user.GetSkeletonCap().RegisterCalibrationCallbacks(
Calibration_Start, Calibration_End, NULL, hCalibrationCallbacks);

//全ての関節を有効に
user.GetSkeletonCap().SetSkeletonProfile(XN_SKEL_PROFILE_ALL);

//キャリブレーションポーズを取得
user.GetSkeletonCap().GetCalibrationPose(strPose);

//----------
// 全フレーム数を取得
XnUInt32 frames;
player.GetNumFrames(generator.GetName(), frames);

// テキストボックスとトラックバーの初期化
textBox1->Text = "0";
trackBar1->Minimum = 0;
trackBar1->Maximum = frames;
trackBar1->Value = 0;
lblframe->Text = frames.ToString();

// すべてのデータの更新を待つ
context.WaitAndUpdateAll();

// 1フレーム分の画像を表示
ShowOneFrame();
}



実行すると、

「'System.AccessViolationException' のハンドルされていない例外が発生しました。
追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。」

というエラーが出て終了してしまいます。調べてみるとユーザー検出コールバック関数を登録するところで止まってしまうようです。

ネットで原因を調べてみると、保護されているメモリにアクセスしたからであるとか、ポインタが間違っているのが原因であると書かれていますが、よく分かりません。

ONIにユーザー情報は入っていませんが、奥行き情報は入っており、それさえあれば骨格抽出はできるらしいのですが、ユーザーのジェネレーターを作る段階で問題があるのでしょうか。

どなたか原因が分かる人はいらっしゃいますでしょうか。ここで示したソースコードは全体の一部だけなので分かりにくいと思いますが、ご助言を伺いたいと思います。

よろしくお願いします。

A 回答 (1件)

昔、一度C++でプログラムを作ったのですが、全く動かず、あきらめました。


ですから、この書き込みは適当に読み流してください。
'System.AccessViolationException' のハンドルされていない例外が発生しました。
追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。」
で検索したらいっぱいヒットしたサイトが出てきましたけど。
たとえば、C#のようですが
http://bbs.wankuma.com/index.cgi?mode=al2&namber …
で、
> AccessViolationException が発生すると言うことは、本来、確保しておくべきメモリを確保していなかったり、足りなかったり、あるいは間違った渡し方をすることでその関数の実行に失敗するか、他のオブジェクトなどが使っているメモリを壊してしまうかという被害が発生します。
> 今回のケースでは StringBuilder にあらかじめ確保しておく文字列バッファ(260 文字ぐらい?)を用意していなかったため、別の場所のメモリが破壊され...
といった記述があります。
shoboyさんのプログラムは私にはさっぱりわからないので、どこが間違っているかはわかりませんが...

もっと詳しいことを求められているのでしたらごめんなさい。
    • good
    • 0
この回答へのお礼

私の場合、ユーザージェネレーターが作れていないのが原因だと思われます。あれからその部分のコードを変更したりしてみたのですが、うまくいかないようです。

情報ありがとうございました。

お礼日時:2015/09/01 16:52

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!