Monday, September 21, 2026
HomeiOS Developmentswift - Modifying TensorFlow Lite Picture Classification iOS App to Show Hyperlinks...

swift – Modifying TensorFlow Lite Picture Classification iOS App to Show Hyperlinks Associated to Picture Class

[ad_1]

I’m attempting to edit the iOS app that’s created with TensorFlow Lite Picture Classification mannequin code. I’ve educated the mannequin to establish particular buildings in a U.S. metropolis, and I would really like the app to carry up hyperlinks to extra details about the constructing as it’s recognized. It will act as a tourism data app, in order that customers may pull up data on a constructing they see as they stroll by. Every class is a particular person constructing.

That is for a grad college undertaking. I’ve some fundamental coding expertise, however I’ve by no means used Swift earlier than. Under is the xcode inference view controller code. Any ideas can be appreciated. Thanks.

// Copyright 2019 The TensorFlow Authors. All Rights Reserved.
//
// Licensed underneath the Apache License, Model 2.0 (the "License");
// you could not use this file besides in compliance with the License.
// You could get hold of a replica of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Until required by relevant regulation or agreed to in writing, software program
// distributed underneath the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, both categorical or implied.
// See the License for the precise language governing permissions and
// limitations underneath the License.

import UIKit

// MARK: InferenceViewControllerDelegate Methodology Declarations
protocol InferenceViewControllerDelegate {

  /**
   This technique is named when the person modifications the stepper worth to replace variety of threads used for inference.
   */
  func didChangeThreadCount(to rely: Int)

}

class InferenceViewController: UIViewController {

  // MARK: Sections and Data to show
  non-public enum InferenceSections: Int, CaseIterable {
    case Outcomes
    case InferenceInfo
  }

  non-public enum InferenceInfo: Int, CaseIterable {
    case Decision
    case Crop
    case InferenceTime

    func displayString() -> String {

      var toReturn = ""

      swap self {
      case .Decision:
        toReturn = "Decision"
      case .Crop:
        toReturn = "Crop"
      case .InferenceTime:
        toReturn = "Inference Time"

      }
      return toReturn
    }
  }

  // MARK: Storyboard Shops
  @IBOutlet weak var tableView: UITableView!
  @IBOutlet weak var threadStepper: UIStepper!
  @IBOutlet weak var stepperValueLabel: UILabel!

  // MARK: Constants
  non-public let normalCellHeight: CGFloat = 27.0
  non-public let separatorCellHeight: CGFloat = 42.0
  non-public let bottomSpacing: CGFloat = 21.0
  non-public let minThreadCount = 1
  non-public let bottomSheetButtonDisplayHeight: CGFloat = 44.0
  non-public let lightTextInfoColor = UIColor(displayP3Red: 117.0/255.0, inexperienced: 117.0/255.0, blue: 117.0/255.0, alpha: 1.0)
  non-public let infoFont = UIFont.systemFont(ofSize: 14.0, weight: .common)
  non-public let highlightedFont = UIFont.systemFont(ofSize: 14.0, weight: .medium)

  // MARK: Occasion Variables
  var inferenceResult: Outcome? = nil
  var wantedInputWidth: Int = 0
  var wantedInputHeight: Int = 0
  var decision: CGSize = CGSize.zero
  var maxResults: Int = 0
  var threadCountLimit: Int = 0
  non-public var currentThreadCount: Int = 0
  non-public var infoTextColor = UIColor.black

  // MARK: Delegate
  var delegate: InferenceViewControllerDelegate?

  // MARK: Computed properties
  var collapsedHeight: CGFloat {
    return normalCellHeight * CGFloat(maxResults - 1) + separatorCellHeight + bottomSheetButtonDisplayHeight

  }

  override func viewDidLoad() {
    tremendous.viewDidLoad()

    // Arrange stepper
    threadStepper.isUserInteractionEnabled = true
    threadStepper.maximumValue = Double(threadCountLimit)
    threadStepper.minimumValue = Double(minThreadCount)
    threadStepper.worth = Double(currentThreadCount)

    // Set the data textual content shade on iOS 11 and better.
    if #obtainable(iOS 11, *) {
      infoTextColor = UIColor(named: "darkOrLight")!
    }
    
  }

  // MARK: Buttion Actions
  /**
   Delegate the change of variety of threads to View Controller and alter the stepper show.
   */
  @IBAction func onClickThreadStepper(_ sender: Any) {

    delegate?.didChangeThreadCount(to: Int(threadStepper.worth))
    currentThreadCount = Int(threadStepper.worth)
    stepperValueLabel.textual content = "(currentThreadCount)"
  }
}

// MARK: UITableView Knowledge Supply
extension InferenceViewController: UITableViewDelegate, UITableViewDataSource {

  func numberOfSections(in tableView: UITableView) -> Int {

    return InferenceSections.allCases.rely
  }

  func tableView(_ tableView: UITableView, numberOfRowsInSection part: Int) -> Int {

    guard let inferenceSection = InferenceSections(rawValue: part) else {
      return 0
    }

    var rowCount = 0
    swap inferenceSection {
    case .Outcomes:
      rowCount = maxResults
    case .InferenceInfo:
      rowCount = InferenceInfo.allCases.rely
    }
    return rowCount
  }

  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

    var peak: CGFloat = 0.0

    guard let inferenceSection = InferenceSections(rawValue: indexPath.part) else {
      return peak
    }

    swap inferenceSection {
    case .Outcomes:
      if indexPath.row == maxResults - 1 {
        peak = separatorCellHeight + bottomSpacing
      }
      else {
        peak = normalCellHeight
      }
    case .InferenceInfo:
      if indexPath.row == InferenceInfo.allCases.rely - 1 {
        peak = separatorCellHeight + bottomSpacing
      }
      else {
        peak = normalCellHeight
      }
    }
    return peak
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "INFO_CELL") as! InfoCell

    guard let inferenceSection = InferenceSections(rawValue: indexPath.part) else {
      return cell
    }

    var fieldName = ""
    var data = ""
    var font = infoFont
    var shade = infoTextColor

    swap inferenceSection {
    case .Outcomes:

      let tuple = displayStringsForResults(atRow: indexPath.row)
      fieldName = tuple.0
      data = tuple.1

      if indexPath.row == 0 {
        font = highlightedFont
        shade = infoTextColor
      }
      else {
        font = infoFont
        shade = lightTextInfoColor
      }

    case .InferenceInfo:
      let tuple = displayStringsForInferenceInfo(atRow: indexPath.row)
      fieldName = tuple.0
      data = tuple.1

    }
    cell.fieldNameLabel.font = font
    cell.fieldNameLabel.textColor = shade
    cell.fieldNameLabel.textual content = fieldName
    cell.infoLabel.textual content = data
    return cell
  }

  // MARK: Format Show of data within the backside sheet
  /**
   This technique codecs the show of the inferences for the present body.
   */
  func displayStringsForResults(atRow row: Int) -> (String, String) {

    var fieldName: String = ""
    var data: String = ""

    guard let tempResult = inferenceResult, tempResult.inferences.rely > 0 else {

      if row == 1 {
        fieldName = "No Outcomes"
        data = ""
      }
      else {
        fieldName = ""
        data = ""
      }
      return (fieldName, data)
    }

    if row < tempResult.inferences.rely {
      let inference = tempResult.inferences[row]
      fieldName = inference.label
      data =  String(format: "%.2f", inference.confidence * 100.0) + "%"
    }
    else {
      fieldName = ""
      data = ""
    }

    return (fieldName, data)
  }

  /**
   This technique codecs the show of further data regarding the inferences.
   */
  func displayStringsForInferenceInfo(atRow row: Int) -> (String, String) {

    var fieldName: String = ""
    var data: String = ""

    guard let inferenceInfo = InferenceInfo(rawValue: row) else {
      return (fieldName, data)
    }

    fieldName = inferenceInfo.displayString()

    swap inferenceInfo {
    case .Decision:
      data = "(Int(decision.width))x(Int(decision.peak))"
    case .Crop:
      data = "(wantedInputWidth)x(wantedInputHeight)"
    case .InferenceTime:
      guard let finalResults = inferenceResult else {
        data = "0ms"
        break
      }
      data = String(format: "%.2fms", finalResults.inferenceTime)
    }

    return(fieldName, data)
  }
}

[ad_2]

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments