- 投稿日:2019-09-15T22:47:02+09:00
Unity+ARKit3のbody segmentation結果を配列として取得する
既知の問題(2019/9/16更新)
以下の方法は、セグメンテーションのテクスチャに限り、端末の向きを変更するとそれ以降値が変化しなくなる問題が起きています。(デプスのテクスチャは問題なし。Orientation設定は関係なし)
そのため、あまり上手い方法ではないかもしれませんので、そのつもりで利用してください。やりたいこと
ARKit3を利用することで人物領域をセグメンテーションすることができる。
しかし、結果がTexture2Dとして取得されるので、そのままでは結果を加工しにくい。
なので、byteなどの配列として結果を取得したい。ハマったポイント
Texure2Dなので、GetPixels()などを使えば一瞬だと思ったが、関数がうまく機能しないらしい。
原因(推定)
UnityのARKit3プラグインを確認していくと、このTexture2Dはネイティブで作られている模様。(CreateExternalTexture/UpdateExternalTextureでの作成・更新処理を発見)
Texure2Dはネイティブで作られたものをラップしているだけなので、GetPixels()などの関数が正しく機能しなかったと思われる。
参考(テラシュールブログさん):
http://tsubakit1.hateblo.jp/entry/20140104/1388830289
http://tsubakit1.hateblo.jp/category/トラブルシューティング?page=1469026740#RenderTextureをTexture2Dに流し込む解決策
凹みTipsさんの
Low-Level Native Plugin Interface を利用してネイティブから Unity のテクスチャを高速に更新する方法を調べてみた - 凹みTips
によると、iOSにおいてはid<MTLTexture>がテクスチャの実体らしいので、以下のようなプラグインを書いて、配列として取得することで解決。
idから配列としてデータを取得する関数は以下。
https://developer.apple.com/documentation/metal/mtltexture/1516318-getbytes/Assets/Plugins/iOS/TextureExtention.mm#import <Metal/Metal.h> #import <MetalKit/MetalKit.h> extern "C" { void GetNativePixels(id<MTLTexture> texture, int width, int height, int sizePerRow, char *buffer) ; } void GetNativePixels(id<MTLTexture> texture, int width, int height, int sizePerRow, char *buffer) { [texture getBytes:buffer bytesPerRow:sizePerRow fromRegion:MTLRegionMake2D(0, 0, width, height) mipmapLevel:0]; }/Assets/Plugins/TextureExtention.csusing System; using UnityEngine; using System.Runtime.InteropServices; public class TextureExtention { [DllImport("__Internal")] public static extern void GetNativePixels(IntPtr texturePtr, int width, int height, int sizePerRow, [Out] byte[] buffer); public static void GetNativePixels(Texture2D humanTexture, ref byte[] buffer) { // humanTexture は ARKit3で取得されたセグメンテーション結果が格納されたテクスチャ IntPtr humanTexturePtr = humanTexture.GetNativeTexturePtr(); int width = humanTexture.width; int height = humanTexture.height; int sizeParRow = humanTexture.width * 1; // ボディセグメンテーションではテクスチャフォーマットはR8なので 1ピクセル=1Byte GetNativePixels(humanTexturePtr, width, height, sizeParRow, buffer); } }補足
今回ネイティブプラグインを作って対処しましたが、Unity内でRenderTexture->Texuture2Dへの変換のようにテクスチャを本当のTexutre2Dコピーして、GetPixels()を使う方法でもできるかもしれません。
また、セグメンテーション結果ではなくデプス推定結果でも同じようにすれば大丈夫です。その際はテクスチャフォーマットがRFloatなので、その調整をする必要があります。動作環境
Unity 2019.2.5f
Xcode 11 GM Seed感想
GetPixels()が使えないという判断までも時間がかかったし、初めてのiOSネイティブプラグイン作成だったので色々苦労してしまいました…。
- 投稿日:2019-09-15T21:13:08+09:00
iPadのOSアップデートをブロックする方法ないの?
組織のiPadを管理している人を恐怖のどん底に追い落とすような、恐ろしい情報が‥。
iPad 上の iOS13 の挙動変更により Azure AD 条件付きアクセス ポリシーの動作に影響が生じる
Appleの仕様変更で、iPadを13にバージョンアップすると、Safariとかネイティブメーラーは、MacOSとみなすぜ!なので準備してね!ということらしい。
そうなっちゃうと、認証とセキュリティポリシーが影響受けそう。下手すればログインできなくなるとか、セキュリティポリシーの適用外になりかねない。
認証の構成やセキュリティポリシーの適用から、iPadのOSバージョンを12にとどめておきたい。せめて無期限とは言わなくても、検証する間だけでもいいから、ってことで調べてみた。
ざっくり
Intuneだとこの記事が一番わかりやすい。
Microsoft Intuneで iOS のアップデートを制限する設定手順の紹介もあるけど、こういうことらしい。
・iOS11.3移行
・監視対象デバイス
・OSのバージョンがリリースされて最長90日までは制限できる
・完全にブロックではなく、あくまで延期でしかない公式ドキュメント
いくつかひろってみた。
■Apple 管理対象のソフトウェアアップデートについて
iOS 11.3 以降、tvOS 12.2 以降では、MDM の管理者が、監視対象のデバイスに新しいソフトウェアアップデートが表示される時期を遅らせることができます。
iOS や macOS のソフトウェアアップデートを管理者が遅らせている場合は、管理者によって認められた最新のソフトウェアアップデートがデバイスで実行されているというメッセージが表示されます。
■Intune Intune に iOS ソフトウェア更新プログラム ポリシーを追加する
ソフトウェアの更新ポリシーにより、監視対象の iOS デバイスに利用可能な最新の OS 更新プログラムを強制的に自動インストールします。 ポリシーを構成しているときに、デバイスで更新プログラムをインストールしない日時を追加できます。
この機能は、以下に適用されます。
iOS 10.3 以降 (監督下)
デバイスは約 8 時間ごとに Intune でチェックインされます。 更新プログラムを利用できて、制限時間中ではない場合、デバイスで最新の OS 更新プログラムをダウンロードしてインストールします。 デバイスを更新するために必要なユーザーの操作はありません。 ポリシーにより、ユーザーが手動で OS を更新できなくなることはありません。10.3ってあるのは誤記?
■AirWatch iOS デバイス用の制限事項プロファイルの構成
このオプションを有効にし、ソフトウェアの更新を延期する日数を指定します。日数は 1 ~ 90 日の範囲です。(iOS 11.3 以降の監視モード デバイス)。日数は、ソフトウェアの更新がリリースされてからの期間です。プロファイルをインストールしてからの期間ではありません。
荒っぽい方法
アップデート用のサーバーへのアクセスを、常時VPN構成+firewallでブロックという方法もあるらしい。
iOS バージョンアップを止める方法
※2014年の記事のようです。まとめ
外部認証サービス使ってたら、そっちの影響も考えなきゃいけない。
とりあえず、β版のiPad用意して検証&
ユーザーのデバイスは延期してその間に検証&対策検討、ですかね・・・。
- 投稿日:2019-09-15T15:51:29+09:00
R.swift5.0でZeplinとの色の連携が完璧になった
R.swift5.0でZeplinについてのtipsです。
R.swift5.0未満のつらみ
R.swiftがCLRファイル形式しかサポートしていなかったので、せっかくZeplinがAsset Colorsを吐き出してくれるのに、
R.color
が使えない...。(このCLRファイルが絶妙に使いにくいのです)なのでZeplinで吐き出される自動生成のコードをXcodeのプロジェクトに追加して利用していました。この問題点は、デザインスペックの管理はZeplin、ソースコード上でのリソース管理はR.swiftに分離したいのに、一部ソースコード上でのリソース管理をZeplinが行なってしまうことです。
この下側のような自動生成コードを使っていました。
R.swift5.0以降の嬉しさ
R.swift5.0のリリースノートの一文に
Removed CLR file support, use color resources insteadCLRファイルのサポートを取り除いて、代わりにカラーリソースを使うようにしましたと書いてあります。
これによって、R.swift5.0からはColor Assetsを参照できるようになったので、自動生成のコードを利用しなくても問題なくなり以下のようなフローに改善されました。
- Zeplinの「export to xcassets」を押す
ビルドをかける
R.colorで色を参照可能になる
超楽!何もしなくて良い!
これによって、色に関してはデザインスペック管理はZeplin、リソース管理はR.swiftという分離を図ることができました。
要望
これはXcode側の問題なのですが、fontをxcassetで定義してコードとストーリーボードから参照できるようになれば、Zeplinがxcassetにfont吐き出して、R.swiftがそれをR.fontで使えるようにして...。ってなりそうなので良いなーと思っています。
- 投稿日:2019-09-15T13:29:35+09:00
RxSwiftをCarthageで入れて起動時に`Library not loaded`エラーが出たらRxRelayも追加して解決した
RxSwiftとRxCocoaを追加後、ビルドはサクセスするのですが、実機で動作確認ししようとすると以下のエラーで落ちてしまいました。
dyld: Library not loaded: @rpath/RxRelay.framework/RxRelay Referenced from: /var/containers/Bundle/Application/xxxxxxx-xxxx-xxxx-xxxx-477EBE5CC202/xxx.app/xxx Reason: image not found今回の解決方法は、RxRelayも追加することでした。
RxSwiftライブラリをビルドすると、以下の5つのフレームワークが生成されます。
- RxSwift
- RxCocoa
- RxRelay
- RxBlocking
- RxTest
RxSwift, RxCocoaのみXcodeで追加すれば良いと思っていたのですが、どうやらRxRelayも必要みたいですね?
TARGETS -> General -> LinkedFrameworks and Libraries
にRxRelayも追加し、
Build Phases の Input Files Lists, Output Files Lists にも追記しました。input.xcfilelist$(SRCROOT)/Carthage/Build/iOS/RxSwift.framework $(SRCROOT)/Carthage/Build/iOS/RxCocoa.framework $(SRCROOT)/Carthage/Build/iOS/RxRelay.frameworkoutput.xcfilelist$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxSwift.framework $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxCocoa.framework $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxRelay.framework以上で、無事に実機での動作確認を行えるようになりました。
- 投稿日:2019-09-15T13:29:35+09:00
RxSwiftをCarthageで入れたら実機で起動できなかったので、RxRelayも追加して解決した
RxSwiftとRxCocoaを追加後、ビルドはサクセスするのですが、実機で動作確認ししようとすると以下のエラーで落ちてしまいました。
dyld: Library not loaded: @rpath/RxRelay.framework/RxRelay Referenced from: /var/containers/Bundle/Application/xxxxxxx-xxxx-xxxx-xxxx-477EBE5CC202/xxx.app/xxx Reason: image not found今回の解決方法は、RxRelayも追加することでした。
RxSwiftライブラリをビルドすると、以下の5つのフレームワークが生成されます。
- RxSwift
- RxCocoa
- RxRelay
- RxBlocking
- RxTest
RxSwift, RxCocoaのみXcodeで追加すれば良いと思っていたのですが、どうやらRxRelayも必要みたいですね?
TARGETS -> General -> LinkedFrameworks and Libraries
にRxRelayも追加し、
Build Phases の Input Files Lists, Output Files Lists にも追記しました。input.xcfilelist$(SRCROOT)/Carthage/Build/iOS/RxSwift.framework $(SRCROOT)/Carthage/Build/iOS/RxCocoa.framework $(SRCROOT)/Carthage/Build/iOS/RxRelay.frameworkoutput.xcfilelist$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxSwift.framework $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxCocoa.framework $(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/RxRelay.framework以上で、無事に実機での動作確認を行えるようになりました。
- 投稿日:2019-09-15T13:20:10+09:00
今回、アプリ内でQRコードを生成して表示する必要があったのでRSBarcodesを使いました
バーコード生成用クラスを作成
import AVFoundation import UIKit import RSBarcodes /// バーコードを生成する final class BarcodeGenerator { /// 生成予定のコードを検証する func validateCode(_ code: String, codeObjectType: AVMetadataObject.ObjectType) -> Bool { return RSUnifiedCodeValidator.shared.isValid( code, machineReadableCodeObjectType: codeObjectType.rawValue ) } /// コードを生成する func generateCodeImage(_ code: String, codeObjectType: AVMetadataObject.ObjectType) -> UIImage? { return RSUnifiedCodeGenerator.shared.generateCode( code, machineReadableCodeObjectType: codeObjectType.rawValue ) } /// スケールを使ってリサイズする func resizeCodeImage(_ image: UIImage, scale: CGFloat) -> UIImage? { return RSAbstractCodeGenerator.resizeImage(image, scale: scale) } /// サイズを指定してリサイズする func resizeCodeImage(_ image: UIImage, size: CGSize, contentMode: UIView.ContentMode) -> UIImage? { return RSAbstractCodeGenerator.resizeImage(image, targetSize: size, contentMode: contentMode) } }専用のクラスを用意して、ライブラリが持つ機能をメソッド化しました。
import AVFoundation
は必須です。QRコードを生成する場合は、
codeObjectType: AVMetadataObject.ObjectType
を.qr
と指定します。