2016-11-09 6 views
3

Язык: Swift 3Swift 3 петли до центра пикселя изображения

Что я использую: Оборудование: IPhone 6 и FLIR Одна тепловизионная камера Software: Xcode 8.1, Заблокировано FLIROne SDK (написано и задокументировано для obj-c и имеет небольшую документацию вообще)

Что я пытаюсь сделать:Получить температуру центрального пикселя из возвращенного потока камеры

Проблемы: У меня есть все, что в приложении я строй настройки и работе, как ожидается, не включая получать эти термические данные. Мне удалось получить температуру из возвращенного потока с камеры, однако я могу получить его только на 0,0 (верхний левый) пиксель. У меня есть перекрестье в центре изображения, в которое подается поток, и я хотел бы получить пиксель в этой центральной точке (точный центр изображения). Я работаю над этим в течение двух дней, и я не могу понять, как это сделать. SDK не позволяет вам указать, какой пиксель читать и из того, что я читал в Интернете, вам нужно пройти через каждый пиксель и остановиться в центре.

Приведенный ниже код получит температуру от 0,0 до 0,0 и отобразит ее правильно. Я хочу, чтобы температура читала центральный пиксель. температура должна быть UInt16, чтобы обеспечить правильное считывание Кельвина (по крайней мере, я понимаю), но я получаю радиометрические данные из Data! как UInt8. ПРИМЕЧАНИЕ: NSData! не работает с этими делегатами. Попытка использовать его (даже в быстром 2.3) заставляет делегата никогда не стрелять. Я должен использовать данные! за то, что он даже запустил делегата. Мне было очень странно, что я не мог использовать swift 2.3, потому что у него есть только NSData. Если это потому, что я что-то напортачил, пожалуйста, дайте мне знать.

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 
    } 
} 

Я новичок в Swift, поэтому я не уверен, что это лучший способ сделать это, так что если у вас есть лучший способ, пожалуйста, сообщите мне об этом.

Текущее решение: Получает центр пикселя, но не динамически (что я хочу)

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 
    } 

ответ

1

если вы пытаетесь прочитать некоторые значения UInt16 от Свифта данных

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] 

или вы можете использовать что-то вроде

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] 

или

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 

или даже лучше

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 

или

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 

что является правильным смещением в данных, чтобы прочитать значение? трудно сказать из информации, предоставленной вами в вашем вопросе.

+0

На досках объявлений SDK мне был дан этот неуловимый поиск петли со всеми видами неправильных вычислений на ней. Единственное, что все говорили, это то, что мне нужно было пройти через пиксели, чтобы добраться до центра. Я не уверен, что я прав на это, но смещение, я бы сказал, равно 2. Поскольку Uint16 является обязательным значением для temp, а данные возвращают Uint8, для построения 16-разрядной temp требуется два 8 бит. Итак, tempAtPixel0 = bytes = [byteArray [0], byteArray [1]]. Похоже, что один из ваших ответов довольно близок к тому, что я попытался, но не мог этого сделать, я скоро попробую. – Nox

+0

Просматривая ваши решения, в основном предоставляем, как конвертировать из данных в массив uint16. Мне в основном нужно: как взять массив байтов uint8 и захватить пиксель в центре UIImageView. Я хотел, чтобы динамически получить центральный пиксель. Я могу жестко закодировать центральный пиксель, который является байтом 74170 и 74171, но я хотел сделать это динамически, если будет выпущена новая камера с высоким разрешением. Мне нравится ваш последний пост, что с расширением данных, хотя и, кажется, хороший способ справиться с получением данных из массива. – Nox

+0

@Nox мы ничего не знаем о бинарном формате ваших данных. Скорее всего, середина ваших «данных изображения» находится в середине структуры данных. Пусть говорят, что данные имеют 1000 байтов (0 - смещение первого значения Int16, 2 - смещение второго значения Int16 ..., 998 - смещение 500-го значения). В этом случае используйте смещение 500, потому что 500 = 1000/(размер Int16 в байтах). Каков фактический размер ваших данных, если байты 74170 и 74171 представляют «средний пиксель»? Если я прав, размер должен быть 2 * 74170 :-), не так ли? – user3441734

Смежные вопросы