从照片 SwiftUI 中获取图像时内存不足
Posted
技术标签:
【中文标题】从照片 SwiftUI 中获取图像时内存不足【英文标题】:Running out of memory while fetching images from Photos SwiftUI 【发布时间】:2021-05-12 16:41:29 【问题描述】:我正在开发一个可以检测狗品种的应用程序,我希望当用户打开他们的照片库时,他们只会看到带有狗的图像。为此,我使用了非常基本的 Vision 宠物识别器模型,问题是在 1000 张照片上运行需要一段时间且内存过多。我想知道是否有任何解决方案。
PhotoLibraryViewModel.swift
import Photos
import UIKit
import Vision
class PhotoLibraryViewModel: ObservableObject
@Published var uiImages = [UIImage]()
var allPhotos : PHFetchResult<PHAsset>? = nil
init()
getPhotos()
private func getPhotos()
phphotoLibrary.requestAuthorization [weak self] status in
switch status
case .authorized:
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
self?.allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)
self?.setCompositionalLayout()
case .denied, .restricted:
print("Not allowed")
case .notDetermined:
print("Not determined yet")
case .limited:
print("limited")
@unknown default:
fatalError()
private func setCompositionalLayout()
print("all photos: " + "\(allPhotos!.count)")
allPhotos?.enumerateObjects() [self] photo, _, _ in
let options = PHImageRequestOptions()
options.version = .original
PHImageManager.default().requestImage(for: photo, targetSize: CGSize(width: (screen.width - 60) / 3, height: (screen.width - 60) / 3), contentMode: PHImageContentMode.aspectFit, options: options) [self] uiImage, _ in
guard let finalUIImage = uiImage else
print("failed to make finalUIImage")
return
checkImage(uiImage: finalUIImage)
private func checkImage(uiImage: UIImage)
var animalRecognitionRequest = VNRecognizeAnimalsRequest(completionHandler: nil)
let animalRecognitionWorkQueue = DispatchQueue(label: "PetClassifierRequest", qos: .userInteractive, attributes: [], autoreleaseFrequency: .workItem)
guard let cgImage = uiImage.cgImage else
print("failed to convert image")
return
animalRecognitionWorkQueue.async
let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
do
try requestHandler.perform([animalRecognitionRequest])
catch
print("error: " + "\(error)")
animalRecognitionRequest = VNRecognizeAnimalsRequest [self] request, error in
if let results = request.results as? [VNRecognizedObjectObservation]
for result in results
let animals = result.labels
for animal in animals
if animal.identifier == "Dog"
DispatchQueue.main.async
uiImages.append(uiImage)
print("dog detected")
continue
PhotoLibraryView.swift
import SwiftUI
struct PhotoLibraryView: View
@StateObject var photoLibraryViewModel = PhotoLibraryViewModel()
var body: some View
NavigationView
ZStack
LinearGradient(gradient: Gradient(colors: [Color(#colorLiteral(red: 0.2588235438, green: 0.7568627596, blue: 0.9686274529, alpha: 1)), Color(#colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1))]), startPoint: .top, endPoint: .bottom)
.edgesIgnoringSafeArea(.all)
ScrollView
// Compositional Layout....
LazyVGrid(columns: Array(repeating: GridItem(.flexible(), spacing: 15), count: 3))
ForEach(0..<photoLibraryViewModel.uiImages.count, id: \.self) index in
Image(uiImage: photoLibraryViewModel.uiImages[index])
.resizable()
.frame(width: (screen.width - 60) / 3, height: (screen.width - 60) / 3)
.cornerRadius(13)
.padding(.horizontal)
.navigationTitle("Dog images")
【问题讨论】:
@matt 是对的,您不直接存储 UIImages,因为图像大小非常大。因此,您可以在网格中加载图像时存储 PHAsset 并请求图像 感谢大家的帮助,但是我怎么能在没有数组或 UIImages 的图像上运行VNRecognizeAnimalsRequest
呢?
【参考方案1】:
@Published var uiImages = [UIImage]()
红旗! [UIImage]
一词立即令人怀疑。图像(尤其是直接来自照片)很大。图像数组是耗尽内存的好方法。
您可以保留一组对图像的引用,但不能保留一组实际图像。
【讨论】:
以上是关于从照片 SwiftUI 中获取图像时内存不足的主要内容,如果未能解决你的问题,请参考以下文章