iOS ARKit Eğitimi: Çıplak Parmaklarla Havada Çizim Yapma
Yayınlanan: 2022-03-11Apple geçtiğimiz günlerde ARKit adlı yeni artırılmış gerçeklik (AR) kitaplığını duyurdu. Birçoğu için, önemsenmesi gereken bir teknoloji bozucu değil, başka bir iyi AR kitaplığı gibi görünüyordu. Bununla birlikte, son birkaç yıldaki AR gelişimine bir göz atarsanız, bu tür sonuçlara varmak için çok hızlı olmamalıdır.
Bu yazımızda iOS ARKit kullanarak eğlenceli bir ARKit örnek projesi oluşturacağız. Kullanıcı parmaklarını bir kalem tutuyormuş gibi masaya yerleştirecek, küçük resme dokunacak ve çizmeye başlayacak. Bitirdikten sonra, kullanıcı aşağıdaki animasyonda gösterildiği gibi çizimlerini 3B bir nesneye dönüştürebilecektir. iOS ARKit örneğimizin tam kaynak kodu GitHub'da mevcuttur.
Neden Şimdi iOS ARKit'i Önemsemeliyiz?
Her deneyimli geliştirici, AR'nin eski bir kavram olduğunun muhtemelen farkındadır. AR'nin ilk ciddi gelişimini, geliştiricilerin web kameralarından tek tek karelere eriştiği zamana bağlayabiliriz. O zamanlar uygulamalar genellikle yüzünüzü dönüştürmek için kullanılıyordu. Bununla birlikte, insanlığın yüzleri tavşanlara dönüştürmenin en yakın ihtiyaçlarından biri olmadığını anlaması uzun sürmedi ve kısa süre sonra hype azaldı!
AR'yi faydalı kılmak için her zaman iki önemli teknoloji sıçramasını kaçırdığına inanıyorum: kullanılabilirlik ve daldırma. Diğer AR yutturmacalarını izlediyseniz, bunu fark edeceksiniz. Örneğin, geliştiriciler mobil kameralardan tek tek karelere eriştiğinde AR heyecanı yeniden başladı. Büyük tavşan transformatörlerinin güçlü geri dönüşünün yanı sıra, 3B nesneleri basılı QR kodlarına bırakan bir uygulama dalgası gördük. Ama asla bir kavram olarak yola çıkmadılar. Artırılmış gerçeklik değil, artırılmış QR kodlarıydı.
Sonra Google bizi bir bilim kurgu parçası olan Google Glass ile şaşırttı. Aradan iki yıl geçti ve bu harika ürünün hayata geçmesi beklendiğinde çoktan ölmüştü! Pek çok eleştirmen, Google Glass'ın başarısızlığının nedenlerini analiz ederek, suçu sosyal yönlerden Google'ın ürünü piyasaya sürerkenki sıkıcı yaklaşımına kadar her şeye attı. Bununla birlikte, bu makaleyi belirli bir nedenden dolayı önemsiyoruz - çevreye dalmak. Google Glass, kullanılabilirlik sorununu çözerken, yine de havada çizilen 2 boyutlu bir görüntüden başka bir şey değildi.
Microsoft, Facebook ve Apple gibi teknoloji devleri bu zorlu dersi ezbere öğrendi. Haziran 2017'de Apple, güzel iOS ARKit kitaplığını duyurdu ve daldırmayı birinci önceliği haline getirdi. Telefon tutmak hala büyük bir kullanıcı deneyimi engelleyici, ancak Google Glass'ın dersi bize sorunun donanım olmadığını öğretti.
Çok yakında yeni bir AR hype zirvesine doğru gittiğimize inanıyorum ve bu yeni önemli pivot ile sonunda kendi iç pazarını bularak daha fazla AR uygulama geliştirmesinin ana akım haline gelmesine izin verebilir. Bu aynı zamanda, dışarıdaki her artırılmış gerçeklik uygulama geliştirme şirketinin Apple'ın ekosisteminden ve kullanıcı tabanından yararlanabileceği anlamına geliyor.
Ama yeteri kadar geçmiş, ellerimizi kodla kirletelim ve Apple artırılmış gerçekliğini çalışırken görelim!
ARKit Daldırma Özellikleri
ARKit iki ana özellik sunar; ilki 3 boyutlu uzayda kamera konumu, ikincisi ise yatay düzlem algılamadır. İlkini elde etmek için ARKit, telefonunuzun gerçek 3B uzayda hareket eden bir kamera olduğunu, herhangi bir noktada bir 3B sanal nesneyi düşürmenin gerçek 3B uzayda o noktaya sabitleneceğini varsayar. İkincisine, ARKit tablolar gibi yatay düzlemleri algılar, böylece üzerine nesneler yerleştirebilirsiniz.
Peki ARKit bunu nasıl başarıyor? Bu, Görsel Atalet Odometrisi (VIO) adı verilen bir teknikle yapılır. Endişelenmeyin, tıpkı girişimcilerin başlangıç adlarının arkasındaki kaynağı bulduğunuzda kıkırdadığınız kıkırdama sayısından zevk almaları gibi, araştırmacılar da onlarınkini, ne zaman ortaya çıkacakları herhangi bir terimi deşifre etmeye çalışırken yaptığınız kafa çiziklerinin sayısında bulurlar. icatlarına isim vermek - hadi eğlenmelerine izin verelim ve devam edelim.
VIO, cihazın 3B alanda konumunu izlemek için kamera çerçevelerinin hareket sensörleriyle kaynaştırıldığı bir tekniktir. Kamera çerçevelerinden hareketin izlenmesi, özelliklerin veya başka bir deyişle görüntüdeki yüksek kontrastlı kenar noktalarının (mavi bir vazo ile beyaz bir masa arasındaki kenar gibi) algılanmasıyla yapılır. Bu noktaların bir çerçeveden diğerine göre ne kadar hareket ettiğini tespit ederek, cihazın 3 boyutlu uzayda nerede olduğu tahmin edilebilir. Bu nedenle ARKit, özelliği olmayan beyaz bir duvara yerleştirildiğinde veya cihaz çok hızlı hareket ederek bulanık görüntülere neden olduğunda düzgün çalışmayacaktır.
iOS'ta ARKit'e Başlarken
Bu makalenin yazıldığı tarih itibariyle ARKit, hala beta sürümünde olan iOS 11'in bir parçasıdır. Bu nedenle, başlamak için iPhone 6s veya sonraki sürümlerde iOS 11 Beta'yı ve yeni Xcode Beta'yı indirmeniz gerekir. Yeni > Proje > Artırılmış Gerçeklik Uygulaması'ndan yeni bir ARKit projesine başlayabiliriz. Ancak, bu artırılmış gerçeklik eğitimine, birkaç temel kod bloğu sağlayan ve özellikle uçak tespiti için yardımcı olan resmi Apple ARKit örneğiyle başlamayı daha uygun buldum. Bu örnek kodla başlayalım, önce içindeki ana noktaları açıklayalım ve sonra projemiz için değiştirelim.
Öncelikle hangi motoru kullanacağımızı belirlemeliyiz. ARKit, Sprite SceneKit veya Metal ile kullanılabilir. Apple ARKit örneğinde, Apple tarafından sağlanan bir 3B motor olan iOS SceneKit kullanıyoruz. Ardından, 3B nesnelerimizi oluşturacak bir görünüm oluşturmamız gerekiyor. Bu, ARSCNView
türünde bir görünüm eklenerek yapılır.
ARSCNView
, SceneKit ana görünümünün SCNView
adlı bir alt sınıfıdır, ancak görünümü birkaç kullanışlı özellikle genişletir. Cihazın bu dünyada hareketli bir kamera olduğunu varsayarak, SceneKit alanını gerçek dünyayla otomatik olarak eşleştirirken, cihaz kamerasından gelen canlı video akışını sahne arka planı olarak işler.
ARSCNView
kendi başına AR işleme yapmaz, ancak cihaz kamerasını ve hareket işlemeyi yöneten bir AR oturum nesnesi gerektirir. Bu nedenle, başlamak için yeni bir oturum atamamız gerekiyor:
self.session = ARSession() sceneView.session = session sceneView.delegate = self setupFocusSquare()
Yukarıdaki son satır, kullanıcıya uçak algılama durumunu görsel olarak tanımlamada yardımcı olan bir görsel gösterge ekler. Focus Square, ARKit kitaplığı tarafından değil, örnek kod tarafından sağlanır ve bu örnek kodla başlamamızın ana nedenlerinden biridir. Bununla ilgili daha fazla bilgiyi örnek kodda bulunan beni oku dosyasında bulabilirsiniz. Aşağıdaki görüntü, bir masaya yansıtılan bir odak karesini göstermektedir:
Bir sonraki adım ARKit oturumunu başlatmaktır. Kullanıcıyı artık izlemiyorsak önceki oturum bilgilerini kullanamayacağımız için, görünüm her göründüğünde oturumu yeniden başlatmak mantıklıdır. Bu nedenle, oturumu viewDidAppear'da başlatacağız:
override func viewDidAppear(_ animated: Bool) { let configuration = ARWorldTrackingSessionConfiguration() configuration.planeDetection = .horizontal session.run(configuration, options: [.resetTracking, .removeExistingAnchors]) }
Yukarıdaki kodda, yatay düzlemleri algılamak için ARKit oturum yapılandırmasını ayarlayarak başlıyoruz. Bu makaleyi yazarken Apple bunun dışında seçenekler sunmuyor. Ancak görünüşe göre, gelecekte daha karmaşık nesneleri tespit etmeyi ima ediyor. Ardından oturumu çalıştırmaya başlıyoruz ve izlemeyi sıfırladığımızdan emin oluyoruz.
Son olarak, kamera konumu, yani gerçek cihaz yönü veya konumu her değiştiğinde Odak Karesini güncellememiz gerekir. Bu, 3B motorun her yeni çerçevesinin oluşturulacağı her seferinde çağrılan SCNView'ın oluşturucu temsilci işlevinde yapılabilir:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { updateFocusSquare() }
Bu noktada, uygulamayı çalıştırırsanız, yatay bir düzlem arayan kamera akışı üzerinde odak karesini görmelisiniz. Bir sonraki bölümde, düzlemlerin nasıl tespit edildiğini ve buna göre odak karesini nasıl konumlandırabileceğimizi anlatacağız.
ARKit'te Uçak Algılama
ARKit yeni uçakları algılayabilir, mevcut uçakları güncelleyebilir veya kaldırabilir. Düzlemleri kullanışlı bir şekilde işlemek için, düzlem konumu bilgisini ve odak karesine bir referansı tutan bazı yapay SceneKit düğümü oluşturacağız. Düzlemler X ve Z yönünde tanımlanır, burada Y yüzeyin normalidir, yani düzlemde yazdırılmış gibi görünmesini istiyorsak çizim düğüm konumlarımızı her zaman düzlemin aynı Y değeri içinde tutmalıyız. .
Uçak tespiti, ARKit tarafından sağlanan geri arama işlevleri aracılığıyla yapılır. Örneğin, yeni bir düzlem algılandığında aşağıdaki geri arama işlevi çağrılır:
var planes = [ARPlaneAnchor: Plane]() func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { if let planeAnchor = anchor as? ARPlaneAnchor { serialQueue.async { self.addPlane(node: node, anchor: planeAnchor) self.virtualObjectManager.checkIfObjectShouldMoveOntoPlane(anchor: planeAnchor, planeAnchorNode: node) } } } func addPlane(node: SCNNode, anchor: ARPlaneAnchor) { let plane = Plane(anchor) planes[anchor] = plane node.addChildNode(plane) } ... class Plane: SCNNode { var anchor: ARPlaneAnchor var focusSquare: FocusSquare? init(_ anchor: ARPlaneAnchor) { self.anchor = anchor super.init() } ... }
Geri arama işlevi bize anchor
ve node
olmak üzere iki parametre sağlar. node
, düzlemin tam konumuna ve yönüne yerleştirilmiş normal bir SceneKit düğümüdür. Geometrisi yoktur, bu yüzden görünmezdir. Bunu, aynı zamanda görünmez olan ancak çapadaki düzlem oryantasyonu ve konumu hakkında bilgi tutan kendi düzlem anchor
eklemek için kullanırız.
Peki ARPlaneAnchor
konum ve yön nasıl kaydedilir? Konum, yön ve ölçeğin tümü 4x4 matrisinde kodlanmıştır. Eğer öğrenmen için bir matematik kavramı seçme şansım varsa, o hiç şüphesiz matrisler olacaktır. Her neyse, bu 4x4 matrisini aşağıdaki gibi tanımlayarak bunu aşabiliriz: 4x4 kayan noktalı sayıları içeren 2 boyutlu parlak bir dizi. Bu sayıları kendi yerel uzayında bir 3B tepe noktası olan v1 ile belirli bir şekilde çarparak, dünya uzayında v1'i temsil eden yeni bir 3B tepe noktası, v2 ile sonuçlanır. Yani, eğer v1 = (1, 0, 0) kendi yerel uzayındaysa ve biz onu dünya uzayında x = 100'e yerleştirmek istiyorsak, v2 dünya uzayına göre (101, 0, 0)'a eşit olacaktır. Tabii ki, bunun arkasındaki matematik, eksenler hakkında rotasyonlar eklediğimizde daha karmaşık hale geliyor, ancak iyi haber şu ki, bunu anlamadan da yapabiliriz (bu kavramın derinlemesine bir açıklaması için bu mükemmel makaledeki ilgili bölümü kontrol etmenizi şiddetle tavsiye ederim. ).
checkIfObjectShouldMoveOntoPlane
zaten çizilmiş nesneler olup olmadığını kontrol eder ve tüm bu nesnelerin y ekseninin yeni algılanan düzlemlerinkiyle eşleşip eşleşmediğini kontrol eder.
Şimdi, önceki bölümde açıklanan updateFocusSquare()
geri dönün. Odak karesini ekranın ortasında tutmak, ancak tespit edilen en yakın düzlemde yansıtmak istiyoruz. Aşağıdaki kod bunu göstermektedir:

func updateFocusSquare() { let worldPos = worldPositionFromScreenPosition(screenCenter, self.sceneView) self.focusSquare?.simdPosition = worldPos } func worldPositionFromScreenPosition(_ position: CGPoint, in sceneView: ARSCNView) -> float3? { let planeHitTestResults = sceneView.hitTest(position, types: .existingPlaneUsingExtent) if let result = planeHitTestResults.first { return result.worldTransform.translation } return nil }
sceneView.hitTest
, bu 2B noktayı alttaki en yakın düzleme yansıtarak ekran görünümünde bir 2B noktaya karşılık gelen gerçek dünya düzlemlerini arar. result.worldTransform
, algılanan düzlemin tüm dönüşüm bilgilerini tutan 4x4'lük bir matrisken, result.worldTransform.translation
yalnızca konumu döndüren kullanışlı bir işlevdir.
Şimdi, ekranda 2B nokta verilen algılanan yüzeylere bir 3B nesneyi bırakmak için ihtiyacımız olan tüm bilgilere sahibiz. Öyleyse çizmeye başlayalım.
Resim çizme
Önce bilgisayarla görmede bir insanın parmağını takip eden şekiller çizme yaklaşımını açıklayalım. Şekil çizme, hareket eden parmak için her yeni konumu algılayarak, o konuma bir tepe noktası bırakarak ve her bir tepe noktasını bir öncekine bağlayarak yapılır. Köşeler basit bir hatla veya düzgün bir çıktıya ihtiyacımız varsa bir Bezier eğrisi ile bağlanabilir.
Basitlik için, çizim için biraz saf bir yaklaşım izleyeceğiz. Parmağın her yeni konumu için, tespit edilen plan üzerine köşeleri yuvarlatılmış ve yüksekliği neredeyse sıfır olan çok küçük bir kutu bırakacağız. Sanki bir noktaymış gibi görünecektir. Kullanıcı çizimi bitirip 3D düğmesini seçtiğinde, bırakılan tüm nesnelerin yüksekliğini kullanıcının parmağının hareketine göre değiştireceğiz.
Aşağıdaki kod, bir noktayı temsil eden PointNode
sınıfını gösterir:
let POINT_SIZE = CGFloat(0.003) let POINT_HEIGHT = CGFloat(0.00001) class PointNode: SCNNode { static var boxGeo: SCNBox? override init() { super.init() if PointNode.boxGeo == nil { PointNode.boxGeo = SCNBox(width: POINT_SIZE, height: POINT_HEIGHT, length: POINT_SIZE, chamferRadius: 0.001) // Setup the material of the point let material = PointNode.boxGeo!.firstMaterial material?.lightingModel = SCNMaterial.LightingModel.blinn material?.diffuse.contents = UIImage(named: "wood-diffuse.jpg") material?.normal.contents = UIImage(named: "wood-normal.png") material?.specular.contents = UIImage(named: "wood-specular.jpg") } let object = SCNNode(geometry: PointNode.boxGeo!) object.transform = SCNMatrix4MakeTranslation(0.0, Float(POINT_HEIGHT) / 2.0, 0.0) self.addChildNode(object) } . . . }
Yukarıdaki kodda, geometriyi y ekseni boyunca yüksekliğin yarısı kadar çevirdiğimizi fark edeceksiniz. Bunun nedeni cismin dibinin her zaman y = 0'da olduğundan emin olmak ve böylece düzlemin üzerinde görünmesini sağlamaktır.
Ardından, SceneKit'in oluşturucu geri çağırma işlevinde, aynı PointNode
sınıfını kullanarak bir kalem ucu gibi davranan bir gösterge çizeceğiz. Çizim etkinse o konuma bir nokta bırakacağız veya 3D modu etkinse çizimi 3D yapıya yükselteceğiz:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { updateFocusSquare() // Setup a dot that represents the virtual pen's tippoint if (self.virtualPenTip == nil) { self.virtualPenTip = PointNode(color: UIColor.red) self.sceneView.scene.rootNode.addChildNode(self.virtualPenTip!) } // Draw if let screenCenterInWorld = worldPositionFromScreenPosition(self.screenCenter, self.sceneView) { // Update virtual pen position self.virtualPenTip?.isHidden = false self.virtualPenTip?.simdPosition = screenCenterInWorld // Draw new point if (self.inDrawMode && !self.virtualObjectManager.pointNodeExistAt(pos: screenCenterInWorld)){ let newPoint = PointNode() self.sceneView.scene.rootNode.addChildNode(newPoint) self.virtualObjectManager.loadVirtualObject(newPoint, to: screenCenterInWorld) } // Convert drawing to 3D if (self.in3DMode ) { if self.trackImageInitialOrigin != nil { DispatchQueue.main.async { let newH = 0.4 * (self.trackImageInitialOrigin!.y - screenCenterInWorld.y) / self.sceneView.frame.height self.virtualObjectManager.setNewHeight(newHeight: newH) } } else { self.trackImageInitialOrigin = screenCenterInWorld } } }
virtualObjectManager
, çizilen noktaları yöneten bir sınıftır. 3D modunda, son konumdan farkı tahmin eder ve bu değerle tüm noktaların yüksekliğini artırır/azaltırız.
Şimdiye kadar, sanal kalemin ekranın ortasında olduğunu varsayarak algılanan yüzey üzerinde çizim yapıyoruz. Şimdi eğlence kısmına geliyoruz—kullanıcının parmağını algılamak ve ekran merkezi yerine onu kullanmak.
Kullanıcının Parmak Ucunu Algılama
Apple'ın iOS 11'de sunduğu harika kitaplıklardan biri de Vision Framework. Bazı bilgisayarlı görme tekniklerini oldukça kullanışlı ve verimli bir şekilde sağlar. Özellikle, artırılmış gerçeklik eğitimimiz için nesne izleme tekniğini kullanacağız. Nesne takibi şu şekilde çalışır: İlk olarak, takip etmek istediğimiz nesne için ona bir görüntü ve görüntü sınırları içinde bir karenin koordinatlarını veriyoruz. Bundan sonra, izlemeyi başlatmak için bazı işlevler çağırırız. Son olarak, o nesnenin konumunun değiştiği yeni bir görüntü ve önceki işlemin analiz sonucunu besliyoruz. Buna göre, bizim için nesnenin yeni konumunu döndürür.
Küçük bir hile kullanacağız. Kullanıcıdan bir kalem tutuyormuş gibi elini masaya koymasını ve küçük resminin kameraya baktığından emin olmasını ve ardından ekrandaki küçük resmine dokunmasını isteyeceğiz. Burada detaylandırılması gereken iki nokta var. İlk olarak, küçük resmin beyaz küçük resim, dış görünüm ve masa arasındaki kontrast yoluyla izlenebilecek kadar benzersiz özellikleri olmalıdır. Bu, daha koyu cilt pigmentinin daha güvenilir izleme ile sonuçlanacağı anlamına gelir. İkincisi, kullanıcı ellerini masanın üzerine koyduğundan ve masayı zaten bir düzlem olarak algıladığımızdan, küçük resmin konumunu 2B görünümden 3B ortama yansıtmak, parmağın neredeyse tam olarak masanın üzerindeki konumunu verecektir. tablo.
Aşağıdaki resim, Vision kitaplığı tarafından algılanabilecek özellik noktalarını göstermektedir:
Küçük resim izlemeyi bir dokunma hareketinde aşağıdaki gibi başlatacağız:
// MARK: Object tracking fileprivate var lastObservation: VNDetectedObjectObservation? var trackImageBoundingBox: CGRect? let trackImageSize = CGFloat(20) @objc private func tapAction(recognizer: UITapGestureRecognizer) { lastObservation = nil let tapLocation = recognizer.location(in: view) // Set up the rect in the image in view coordinate space that we will track let trackImageBoundingBoxOrigin = CGPoint(x: tapLocation.x - trackImageSize / 2, y: tapLocation.y - trackImageSize / 2) trackImageBoundingBox = CGRect(origin: trackImageBoundingBoxOrigin, size: CGSize(width: trackImageSize, height: trackImageSize)) let t = CGAffineTransform(scaleX: 1.0 / self.view.frame.size.width, y: 1.0 / self.view.frame.size.height) let normalizedTrackImageBoundingBox = trackImageBoundingBox!.applying(t) // Transfrom the rect from view space to image space guard let fromViewToCameraImageTransform = self.sceneView.session.currentFrame?.displayTransform(withViewportSize: self.sceneView.frame.size, orientation: UIInterfaceOrientation.portrait).inverted() else { return } var trackImageBoundingBoxInImage = normalizedTrackImageBoundingBox.applying(fromViewToCameraImageTransform) trackImageBoundingBoxInImage.origin.y = 1 - trackImageBoundingBoxInImage.origin.y // Image space uses bottom left as origin while view space uses top left lastObservation = VNDetectedObjectObservation(boundingBox: trackImageBoundingBoxInImage) }
Yukarıdaki en zor kısım, dokunma konumunun UIView koordinat alanından görüntü koordinat alanına nasıl dönüştürüleceğidir. ARKit bize, görüntü koordinat alanından bir görünüm alanı koordinat alanına dönüştüren, ancak tam displayTransform
matrisini sağlar. Peki tersini nasıl yapabiliriz? Matrisin tersini kullanarak. Bu yazıda matematik kullanımını gerçekten en aza indirmeye çalıştım, ancak bazen 3D dünyasında bu kaçınılmazdır.
Ardından, oluşturucuda, parmağın yeni konumunu izlemek için yeni bir görüntü besleyeceğiz:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) { // Track the thumbnail guard let pixelBuffer = self.sceneView.session.currentFrame?.capturedImage, let observation = self.lastObservation else { return } let request = VNTrackObjectRequest(detectedObjectObservation: observation) { [unowned self] request, error in self.handle(request, error: error) } request.trackingLevel = .accurate do { try self.handler.perform([request], on: pixelBuffer) } catch { print(error) } . . . }
Nesne izleme tamamlandığında, küçük resim konumunu güncelleyeceğimiz bir geri arama işlevi çağıracaktır. Tipik olarak, musluk tanıyıcıda yazılan kodun tersidir:
fileprivate func handle(_ request: VNRequest, error: Error?) { DispatchQueue.main.async { guard let newObservation = request.results?.first as? VNDetectedObjectObservation else { return } self.lastObservation = newObservation var trackImageBoundingBoxInImage = newObservation.boundingBox // Transfrom the rect from image space to view space trackImageBoundingBoxInImage.origin.y = 1 - trackImageBoundingBoxInImage.origin.y guard let fromCameraImageToViewTransform = self.sceneView.session.currentFrame?.displayTransform(withViewportSize: self.sceneView.frame.size, orientation: UIInterfaceOrientation.portrait) else { return } let normalizedTrackImageBoundingBox = trackImageBoundingBoxInImage.applying(fromCameraImageToViewTransform) let t = CGAffineTransform(scaleX: self.view.frame.size.width, y: self.view.frame.size.height) let unnormalizedTrackImageBoundingBox = normalizedTrackImageBoundingBox.applying(t) self.trackImageBoundingBox = unnormalizedTrackImageBoundingBox // Get the projection if the location of the tracked image from image space to the nearest detected plane if let trackImageOrigin = self.trackImageBoundingBox?.origin { self.lastFingerWorldPos = self.virtualObjectManager.worldPositionFromScreenPosition(CGPoint(x: trackImageOrigin.x - 20.0, y: trackImageOrigin.y + 40.0), in: self.sceneView) } } }
Son olarak çizim yaparken ekran merkezi yerine self.lastFingerWorldPos
kullanacağız ve işimiz bitti.
ARKit ve Gelecek
Bu yazıda, kullanıcı parmakları ve gerçek hayat tabloları ile etkileşim yoluyla AR'nin nasıl sürükleyici olabileceğini gösterdik. Bilgisayar vizyonundaki daha fazla ilerlemeyle ve araçlara (derinlik kameraları gibi) daha fazla AR-dostu donanım ekleyerek, etrafımızdaki daha fazla nesnenin 3B yapısına erişebiliriz.
Henüz geniş kitlelere duyurulmamış olsa da, Microsoft'un AR'ye özel donanım ile gelişmiş 3D ortam tanıma tekniklerini birleştiren Hololens cihazı aracılığıyla AR yarışını kazanma konusunda ne kadar ciddi olduğunu belirtmekte fayda var. Bu yarışı kimin kazanacağını görmek için bekleyebilir veya şimdi gerçek sürükleyici artırılmış gerçeklik uygulamaları geliştirerek bunun bir parçası olabilirsiniz! Ama lütfen insanlığa bir iyilik yapın ve canlı nesneleri tavşanlara dönüştürmeyin.