ビギグラマーのノート

自作PCやプログラミングについてのブログです。

OpenScanの構築

 はじめに

 OpenScanオープンソースの3Dスキャンプラットフォームの一つです。3Dスキャンプラットフォームの文字は公式にはないのですが、結構勘違いしそうなので適当に造語しています。意味合いとしては、写真で3Dスキャンする時複数の画像が必要なのですが、これを支援する器具という認識をしています。実際に3Dデータを作成するのは 

Recap PhotMeshroomといったPCで動かすソフトウェアになります。決して作ったからすぐスキャンし始められるものではないことを留意しておいてください。

 3DスキャンのはOpenScan以外にもCiclop 3D Scanner by bq3D - ThingiverseなどThinguverseで探せばいくつか見つけることができます。

 この中でもOpenScanは今流行りの写真解析の際の写真撮影を自動化するプラットフォームです。また開発が積極的でRaspberry pi対応等を行っていることから、これを選びました。しかし、体系的な組み立てからLaunchまで解説したところはほとんど無くましてや日本語解説サイトなど皆無なのでココに備忘録的に残しておきます。

参考

組み立てが乗っているPDF(何故か公式サイト内で探せなかった...

https://f86f3340-fde8-4577-a319-4f2c4f699e69.filesusr.com/ugd/953640_06c9f25b7a7b4940821ed21192586c02.pdf

ラズパイシールドの制作が乗っているPDF(公式Raspi対応に掲載されている

2019-12-02 Manual.pdf - Google ドライブ

シールド等の回路図

2019-11-16 Circuit diagram.pdf - Google ドライブ

 

 

【Swift】Frameworkをテスト環境と共に構築する

環境

Xcode: 11.2

Swift: 5

Frameworkの作成

 まずはじめにFrameworkとそのテスト環境を作成します。最初に作るのはFrameworkです。Single View Appから作り始めると後に追記するScriptの関係から多少めんどくさくなります。

f:id:BegiGrammer:20191102164839p:plain

 FrameworkのTargetでテスト用のSingleViewAppを追加します。

f:id:BegiGrammer:20191102165020p:plain

f:id:BegiGrammer:20191102165026p:plain

 次のステップとしてFrameworkに仮のclassを作っておきます。Frameworkの内容はこの場所等に書いていきます。

f:id:BegiGrammer:20191102165338p:plain

 さらに次にはTargetでCross-Platform > Aggregateを追加します。追加方法は上記のSingleViewAppの追加方法と同じです。Aggregateを追加することでFrameworkをSimulator用とDevice用の両者に対応するような結合したFrameworkを出力するようにします。

f:id:BegiGrammer:20191102165727p:plain

今作成したAggregateのBuildPhasesでRun Scriptを追加します。写真がちょっと違っていますが場所は同じです。

f:id:BegiGrammer:20191102170514p:plain

 この場所に貼り付けるScirptはこちらをコピペしてくればOKです。

gist.github.com

ビルドターゲットとして先ほど作成したAggregateを指定し、command + B等でビルドします。

f:id:BegiGrammer:20191102170757p:plain

このビルドでFrameworkの作成が完了しました。このFrameworkの場所は少々探しにくい位置にありますがProductsでShow In Finderをすることで素早くアクセスすることができます。

f:id:BegiGrammer:20191102171411p:plain

 Frameworkがある場所はDebug-universal内、今回はTestFramework.frameworkです。その他のフォルダには実機用とSimulator用のFrameworkが置いてあります。余談ですがこのFrameworkの違いはスマホ用とPC用で採用しているプロセッサの違いから来ているものなので、将来的にIntel Macから自社開発のCPU搭載Macとなった場合若干開発が楽になりそうです。

f:id:BegiGrammer:20191102172033p:plain

f:id:BegiGrammer:20191102172038p:plain

以下からは作成したFrameworkを実際のAppに組み込む方法となります。

追記 1

 いちいちめんどくさい場所からShow in Finderして持ってこずとも、Project直下にFrameworkが作成されている模様。Aggregateをビルドした際に勝手に開く場所ね。最初この方法でやった時には.frameworkはこの場所に作成されていなかったような覚えがありますが、知らないうちに環境変えてしまったのかよくわかりません。まあ、どちらからも取れるってことでここはひとつ。

 さらにBuildターゲット?を選択する際に写真ではGeneric iOS Deviceを選択していますが、一番上の選択肢にあると思うMy Macでも同様にできるようです。Simulatorは結局Mac上で動いているためユニバーサルFrameworkではどっちでも選べるのか?まあ、そんな感じに思っています。ただし、Generic iOS Deviceを選択した場合のみDeviceDataフォルダ下(ようは前述しためんどくさい深い場所、Show in Finderで飛べる)に生成されるようです。つまり、BuildターゲットはMyMacを選択し、Generic iOS Deviceはここでも一応できるよ程度に覚えておくのがいいかもしれません。

 

追記 2

 本記事ではまずProjectをFrameworkで作成し、後にSingleViewAppを追加しました。これを逆にするとどうなるでしょうか。つまりSingleViewAppでProject作成後Frameworkを追加した場合です。この場合Universalに.frameworkが作成されません。また追記1で記述した箇所にframeworkは同様に作成されません。

 結論からいうと${PROJECT_NAME}の変数がFrameworkの箇所を指さなくなる為Scriptが思った通りに実行されません。

 これはRunScriptを読んで貰えば分かるのですが、

"${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework

という箇所でiOS側のframeworkを指定しているのですが、この${PROJECT_NAME}がFrameWorkではなく最初に作成されたSingleViewAppの方を指してしまうのです。そうするとBuild/Products/Debug-iphoneos/SingleViewAppName.frameworkにはFramework本体が作成されない為、ScriptがStep.1 Build Devices and Simulator versions以降実質的に実行されない状態となる為です。

 わかりづらい説明ですが、とりあえずFramework -> SingleViewAppの順で作成すれば問題ないという事です。どうしてもSingleViewApp作成後Frameworkを追加したい場合Run Scripを変更しなければなりません。

Frameworkの組込

 SingleViewAppでとりあえず空のProjectを作成しておきます。今回は"Test"という名のAppを作成しました。組込方法はいくつかあるのですが、とりあえずわかりやすい方法で回してきます。右クリックでAdd File to "Project"を選択し作成したFrameworkをAppに組み込みます。この際にCopy items if neededに選択をしておいてください。

f:id:BegiGrammer:20191102173906p:plain

 FrameworkをProjectに追加後、Targetsの"Project Name"(今回はTest)のCopy FilesにFrameworkを追加します。この時Copy Filesの項目が存在しない場合はRun Scriptと同じようにCopy Filesの項目を追加してください。またFrameworkを追加するためにCopy FilesのDestinationをFrameworkに変更してください。

f:id:BegiGrammer:20191102174426p:plain

f:id:BegiGrammer:20191102174440p:plain

これで自作Frameworkの組込が完了しました。後はCocoa podsと同じようにimportすれば使用が可能です。

f:id:BegiGrammer:20191102174630p:plain

 

Raspberry piでHDMI出力のON OFF

内容

 Raspberry pyでHDMI接続の液晶のON OFFを切り替えるときによく紹介されているのが tvserviceを使った方法ですが、当方のパネルではOFFはできてもONができませんでした。この復帰ができない現象はいくつかのブログで指摘されているようで、これに代わる物の日本語記事がなかったのでメモがわりに。

解決法

raspberrypi.stackexchange.com

 上のリンクで外人兄貴が指摘しているのは tvservice を使った方法はBest wayではないということです。その代りとして使われるのが

vcgencmd display_power 0 # ディスプレイ OFF

vcgencmd display_power 1 # ディスプレイ ON

ということです。 完全に受け売り記事ですが以上で…

【Swift】ScrollView 内にImageViewがある時zoomの変更に注意を!

はじめに

 ScrollViewはiOSの設計の中でもかなり重要なファクターを担っており、これをせいするものがSwiftを制すとも言われます。私が言っているだけですが...

 ScrollViewにImageViewを入れて画像を表示したいというのは非常に多い場面だと思います。その際のZoom指定で数時間悩んだのでメモを残しておきます。

やりたいこと

 これは非常にシンプルでScrollView内の画像を入れ替えた際に画面にちょうど良い形でZoomが行われることを目標にしています。

f:id:BegiGrammer:20190616011233g:plain

To Do

 このようにShow1Btnを押すとScrollViewに青空が、Show2Btnを押すとピザが表示されるようにします。さらに両者のサイズに合わせてZoomを自動で計算し、よしなに表示するようにします。

問題点

 これを実現するために作ったコードは非常に単純で以下のようにしました。

 しかしこれをただ単純にImageViewにImageを挿入後、ImageViewのサイズを整え、ScrollViewのcontentSizeを変更した後に実行したところ以下のようになりました。

f:id:BegiGrammer:20190616012235g:plain

Failure

 1枚目のリサイズはうまく言っているのですが、2枚目以降のリサイズができていないことがわかります。非常に簡単なことなのにここでつまずくかと、ストレスを溜めて画面パンチしそうになる手を押さえつけしばらく考えていました。

解法

 結局しばらく考えたのちに以下のような答えにたどり着きました。

 すなわち言葉では言い表しにくいのですがScrollViewのZoom関係の設定では、Propertyが変更されると現在の倍率の1/x倍して等倍に戻してから次の倍率を再計算しているのでしょう。もしくはこれと同じ結果になる前回と次回の倍率の差か... こっちの方が計算量少ないですかね

 そのためX倍した状態でScrollViewの中のViewのサイズを変更し倍率を変えた時、変更されたViewに1/Xが掛けられ等倍に戻せて無い状態から更に指定された倍率にしようとした結果おかしな状態になるのだと思います。

 教訓としては、「ScrollViewのSubViewnのサイズ変更をするときはZoomを1倍に戻してから変更しないと危ないよ」ということでした。

正解のコード

『OpenCV for iOS』ポートレート撮影しUIImageToMatすると画像が横向く

 はじめに

 いつにも増して題名がイミフですので、写真で説明しましょう。

f:id:BegiGrammer:20180904002121p:plain

 上の段が現在カメラで見えているものです。そしてその下の段がOpenCVのUIImageToMat・MatToUIImageを経てUIImageViewに貼り付けられた画像になります。ポートレートで撮影しているにも関わらず、横向きになっていることがわかります。これをどうにかしようとするのがこの記事になります。

原因と解決法

 iPhoneの縦長撮影は実を言うと横向き撮影とデータは変わりません。そのためkeyで横向き・縦向きを制御しているのですが、OpeCVのMatに変換されるとそのkeyが脱落してしまいます。そのため90度回転した画像が送られてくるわけです。

 以下が元々のキーを付け直す作業になります。

ネタ元

stackoverflow.com

NavigationBarとStatusBarの隙間を埋める

 はじめに

 NavigationBarを手動で追加した場合StatusBarの色が違います。文字にすると表現しずらいため画像で表すと。

f:id:BegiGrammer:20180703213334p:plain

 こんな感じになっているところを次のようにしたいと思います。

f:id:BegiGrammer:20180703213448p:plain

方法

UIBarPositionDelegateを追加してNavigation Bar のdelegateにselfを設定する、そして

 func position(for bar: UIBarPositioning) -> UIBarPosition {

     return .topAttached

 }

これでNavigationBarがStatusBarまで延長されて良さげになるようです。

参照

日本語のHow to ブログがあったと思ったのですが、ざっと探す感じ見当たらなくなっていたため備忘録として残します。

stackoverflow.com

【Swift】UITextViewのカーソルの位置・サイズを取得する

前置き

 UITextViewはなかなか痒いところに手が届かないクラスだと思います。今回はTextViewのカーソルの位置をCGPointで取得したかったのですが、なかなか検索に引っかからなかったので備忘録として残しておきます。

コード

    func textViewDidChangeSelection(_ textView: UITextView) {

        guard let range = textView.selectedTextRange else {return}

        let cursor = textView.caretRect(for: range.end)

        print(cursor)

    }

 

参考

stackoverflow.com