Post not yet marked as solved
Post marked as unsolved with 2 replies, 1,286 views
Hello,
I'm building an AR image tracking application that detects some images and play video on each image.
In most cases there is no problem, but some images are not detected.
So, I tried these.
when I init ARReferenceImage, I set the physicalWidth value to be same as the actual size. (It is 10cm)
I change the contrast of image.
But it didn't work very well.
I would be very grateful if you could give me a small hint.
Here is my code.
///Model
struct PhotoCard {
var imageName: String
var image: UIImage
var videoURL: URL
}
struct TrackingItem {
var referenceImage: ARReferenceImage
var videoURL: URL
}
final class CameraModel {
private let dataManger = DataManger.shared()
private func getPhotoCards() -> [PhotoCard] {
//get photocard from server
return dataManger.getPhotoCards()
}
func trackingItems() -> [TrackingItem] {
let photocards: [PhotoCard] = getPhotoCards()
var items: [TrackingItem] = []
photocards.forEach { photoCard in
guard let cgImage = photoCard.image.cgImage else { return }
let referenceImage = ARReferenceImage(cgImage, orientation: .up, physicalWidth: 0.1)
referenceImage.name = photoCard.imageName
let item = TrackingItem(referenceImage: referenceImage, videoURL: photoCard.videoURL)
items.append(item)
}
return items
}
}
///viewController
import SceneKit
import ARKit
import AVFoundation
import SpriteKit
import RxSwift
final class CameraViewController: VideoPlayerPresentableViewController, ARSCNViewDelegate {
@IBOutlet private var sceneView: ARSCNView!
private let model = CameraModel()
private var data: [TrackingItem] = []
override func viewDidLoad() {
super.viewDidLoad()
setupSceneView()
setupTrackingConfiguration()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneView.session.pause()
}
private func setupSceneView() {
sceneView.delegate = self
let scene = SCNScene(named: "SceneAssets.scnassets/photocard.scn")!
sceneView.scene = scene
}
private func setupTrackingConfiguration() {
data = model.trackingItems()
let configuration = ARImageTrackingConfiguration()
configuration.isAutoFocusEnabled = true
let trackingImages = data.map { $0.referenceImage }
configuration.trackingImages = Set(trackingImages)
configuration.maximumNumberOfTrackedImages = trackingImages.count
sceneView.session.run(configuration)
}
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let current = data.first(where: { $0.referenceImage.name == imageName }) else { return }
let referenceImage = imageAnchor.referenceImage
let planeGeometry = SCNPlane(width: referenceImage.physicalSize.width,
height: referenceImage.physicalSize.height)
let plane = SCNNode(geometry: planeGeometry)
plane.transform = SCNMatrix4MakeRotation(-.pi/2, 1, 0, 0)
let videoSceneAndPlayer = makeVideoSceneAndPlayer(with: current.videoURL)
planeGeometry.materials.first?.diffuse.contents = videoSceneAndPlayer.0
node.addChildNode(plane)
anchorAndPlayerMap[anchor] = videoSceneAndPlayer.1
model.updatePlayYN(of: current)
}
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let imageAnchor = anchor as? ARImageAnchor,
imageAnchor.isTracked == false else { return }
sceneView.session.remove(anchor: anchor)
}
private func makeVideoSceneAndPlayer(with url: URL) -> (SKScene, AVPlayer) {
let size = CGSize(width: 500, height: 500)
let scene = SKScene(size: size)
scene.scaleMode = .aspectFit
let player = AVPlayer(url: url)
let videoSpriteNode = SKVideoNode(avPlayer: player)
videoSpriteNode.position = CGPoint(x: size.width/2, y: size.height/2)
videoSpriteNode.size = size
videoSpriteNode.yScale = -1
scene.addChild(videoSpriteNode)
addObserver(of: player)
player.play()
return (scene, player)
}
}