2016-11-09 2 views
3

Sprache: Swift 3Swift 3 Schleife Mittelpixel des Bildes

Was ich bin mit: Hardware: ein iPhone 6 und FLIR Eine Wärmebildkamera Software: Xcode 8.1, Locked down FLIROne SDK (geschrieben und dokumentiert für obj-c und hat wenig Dokumentation überhaupt)

Was ich versuche zu tun: Erhalten Sie die Temperatur des zentralen Pixels aus dem zurück Kamera Strom

Das Problem: Ich habe alles in der App I Setup bin den Aufbau und die Arbeit einschließlich wie erwartet nicht diese thermischen Daten zu bekommen. Ich konnte die Temperatur aus dem zurückgesendeten Stream von der Kamera bekommen, aber ich kann es nur für das 0,0 Pixel (oben links) bekommen. Ich habe ein Fadenkreuz in der Mitte der Bildansicht, in das der Stream einfließt, und ich möchte das Pixel an diesem Mittelpunkt (der exakten Mitte des Bildes) erhalten. Ich arbeite seit zwei Tagen daran und ich kann mir nicht vorstellen, wie ich das machen soll. Mit dem SDK können Sie nicht angeben, aus welchem ​​Pixel und von was ich online gelesen habe. Sie müssen jedes Pixel durchlaufen und in der Mitte stoppen.

Der folgende Code wird die Temperatur von Pixel 0,0 erhalten und korrekt angezeigt. Ich möchte stattdessen die Temperatur erhalten, um das mittlere Pixel zu lesen. Temperatur muss UInt16 sein, um korrekte Kelvin-Anzeige (von dem, was ich zumindest verstehe) zu liefern, aber ich erhalte die radiometrischen Daten von Daten! als UInt8. HINWEIS: NSData! funktioniert nicht mit diesen Delegierten. Der Versuch, sie zu benutzen (selbst in swift 2.3), führt dazu, dass der Delegierte niemals feuert. Ich muss Daten verwenden! damit es sogar den Delegierten laufen lässt. Ich fand es sehr merkwürdig, dass ich swift 2.3 nicht verwenden konnte, weil es nur NSData hat. Wenn das daran liegt, dass ich etwas vermasselt habe, lass es mich wissen.

func flirOneSDKDelegateManager(_ delegateManager: FLIROneSDKDelegateManager!, didReceiveRadiometricData radiometricData: Data!, imageSize size: CGSize) { 

    let byteArray = radiometricData?.withUnsafeBytes{ 
     [UInt8](UnsafeBufferPointer(start: $0, count: (radiometricData?.count)!)) 
    } 

    let temperature = UnsafePointer(byteArray!).withMemoryRebound(to: UInt16.self, capacity: 1){ 
     $0.pointee 
    } 

    debugPrint(temperature) 

    DispatchQueue.main.async{ 
     self.tempLabel.text = NSString(format: "%.1f",self.convertToFarenheit(kelvin: temperature)) as String 
    } 
} 

Ich bin neu in Swift so bin ich nicht sicher, ob dies der beste Weg ist, dies so zu tun, wenn Sie eine bessere Art und Weise haben Sie mich auf sie beraten.

Aktuelle Lösung: Ruft das Mittelpixel, aber nicht dynamisch (das ist, was ich will)

let byteArray = radiometricData?.withUnsafeBytes{ 
     [UInt8](UnsafeBufferPointer(start: $0, count: (radiometricData?.count)!)) 
    } 

    let bytes:[UInt8] = [(byteArray?[74170])!,(byteArray?[74171])!] 

    let temperature = UnsafePointer(bytes).withMemoryRebound(to: UInt16.self, capacity: 1){ 
     $0.pointee 
    } 

Antwort

1

vorausgesetzt, Sie versuchen, einige UInt16 Werte von Swifts Daten zu lesen

import Foundation 

var data = Data([1,0,2,0,255,255,1]) // 7 bytes 
var arr: [UInt16] = [] 

// in my data only 6 bytes could be represented as Int16 values, so i have to ignore the last one ... 
for i in stride(from: 0, to: 2 * (data.count/2) , by: MemoryLayout<UInt16>.stride) { 
    arr.append(data.subdata(in: i..<(i+MemoryLayout<UInt16>.stride)).withUnsafeBytes { $0.pointee }) 
} 

print(arr) // [1, 2, 65535] 

oder Sie könnten etwas wie

let arr0: [UInt16] = data.withUnsafeBytes { (p: UnsafePointer<UInt8>)->[UInt16] in 
    let capacity = data.count/MemoryLayout<UInt16>.stride 
    return p.withMemoryRebound(to: UInt16.self, capacity: capacity) { 
     var arr = [UInt16]() 
     for i in 0..<capacity { 
      arr.append(($0 + i).pointee) 
     } 
     return arr 
    } 
} 
print(arr0) // [1, 2, 65535] 
verwenden

oder

extension Data { 
    func scan<T>(offset: Int, bytes: Int) -> T { 
     return self.subdata(in: offset..<(offset+bytes)).withUnsafeBytes { $0.pointee } 
    } 
} 

let k: UInt16 = data.scan(offset: 2, bytes: MemoryLayout<UInt16>.stride) 
print(k) // 2 

oder noch besser

extension Data { 
    func scan<T>(from: Int)->T { 
     return self.withUnsafeBytes { (p: UnsafePointer<UInt8>)->T in 
      p.advanced(by: from).withMemoryRebound(to: T.self, capacity: 1) { 
       $0.pointee 
      } 
     } 
    } 
} 
let u0: UInt16 = data.scan(from: 2) 
print(u0) // 2 

oder

extension Data { 
     func scan2<T>(from: Int)->T { 
      return self.withUnsafeBytes { 
// Precondition: The underlying pointer plus offset is properly aligned for accessing T. 
// Precondition: The memory is initialized to a value of some type, U, such that T is layout compatible with U. 
       UnsafeRawPointer($0).load(fromByteOffset: from, as: T.self) 
      } 
     } 
    } 

    let u2: UInt16 = data.scan2(from: 2) 
    print(u2) // 2 

was ist das Recht in Ihrer Daten-Offset, um den Wert zu lesen? Aus den Informationen, die Sie in Ihrer Frage angegeben haben, lässt sich nur schwer etwas sagen.

+0

Auf den SDK-Message Boards erhielt ich diese wackelige Suche nach einer Schleife mit allen möglichen falschen Berechnungen. Das einzige, was alle sagten, war, dass ich die Pixel durchlaufen musste, um zur Mitte zu gelangen. Ich bin mir nicht sicher, ob ich recht habe, aber der Offset, würde ich sagen, ist 2. Da Uint16 der erforderliche Wert für die Temperatur ist und Daten zurückgibt Uint8, dauert es zwei 8 Bits, um die 16-Bit-Temp zu konstruieren. Also tempAtPixel0 = Bytes = [ByteArray [0], ByteArray [1]]. Es sieht so aus, als wäre eine deiner Antworten ziemlich nah an etwas, das ich versucht habe, aber ich konnte es nicht tun. Ich werde es bald ausprobieren. – Nox

+0

Wenn Sie Ihre Lösungen durchsehen, wird meist erläutert, wie Sie Daten in das uint16-Array konvertieren können. Ich brauche im Grunde: Wie nehme ich die Uint8-Byte-Array und greifen Sie das Pixel in der Mitte des UIImageView. Ich wollte einen Weg, um das zentrale Pixel dynamisch zu bekommen. Ich kann das zentrale Pixel, das Byte 74170 und 74171, fest codieren, aber ich wollte es dynamisch machen, falls eine neue höhere Kamera veröffentlicht wird. Ich mag Ihren letzten Beitrag, dass mit der Datenerweiterung aber und scheint ein guter Weg, um mit den Daten aus dem Array zu bekommen. – Nox

+0

@Nox wissen wir nichts über das binäre Format Ihrer Daten. Wahrscheinlich befindet sich die Mitte Ihrer "Bilddaten" in der Mitte der Datenstruktur. Nehmen wir an, die Daten haben 1000 Bytes (0 ist der Offset des ersten Int16 Wertes, 2 ist der Offset des zweiten Int16 Wertes ..., 998 ist der Offset des 500sten Wertes). Verwenden Sie in diesem Fall den Offset 500, da 500 = 1000/(Größe von Int16 in Byte). Was ist die tatsächliche Größe Ihrer Daten, wenn die Bytes 74170 und 74171 das "mittlere Pixel" darstellen? Wenn ich richtig bin, sollte die Größe 2 * 74170 sein :-), oder? – user3441734