質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

0回答

1186閲覧

マーカをスマホカメラで認識すると、マーカの大きさと同じ大きさのクロマキー処理された動画がマーカに重なるように再生される。

water_lily

総合スコア4

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/01/31 03:37

編集2020/01/31 04:44

前提・実現したいこと

タイトルにあるようなアプリケーションを制作しています。
二つの別々のプログラムを一つにまとめることができず困っています。

一つは、あらかじめ登録しておいたマーカ画像をカメラで認識すると、デバイスの画面上ではマーカの大きさと同じ大きさの(クロマキー処理されていない)動画がマーカの二次元平面上で覆いかぶさるように再生されます。
※ハリーポッター の中の人が動く肖像画を想像していただけるとわかりやすいかと思います。
二つ目は、アプリを立ち上げるとともに、(マーカを認識せずとも)クロマキー処理された動画が(マーカの大きさと異なる大きさで)再生されます。

この二つのプログラムを一つにまとめるとタイトルのようなアプリケーションが制作できると思うのですが、うまくいきません。

※MikaRika.MP4が再生したい動画
※ChromaKeyFilterという別ファイルで動画の緑色の部分をクロマキー処理しています

一つ目のコードViewController.swift

import UIKit import SceneKit import ARKit import CoreMedia class ViewController: UIViewController{ @IBOutlet var sceneView: ARSCNView! @IBOutlet weak var instructionLabel: UILabel! private var imageConfiguration: ARImageTrackingConfiguration? private var worldConfiguration: ARWorldTrackingConfiguration? override func viewDidLoad() { super.viewDidLoad() sceneView.delegate = self let scene = SCNScene() sceneView.scene = scene setupObjectDetection() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if let configuration = worldConfiguration { sceneView.debugOptions = .showFeaturePoints sceneView.session.run(configuration) } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) sceneView.session.pause() } private func setupImageDetection() { imageConfiguration = ARImageTrackingConfiguration() guard let referenceImages = ARReferenceImage.referenceImages( inGroupNamed: "AR Images", bundle: nil) else { fatalError("Missing expected asset catalog resources.") } imageConfiguration?.trackingImages = referenceImages } private func setupObjectDetection() { worldConfiguration = ARWorldTrackingConfiguration() worldConfiguration?.detectionObjects = referenceObjects guard let referenceImages = ARReferenceImage.referenceImages( inGroupNamed: "AR Images", bundle: nil) else { fatalError("Missing expected asset catalog resources.") } worldConfiguration?.detectionImages = referenceImages } } extension ViewController: ARSCNViewDelegate { func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { DispatchQueue.main.async { self.instructionLabel.isHidden = true } if let imageAnchor = anchor as? ARImageAnchor { handleFoundImage(imageAnchor, node) } else if let objectAnchor = anchor as? ARObjectAnchor { handleFoundObject(objectAnchor, node) } } private func handleFoundImage(_ imageAnchor: ARImageAnchor, _ node: SCNNode) { let name = imageAnchor.referenceImage.name! print("you found a (name) image") let size = imageAnchor.referenceImage.physicalSize if let videoNode = makeDinosaurVideo(size: size) { node.addChildNode(videoNode) node.opacity = 1 } } private func makeDinosaurVideo(size: CGSize) -> SCNNode? { guard let videoURL = Bundle.main.url(forResource: "MikaRika", withExtension: "mp4") else { return nil } let avPlayerItem = AVPlayerItem(url: videoURL) let avPlayer = AVPlayer(playerItem: avPlayerItem) avPlayer.play() NotificationCenter.default.addObserver( forName: .AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { notification in avPlayer.seek(to: .zero) avPlayer.play() } let avMaterial = SCNMaterial() avMaterial.diffuse.contents = avPlayer let videoPlane = SCNPlane(width: size.width, height: size.height) videoPlane.materials = [avMaterial] let videoNode = SCNNode(geometry: videoPlane) videoNode.eulerAngles.x = -.pi / 2 return videoNode } }

二つ目のコードViewController.swift

class VideoMetalView: MTKView { private let colorSpace = CGColorSpaceCreateDeviceRGB() private let videoOutput = AVPlayerItemVideoOutput.init(pixelBufferAttributes: [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, ] as [String: Any]) private var ciContext: CIContext! private var player: AVPlayer? private var bufferMtkView: MTKView! private var pipelineState: MTLComputePipelineState! private var defaultLibrary: MTLLibrary! private var commandQueue: MTLCommandQueue! private var threadsPerThreadgroup: MTLSize! private var threadgroupsPerGrid: MTLSize! required init(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } required init(frame: CGRect, device: MTLDevice) { ciContext = CIContext(mtlDevice: device) super.init(frame: frame, device: device) framebufferOnly = false isOpaque = false backgroundColor = .clear commandQueue = device.makeCommandQueue() defaultLibrary = device.makeDefaultLibrary()! pipelineState = try! device.makeComputePipelineState(function: defaultLibrary.makeFunction(name: "ChromaKeyFilter")!) threadsPerThreadgroup = MTLSizeMake(16, 16, 1) bufferMtkView = MTKView(frame: frame, device: device) bufferMtkView.translatesAutoresizingMaskIntoConstraints = false bufferMtkView.framebufferOnly = false bufferMtkView.isHidden = true addSubview(bufferMtkView) } func setupPlayer(url: URL) { player = AVPlayer(url: url) player!.actionAtItemEnd = AVPlayer.ActionAtItemEnd.none NotificationCenter.default.addObserver(self, selector: #selector(VideoMetalView.didPlayToEnd), name: NSNotification.Name("AVPlayerItemDidPlayToEndTimeNotification"), object: player!.currentItem) guard let player = player, let videoItem = player.currentItem else { return } videoItem.add(videoOutput) } func play() { player?.play() } func pause() { player?.pause() } func updateThreadgroupsPerGrid() { threadgroupsPerGrid = MTLSizeMake( Int(ceilf(Float(frame.width) / Float(threadsPerThreadgroup.width))), Int(ceilf(Float(frame.height) / Float(threadsPerThreadgroup.height))), 1) } func updateDrawableSize() { drawableSize = bounds.size bufferMtkView.drawableSize = bufferMtkView.bounds.size } override func draw(_ dirtyRect: CGRect) { guard let device = device, let drawable = currentDrawable, let tempDrawable = bufferMtkView.currentDrawable, let image = makeCurrentVideoImage() else { return } ciContext.render(image, to: tempDrawable.texture, commandBuffer: nil, bounds: bounds, colorSpace: colorSpace) colorPixelFormat = tempDrawable.texture.pixelFormat let commandBuffer = commandQueue.makeCommandBuffer()! let commandEncoder = commandBuffer.makeComputeCommandEncoder()! commandEncoder.setComputePipelineState(pipelineState) commandEncoder.setTexture(tempDrawable.texture, index: 0) commandEncoder.setTexture(drawable.texture, index: 1) let factors: [Float] = [ 0, // red 1, // green 0, // blue 0.43, // threshold 0.11 // smoothing ] for i in 0..<factors.count { var factor = factors[i] let size = max(MemoryLayout<Float>.size, 16) let buffer = device.makeBuffer( bytes: &factor, length: size, options: [.storageModeShared] ) commandEncoder.setBuffer(buffer, offset: 0, index: i) } commandEncoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup) commandEncoder.endEncoding() commandBuffer.present(drawable) commandBuffer.commit() } private func makeCurrentVideoImage() -> CIImage? { guard let player = player, let videoItem = player.currentItem else { return nil } let time = videoItem.currentTime() guard videoOutput.hasNewPixelBuffer(forItemTime: time), let pixelBuffer = videoOutput.copyPixelBuffer(forItemTime: time, itemTimeForDisplay: nil) else { return nil } return CIImage(cvPixelBuffer: pixelBuffer) } @objc private func didPlayToEnd(notification: NSNotification) { let item: AVPlayerItem = notification.object as! AVPlayerItem item.seek(to: CMTime.zero, completionHandler: nil) } }

試したこと

いろいろな箇所を追加したり省略したり試みたのですがどうもうまくいかず行き詰まっている状態です。
具体的には、レンダリングに不具合が生じておりアプリ立ち上げから動きません。原因として考えられるのは、レンダリングの命令文が重複して互いに干渉しているのかと考えております。

補足情報(FW/ツールのバージョンなど)

target ios13.1
Xcode 11

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2020/01/31 04:08

「うまくいかない」をもう少し具体的に説明されると回答が得られやすくなるかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問