[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]
