47191


現在、coreMLとVisionを使って画像の物体認識を行うアプリを作成中です。

以下のようなコーディングを行い、画像の物体認識した結果をデバッグエリアに出力しています。  
その後、配列の0番目をbestに代入します。

[code]

    func handleClassification(request: VNRequest, error: Error?) {
        guard let observations = request.results as? [VNClassificationObservation] else { fatalError() }
        //print("observations = ", observations)
        guard let best = observations.first else { fatalError() }
    
[/code]

以下は出力結果です。

[![画像の説明をここに入力](https://i.stack.imgur.com/soata.png)](https://i.stack.imgur.com/soata.png)

配列の0番目の要素はsoccerで推測値が0.909137  
配列の1番目の要素はbaseballで推測値が0.087247  
といった感じで並んでいます。

画像の物体認識した結果後、配列内の要素の順番を変更したいのですが、やり方がわかりません。  
(やってみたいことははっきりとしているのですが、解決方法がわかりません)

■やってみたいこと  
画像の物体認識した結果後、  
もしbaseballの推測値が0.080000以上のときは、baseballを配列の0番目に変更したいです。  
baseballの推測値が0.080000より小さいときは、配列の順番を変更しない。

if文で記述すると以下のような感じになると思います。

[code]

     if baseballの推測値が0.080000以上だったら {
         baseballを配列の0番目に置く。
     } baseballの推測値が0.080000より小さかったら {
         配列の順番は変更しない。
     }
    
[/code]

独学でSwiftを学んでいるため分からないことが多いのですが、  
そもそも上記のような配列内の操作は可能なのでしょうか。

ご教示いただけますでしょうか、宜しくお願いします。

* * *

* * *

■追記

配列の要素を入れ替える方法は、[こちら](https://teratail.com/questions/46764)の記事を参考に実装したいと思います。

そのため、以下のようなコーディングを目指しています。

[code]

    if baseballの推測値が0.080000以上だったら {
         配列内のbaseballのindex番号を調べる。
         例えば、画像認識の結果、baseballのindex番号が配列の4番目の場合は、
         配列の0番目と4番目を入れ替える。
     } baseballの推測値が0.080000より小さかったら {
         配列の順番を変更しない。
     }
    
[/code]

現在は、配列内でbaseballの推測値が0.080000以上であるのか  
baseballの推測値が0.080000より小さいのかを察知する方法が  
分かりません。

お手数をおかけ致しますがご教示頂けますでしょうか。  
宜しくお願い致します。


CC BY-SA 4.0
2018-08-02T04:40:09.413
47175
2018-08-02T12:09:00.077
2018-08-02T10:11:34.137
14329
14329
question
swift ios iphone swift4 array
Swiftの配列内を操作する方法


使用されている配列がNSArrayの場合はそのままではむつかしいでしょう。  
NSMutableArrayに一度入れ替えると、インデックス操作により要素の入れ替えは簡単になります。


CC BY-SA 4.0
2018-08-02T05:43:02.187
47178
2018-08-02T05:43:02.187
17014
47175
answer


何点かポイントを。

  * 配列(あなたの`observations`)を`let`で宣言すると、その中身を後から変更することはできません。`guard let`ほどポピュラーなイディオムではありませんが、Swiftでは`guard var`なんて宣言もできます。

  * `baseballの推測値が0.080000以上だったら`なんて条件を少し書き換えて、「信頼度が0.080000以上で識別子が`"baseball"`の要素があれば」と読み替えてみます。Swiftの`Array`には大変汎用性の高い`index(where:)`と言うメソッドがあるので、それを使えば判定と同時にそのindex番号を得ることができます。

  * (現在の)Swiftの`Array`には、`swapAt(_:_:)`というメソッドがあるので、特別に要素入れ替え用の`extension`を定義する必要はありません。

以上をコードの形にまとめると、こんな感じになります。

[code]

    guard var observations = request.results as? [VNClassificationObservation] else { fatalError() }
    //print("observations = ", observations)
    //`identifier`が"baseball"で、`confidence`が0.080000以上の要素のindexを取得する
    if let baseballIndex = observations.index(where: {$0.identifier == "baseball" && $0.confidence >= 0.080000}) {
        //取得できたならそのindexと0番目を入れ替え
        observations.swapAt(0, baseballIndex)
    } else {
        //配列の順番は変更しない。
    }
    
[/code]


CC BY-SA 4.0
2018-08-02T12:09:00.077
47191
2018-08-02T12:09:00.077
13972
47175
answer