Skip to content

Commit

Permalink
person mask and personBlend available.
Browse files Browse the repository at this point in the history
  • Loading branch information
john-rocky committed Dec 21, 2021
1 parent db2789a commit 533a61a
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import PackageDescription

let package = Package(
name: "SemanticImage",
platforms: [
.iOS(.v15)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
Expand Down
100 changes: 99 additions & 1 deletion Sources/SemanticImage/SemanticImage.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,104 @@
public struct SemanticImage {
import Foundation
import Vision
import UIKit

public class SemanticImage {
public private(set) var text = "Hello, World!"

public init() {
}

lazy var personSegmentationRequest = VNGeneratePersonSegmentationRequest()
let ciContext = CIContext()

public func personMaskImage(uiImage:UIImage) -> UIImage? {
let newImage = getCorrectOrientationUIImage(uiImage:uiImage)
guard let ciImage = CIImage(image: newImage) else { print("Image processing failed.Please try with another image."); return nil }
let handler = VNImageRequestHandler(ciImage: ciImage, options: [:])
do {
try handler.perform([personSegmentationRequest])
guard let result = personSegmentationRequest.results?.first
else { print("Image processing failed.Please try with another image.") ; return nil }
let maskCIImage = CIImage(cvPixelBuffer: result.pixelBuffer)
let scaledMask = maskCIImage.resize(as: CGSize(width: ciImage.extent.width, height: ciImage.extent.height))

guard let safeCGImage = ciContext.createCGImage(scaledMask, from: scaledMask.extent) else { print("Image processing failed.Please try with another image.") ; return nil }
let maskUIImage = UIImage(cgImage: safeCGImage)
return maskUIImage

} catch let error {
print("Vision error \(error)")
return nil
}
}


public func blendPersonImage(personUIImage: UIImage, backgroundUIImage: UIImage) -> UIImage? {
let newPersonUIImage = getCorrectOrientationUIImage(uiImage:personUIImage)
let newBackgroundUIImage = getCorrectOrientationUIImage(uiImage:backgroundUIImage)

guard let personCIImage = CIImage(image: newPersonUIImage),
let backgroundCIImage = CIImage(image: newBackgroundUIImage),
let maskUIImage = personMaskImage(uiImage: newPersonUIImage),
let maskCIImage = CIImage(image: maskUIImage) else {
return nil }

let backgroundImageSize = backgroundCIImage.extent
let originalSize = personCIImage.extent
var scale:CGFloat = 1
let widthScale = originalSize.width / backgroundImageSize.width
let heightScale = originalSize.height / backgroundImageSize.height
if widthScale > heightScale {
scale = personCIImage.extent.width / backgroundImageSize.width
} else {
scale = personCIImage.extent.height / backgroundImageSize.height
}

let scaledBG = backgroundCIImage.resize(as: CGSize(width: backgroundCIImage.extent.width*scale, height: backgroundCIImage.extent.height*scale))
let BGCenter = CGPoint(x: scaledBG.extent.width/2, y: scaledBG.extent.height/2)
let originalExtent = personCIImage.extent
let cropRect = CGRect(x: BGCenter.x-(originalExtent.width/2), y: BGCenter.y-(originalExtent.height/2), width: originalExtent.width, height: originalExtent.height)
let croppedBG = scaledBG.cropped(to: cropRect)
let translate = CGAffineTransform(translationX: -croppedBG.extent.minX, y: -croppedBG.extent.minY)
let traslatedBG = croppedBG.transformed(by: translate)
print(traslatedBG.extent)
guard let blended = CIFilter(name: "CIBlendWithMask", parameters: [
kCIInputImageKey: personCIImage,
kCIInputBackgroundImageKey:traslatedBG,
kCIInputMaskImageKey:maskCIImage])?.outputImage else { return nil }
let blendedUIImage = UIImage(ciImage: blended)
return blendedUIImage
}

func scaleMaskImage(maskCIImage:CIImage, originalCIImage:CIImage) -> CIImage {
let scaledMaskCIImage = maskCIImage.resize(as: originalCIImage.extent.size)
return scaledMaskCIImage
}

public func getCorrectOrientationUIImage(uiImage:UIImage) -> UIImage {
var newImage = UIImage()
switch uiImage.imageOrientation.rawValue {
case 1:
guard let orientedCIImage = CIImage(image: uiImage)?.oriented(CGImagePropertyOrientation.down),
let cgImage = ciContext.createCGImage(orientedCIImage, from: orientedCIImage.extent) else { return uiImage}

newImage = UIImage(cgImage: cgImage)
case 3:
guard let orientedCIImage = CIImage(image: uiImage)?.oriented(CGImagePropertyOrientation.right),
let cgImage = ciContext.createCGImage(orientedCIImage, from: orientedCIImage.extent) else { return uiImage}
newImage = UIImage(cgImage: cgImage)
default:
newImage = uiImage
}
return newImage
}
}

extension CIImage {
func resize(as size: CGSize) -> CIImage {
let selfSize = extent.size
let transform = CGAffineTransform(scaleX: size.width / selfSize.width, y: size.height / selfSize.height)
return transformed(by: transform)
}
}

0 comments on commit 533a61a

Please sign in to comment.