So lösen Sie das Problem mit dem Vision-Framework in Swift, das zu viel Hintergrund anzeigtIOS

Programmierung für iOS
Anonymous
 So lösen Sie das Problem mit dem Vision-Framework in Swift, das zu viel Hintergrund anzeigt

Post by Anonymous »

Ich arbeite an einer Funktion für eine Photo Booth-App in Swift, um den Hintergrund mithilfe des Vision-Frameworks und AVFoundation zu ersetzen. Ich habe jedoch ein Problem, bei dem der ursprüngliche Hintergrund mehr zu sehen ist, als er sollte, oder vielleicht nicht richtig ausgerichtet ist.
Hier ist ein Bild des Problems, das ich sehe:
Image

Hier ist mein Code für die Verarbeitung der endgültigen Vorschau:

Code: Select all

func processFrameForFinalImage(
pixelBuffer: CVPixelBuffer,
orientation: CGImagePropertyOrientation,
quality: VNGeneratePersonSegmentationRequest.QualityLevel,
showInPreview: Bool,
completion: @escaping (UIImage?) ->  Void
) {

let request = VNGeneratePersonSegmentationRequest()
request.qualityLevel = quality
request.outputPixelFormat = kCVPixelFormatType_OneComponent8

let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer,
orientation: .up,
options: [:])

DispatchQueue.global(qos: .userInitiated).async {
do {
try handler.perform([request])
guard let maskBuffer = request.results?.first?.pixelBuffer else {
DispatchQueue.main.async { completion(nil) }
return
}

// Convert buffers to CIImage and apply consistent orientation
let cameraImage = CIImage(cvPixelBuffer: pixelBuffer).oriented(orientation)
var maskImage = CIImage(cvPixelBuffer: maskBuffer).oriented(orientation)

maskImage = maskImage.applyingFilter("CIGaussianBlur", parameters: [
kCIInputRadiusKey: 2.0
])

if let erode = CIFilter(name: "CIMorphologyMinimum",
parameters: [kCIInputImageKey: maskImage,
"inputRadius": 1.0]),
let output = erode.outputImage {
maskImage = output
}

// Increase contrast to push mask values toward 0 or 1
if let controls = CIFilter(name: "CIColorControls") {
controls.setValue(maskImage, forKey: kCIInputImageKey)
controls.setValue(1.2, forKey: kCIInputContrastKey)
controls.setValue(0.0, forKey: kCIInputSaturationKey)
if let output = controls.outputImage {
maskImage = output
}
}

// Clamp to [0, 1]
if let clamp = CIFilter(name: "CIColorClamp") {
clamp.setValue(maskImage, forKey: kCIInputImageKey)
clamp.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputMinComponents")
clamp.setValue(CIVector(x: 1, y: 1, z: 1, w: 1), forKey: "inputMaxComponents")
if let output = clamp.outputImage {
maskImage = output
}
}

var composited = cameraImage

if self.isBackgroundReplacementEnabled,
let bgImage = self.backgroundImage {

// Scale background to match camera image size
var bg = bgImage.transformed(by: CGAffineTransform(
scaleX: cameraImage.extent.width / bgImage.extent.width,
y: cameraImage.extent.height / bgImage.extent.height
))

// Align background origin
let dx = cameraImage.extent.origin.x - bg.extent.origin.x
let dy = cameraImage.extent.origin.y - bg.extent.origin.y
bg = bg.transformed(by: CGAffineTransform(translationX: dx, y: dy))

// Blend the person (camera) over background using mask
composited = cameraImage.applyingFilter("CIBlendWithMask", parameters: [
kCIInputBackgroundImageKey: bg,
kCIInputMaskImageKey: maskImage
])
}

// Prepare for preview output
let finalImage = self.aspectFillImage(composited, targetSize: self.previewLayer.bounds.size)
guard let cgImage = self.ciContext.createCGImage(finalImage, from: finalImage.extent) else {
DispatchQueue.main.async { completion(nil) }
return
}

let uiImage = UIImage(cgImage: cgImage)

DispatchQueue.main.async {
if showInPreview {
self.previewLayer.contents = cgImage
}
completion(uiImage)
}

} catch {
print("Segmentation error: \(error)")
DispatchQueue.main.async { completion(nil) }
}
}
}
Und das ist der Code zum Einrichten der Kamera, ich verwende nur die Frontkamera:

Code: Select all

func setupCamera() {
session.beginConfiguration()
session.sessionPreset = .medium
guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, for:  .video, position: .front),
let input = try? AVCaptureDeviceInput(device: device) else {
print("⚠️ Could not create camera input")
return
}

if session.canAddInput(input) {
session.addInput(input)
}

let output = AVCaptureVideoDataOutput()
output.setSampleBufferDelegate(self, queue: DispatchQueue(label: "camera.frame.queue"))
if session.canAddOutput(output) {
session.addOutput(output)
}

session.commitConfiguration()
}
Ich bin mir nicht sicher, was ich falsch mache. Ich denke, es könnte etwas mit der Ausrichtung zu tun haben.
Eine Sache, die mir auffällt, ist, dass ich mit VNImageRequestHandler nur mit der Ausrichtung nach oben gute Ergebnisse erzielen kann. Ursprünglich habe ich versucht, den gleichen Wert zu übergeben wie den, den ich „processFrameForFinalImage“ nenne, nämlich leftMirrored, aber das führte zu einer falschen Position der Maske.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post