実現したいこと
・Unity内で360度カメラ THETA Z1を接続し、映像のリアルタイム画像処理を行いたい。
・画像処理にはOpenCVplusUnityを使用する。
前提
まず、THETAに接続して映像を表示するためコード
参考:(https://qiita.com/reiya_prog/items/b52be9adf7a82a89eae0 )に
OpenCVを使って画像データを透視投影変換するプログラムを追加し、
THETAでリアルタイム画像処理を行うためのテストスクリプトを作成しました。
このスクリプトを平面に追加し、Playボタンを押して実行しましたが、カメラ映像は表示されず、以下のエラーメッセージが表示されました。
ちなみに
OpenCVの画像処理のプログラムを付け加える前の元のスクリプトでは、映像は問題なく表示できております。
発生している問題・エラーメッセージ
エラーメッセージは以下の通りです。
C#
1OpenCVException: _src.total() > 0 2OpenCvSharp.NativeMethods+<>c.<.cctor>b__1286_0 (OpenCvSharp.ErrorCode status, System.String funcName, System.String errMsg, System.String fileName, System.Int32 line, System.IntPtr userdata) (at Assets/OpenCV+Unity/Assets/Scripts/OpenCvSharp/PInvoke/NativeMethods.cs:190) 3(wrapper native-to-managed) OpenCvSharp.NativeMethods+<>c.<.cctor>b__1286_0(OpenCvSharp.ErrorCode,intptr,intptr,intptr,int,intptr) 4OpenCvSharp.Cv2.WarpPerspective (OpenCvSharp.InputArray src, OpenCvSharp.OutputArray dst, OpenCvSharp.InputArray m, OpenCvSharp.Size dsize, OpenCvSharp.InterpolationFlags flags, OpenCvSharp.BorderTypes borderMode, System.Nullable`1[T] borderValue) (at Assets/OpenCV+Unity/Assets/Scripts/OpenCvSharp/Cv2/Cv2_imgproc.cs:984) 5LivePreview2+<GetLivePreview>d__2.MoveNext () (at Assets/Scripts/LivePreview2.cs:78) 6UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at <86acb61e0d2b4b36bc20af11093be9a5>:0) 7UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) 8LivePreview2:Start() (at Assets/Scripts/LivePreview2.cs:13) 9
該当のソースコード
スクリプト名:LivePreview2
C#
1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using System.Net; 5using System.IO; 6using OpenCvSharp; 7 8public class LivePreview2 : MonoBehaviour{ 9 // 取得した画像を適用するマテリアル 10 public Material view_material; 11 12 void Start(){ 13 StartCoroutine(GetLivePreview()); 14 } 15 16 IEnumerator GetLivePreview(){ 17 // POST先のURL。基本的には機種によらず同じURLで実行することができる 18 const string get_livepreview_URL = "http://192.168.1.1:80/osc/commands/execute"; 19 WebRequest livepreview_request = HttpWebRequest.Create(get_livepreview_URL); 20 livepreview_request.Method = "POST"; 21 livepreview_request.Timeout = 300000; 22 23 // POSTするjsonファイルの加工 24 livepreview_request.ContentType = "application/json;charset=utf-8"; 25 byte[] post_data = System.Text.Encoding.UTF8.GetBytes("{\"name\":\"camera.getLivePreview\"}"); 26 livepreview_request.ContentLength = post_data.Length; 27 28 // 通信開始 29 Stream request_stream = livepreview_request.GetRequestStream(); 30 request_stream.Write(post_data, 0, post_data.Length); 31 request_stream.Close(); 32 Stream response_stream = livepreview_request.GetResponse().GetResponseStream(); 33 34 BinaryReader response_reader 35 = new BinaryReader(new BufferedStream(response_stream), new System.Text.ASCIIEncoding()); 36 List<byte> picture_data = new List<byte>(); 37 bool is_load_start = false; 38 39 // MotionJPEGで送信される画像データを受け取り次第テクスチャとして適用させ続ける 40 while (true){ 41 byte byte_data = response_reader.ReadByte(); 42 if (!is_load_start){//画像データの先頭を捜索中 43 // MotionJPEGの先頭2バイトは0xFFD8 44 if (byte_data == 0xFF){ 45 byte next_data = response_reader.ReadByte(); 46 if (next_data == 0xD8){ 47 // MotionJPEGの先頭2バイトの確認ができたので、画像データとして取得開始 48 picture_data.Add(byte_data); 49 picture_data.Add(next_data); 50 51 is_load_start = true; 52 } 53 } 54 }else{ 55 picture_data.Add(byte_data); 56 // MotionJPEGの末尾2バイトは0xFFD9 57 if (byte_data == 0xFF){ 58 byte next_data = response_reader.ReadByte(); 59 if (next_data == 0xD9){ 60 // MotionJPEGの末尾2バイトの確認が出来たので、画像データをまとめてテクスチャとして適用 61 picture_data.Add(next_data);//データの追加 62 63 //追加ここから 64 65 // 画像データをMatオブジェクトに変換 66 Mat srcMat = new Mat(); 67 Cv2.ImDecode(picture_data.ToArray(), ImreadModes.Color);//画像データの読み込み 68 //picture_data.というリストを配列に変換し カラーで読み込み 69 70 // 透視投影変換の行列を作成 71 Mat perspectiveMatrix = Cv2.GetPerspectiveTransform( 72 new Point2f[4] { new Point2f(0, 0), new Point2f(srcMat.Width, 0), new Point2f(srcMat.Width, srcMat.Height), new Point2f(0, srcMat.Height) }, 73 new Point2f[4] { new Point2f(100, 100), new Point2f(srcMat.Width - 100, 100), new Point2f(srcMat.Width - 100, srcMat.Height - 100), new Point2f(100, srcMat.Height - 100) } 74 ); 75 76 // 透視投影変換を適用 77 Mat perspectiveMat = new Mat(); 78 Cv2.WarpPerspective(srcMat, perspectiveMat, perspectiveMatrix, srcMat.Size()); 79 80 // MatをTexture2Dに変換 81 Texture2D sphereTexture = new Texture2D(perspectiveMat.Width, perspectiveMat.Height, TextureFormat.RGBA32, false); 82 OpenCvSharp.Unity.MatToTexture(perspectiveMat, sphereTexture); 83 84 // テクスチャとして適用 85 Destroy(view_material.mainTexture); 86 view_material.mainTexture = sphereTexture; 87 88 //追加ここまで 89 90 Texture2D sphere_texture = new Texture2D(1, 1); 91 sphere_texture.LoadImage((byte[])picture_data.ToArray()); 92 Destroy(view_material.mainTexture); // 書いておかないと無限にテクスチャが増えてメモリリークする 93 view_material.mainTexture = sphere_texture; 94 picture_data.Clear(); 95 System.GC.Collect(); 96 is_load_start = false; 97 yield return null; 98 }else{ 99 picture_data.Add(next_data); 100 } 101 } 102 } 103 } 104 } 105} 106
ちなみに、インポートのusing OpenCvSharp;の部分と
63行目から88行目までが、THETAに接続して映像を表示するためのコード
参考:(https://qiita.com/reiya_prog/items/b52be9adf7a82a89eae0 )に追加した部分です。
試したこと
変換前の画像データを格納するsrcMatが空ではないのかと仮定して、画像データを読み込むためのメソッドであるCv2.ImDecodeを
67行目
Cv2.ImDecode(picture_data.ToArray(), ImreadModes.Color);
に第三引数としてsrcMatを追加して
Cv2.ImDecode(picture_data.ToArray(), ImreadModes.Color, srcMat);
と修正しましたが
以下のようにエラーが出ました。
No overload for method 'ImDecode' takes 3 arguments
補足情報(FW/ツールのバージョンなど)
OpenCV plus Unity Unity2021.3.11f1
回答1件
あなたの回答
tips
プレビュー
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。