The Challenge of Developing a Birthday Celebration Filter Using ARKit

May 9, 2023 | Tech Talk

Hello. I'm an iOS app developer on the Wadiz app development team.
Recently, Wadizhas ARKitto create Birthday Celebration Filterusing ARKit. I'd like to share the process.

Tech Story: Developing a Birthday Celebration Filter Using ARKit

 

Development Background

If your birthday is coming up soon? You can use the birthday celebration filter feature on Wadiz for three days before and after your birthday.
After granting camera access permission, when you enter the screen, the front camera will recognize your face and a party hat will appear. Press the record button, and Wadizrepresentative characters, Jingook, Genie, and Joy, will appear and strike poses to take photos with you.

This feature was born from a plan to boost Wadiz users' participation in funding through birthday celebration coupons. We aimed to incorporate the fun element of a user participation event into the app.

Tech Story: Developing a Birthday Celebration Filter Using ARKit

Sunglasses are unrelated to the actual service!

 

Face Recognition via ARKit

ARKit is a software framework for creating augmented reality (AR) apps, unveiled at WWDC17. ARKit provides technology that uses the camera and sensors of iOS devices to create virtual worlds based on the real world.
It can track your current location and orientation using the camera, and perform tasks such as object detection and detail extraction.

Tech Story: Developing a Birthday Celebration Filter Using ARKit

Reference: Apple Developer Documentation

 

ARKit's ARSCNView is a SceneKit-based 3D view. ARSCNView processes camera input data in real time to display virtual objects. ARSCNView requires an active session to function, and ARSession settings are configured through ARConfiguration.

The types of ARConfiguration provided by ARKit are as follows. Each configuration enables users to have different AR experiences.

  • ARWorldTrackingConfiguration

  • AR Geo-Tracking Configuration

  • AR Orientation Tracking Configuration

  • ARBodyTrackingConfiguration

  • ARFaceTrackingConfiguration

Among these, ARFaceTrackingConfiguration recognizes faces from the information received via the camera and provides facial information through FaceAnchor. Then, in the ARSCNViewDelegate functions,

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode?

This allows you to create new nodes based on new ARAnchors detected by ARKit.

func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
    guard let device = MTLCreateSystemDefaultDevice() else { return nil }
    let faceGeometry = ARSCNFaceGeometry(device: device)

    let faceNode = FaceFilterNode(geometry: faceGeometry)
    let headNode = HeadNode(with: "filter_hat")
    let eyeNode = EyeNode(with: "filter_sunglasses")
    faceNode.addChildNode(headNode)
    faceNode.addChildNode(eyeNode)

    return faceNode
}

The EyeNode and HeadNode are defined by inheriting from SCNNode as shown below. They are responsible for applying filter images to the head and eye positions.

class EyeNode: SCNNode, FilterNodeElementProtocol {
    init(with imageName: String, width: CGFloat = 0.2) {
        super.init()
        setup(with: imageName, width: width)
    }
    func updatePosition(for vectors: [vector_float3]) {
        let eyeIndex = 12
        if let newPosition = vectors[safe: eyeIndex] {
            self.position = SCNVector3(newPosition)
        }
    }

    //...
}

The vectors array received as a parameter in the updatePosition function is FaceAnchor's ARFaceGeometry an array containing the vertex elements of each face provided by,

  • The center of the eye

  • Center of the mouth

  • tip of the nose

It provides detailed information on approximately 1,220 elements.

 

Once you've created a new node like this, you need to update it every frame. Another ARSCNViewDelegate function,

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor)

This is handling it.

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
    guard let faceAnchor = anchor as? ARFaceAnchor,
    let filterNode = node as? FilterNode else { return }

    filterNode.geometry.update(from: faceAnchor.geometry)
    let vertices = anchor.geometry.vertices
    filterNode.subNodes.forEach { $0.updatePosition(for: vertices) }
}

This process updates the new geometry information in the FilterNode created to generate the filter image, and uses the newly acquired vector data to update the positions and orientations of the EyeNode and HeadNode.

Then, you'll get a cool filter feature like this. Pretty simple, right? 😁

Tech Story: Developing a Birthday Celebration Filter Using ARKit

 

While working on the project

While working on the project, there were both interesting and disappointing aspects!
ARKit's ARFaceTrackingConfiguration only supports the front camera. To enable rear camera support, you'd need to implement face feature detection for each frame using frameworks like Vision Framework. It was disappointing because this posed practical difficulties.

There are also areas I'd like to develop further. Did you notice that both the sunglasses and the conical hat are 2D elements? If I had done 3D modeling, it could have provided a more vivid AR experience regardless of the angle. I want to continue the project and add 3D elements.

The camera recording feature and ARKit implementation I worked on this time aren't common experiences for many developers. Implementing it from scratch, without relying on familiar frameworks or libraries, was quite challenging at first. But I enjoyed creating my own ground rules—figuring out how to implement things quickly and what to watch out for.
As a junior developer, I think this was a truly valuable experience!

Still have questions? 👀

Curious about the app development team's culture? 👉 Click
The app development team also built the Instagram sharing feature! 👉Click

👇 Click the tag to see posts with the same keyword.

Tech Talk

Tech Talk

Technical Organization

We create essential services that empower everyone to take on challenges and experience something new.