Share
Embed
Transcript
87 slides
-
func createVideoNode(size: CGFloat, videoUrl: URL) -> SCNNode { // αΠζ͕খ͍͞ͱϏσΦͷղ૾͕མͪΔ
let skSceneSize = CGSize(width: 1024, height: 1024) // AVPlayerੜ let avPlayer = AVPlayer(url: videoUrl) // SKVideoNodeੜ let skVideoNode = SKVideoNode(avPlayer: avPlayer) skVideoNode.position = CGPoint(x: skSceneSize.width / 2.0, y: skSceneSize.height / 2.0) skVideoNode.size = skSceneSize skVideoNode.yScale = -1.0 // ࠲ඪܥΛ্Լٯʹ͢Δ skVideoNode.play() // SKSceneੜ let skScene = SKScene(size: skSceneSize) skScene.addChild(skVideoNode) // SCNMaterialੜ let material = SCNMaterial() material.diffuse.contents = skScene material.isDoubleSided = true // SCNNodeੜ let node = SCNNode() // SCNPlane(=SCNGeometryΛܧঝͨ͠Ϋϥε)ੜ node.geometry = SCNPlane(width: size, height: size) node.geometry?.materials = [material] node.scale = SCNVector3(1, 0.5625, 1) return node } !24 "71MBZFS 4,7JEFP/PEF 4,4DFOF 4$/.BUFSJBM 4$/(FPNFUSZ 4$//PEF -
func createVideoNode(size: CGFloat, videoUrl: URL) -> SCNNode { // αΠζ͕খ͍͞ͱϏσΦͷղ૾͕མͪΔ
let skSceneSize = CGSize(width: 1024, height: 1024) // AVPlayerੜ let avPlayer = AVPlayer(url: videoUrl) // SKVideoNodeੜ let skVideoNode = SKVideoNode(avPlayer: avPlayer) skVideoNode.position = CGPoint(x: skSceneSize.width / 2.0, y: skSceneSize.height / 2.0) skVideoNode.size = skSceneSize skVideoNode.yScale = -1.0 // ࠲ඪܥΛ্Լٯʹ͢Δ skVideoNode.play() // SKSceneੜ let skScene = SKScene(size: skSceneSize) skScene.addChild(skVideoNode) // SCNMaterialੜ let material = SCNMaterial() material.diffuse.contents = skScene material.isDoubleSided = true // SCNNodeੜ let node = SCNNode() // SCNPlane(=SCNGeometryΛܧঝͨ͠Ϋϥε)ੜ node.geometry = SCNPlane(width: size, height: size) node.geometry?.materials = [material] node.scale = SCNVector3(1, 0.5625, 1) return node } !25 "71MBZFS 4,7JEFP/PEF 4,4DFOF 4$/.BUFSJBM 4$/(FPNFUSZ 4$//PEF -
func createVideoNode(size: CGFloat, videoUrl: URL) -> SCNNode { // αΠζ͕খ͍͞ͱϏσΦͷղ૾͕མͪΔ
let skSceneSize = CGSize(width: 1024, height: 1024) // AVPlayerੜ let avPlayer = AVPlayer(url: videoUrl) // SKVideoNodeੜ let skVideoNode = SKVideoNode(avPlayer: avPlayer) skVideoNode.position = CGPoint(x: skSceneSize.width / 2.0, y: skSceneSize.height / 2.0) skVideoNode.size = skSceneSize skVideoNode.yScale = -1.0 // ࠲ඪܥΛ্Լٯʹ͢Δ skVideoNode.play() // SKSceneੜ let skScene = SKScene(size: skSceneSize) skScene.addChild(skVideoNode) // SCNMaterialੜ let material = SCNMaterial() material.diffuse.contents = skScene material.isDoubleSided = true // SCNNodeੜ let node = SCNNode() // SCNPlane(=SCNGeometryΛܧঝͨ͠Ϋϥε)ੜ node.geometry = SCNPlane(width: size, height: size) node.geometry?.materials = [material] node.scale = SCNVector3(1, 0.5625, 1) return node } !26 "71MBZFS 4,7JEFP/PEF 4,4DFOF 4$/.BUFSJBM 4$/(FPNFUSZ 4$//PEF -
func createVideoNode(size: CGFloat, videoUrl: URL) -> SCNNode { // αΠζ͕খ͍͞ͱϏσΦͷղ૾͕མͪΔ
let skSceneSize = CGSize(width: 1024, height: 1024) // AVPlayerੜ let avPlayer = AVPlayer(url: videoUrl) // SKVideoNodeੜ let skVideoNode = SKVideoNode(avPlayer: avPlayer) skVideoNode.position = CGPoint(x: skSceneSize.width / 2.0, y: skSceneSize.height / 2.0) skVideoNode.size = skSceneSize skVideoNode.yScale = -1.0 // ࠲ඪܥΛ্Լٯʹ͢Δ skVideoNode.play() // SKSceneੜ let skScene = SKScene(size: skSceneSize) skScene.addChild(skVideoNode) // SCNMaterialੜ let material = SCNMaterial() material.diffuse.contents = skScene material.isDoubleSided = true // SCNNodeੜ let node = SCNNode() // SCNPlane(=SCNGeometryΛܧঝͨ͠Ϋϥε)ੜ node.geometry = SCNPlane(width: size, height: size) node.geometry?.materials = [material] node.scale = SCNVector3(1, 0.5625, 1) return node } !27 "71MBZFS 4,7JEFP/PEF 4,4DFOF 4$/.BUFSJBM 4$/(FPNFUSZ 4$//PEF -
func createVideoNode(size: CGFloat, videoUrl: URL) -> SCNNode { // αΠζ͕খ͍͞ͱϏσΦͷղ૾͕མͪΔ
let skSceneSize = CGSize(width: 1024, height: 1024) // AVPlayerੜ let avPlayer = AVPlayer(url: videoUrl) // SKVideoNodeੜ let skVideoNode = SKVideoNode(avPlayer: avPlayer) skVideoNode.position = CGPoint(x: skSceneSize.width / 2.0, y: skSceneSize.height / 2.0) skVideoNode.size = skSceneSize skVideoNode.yScale = -1.0 // ࠲ඪܥΛ্Լٯʹ͢Δ skVideoNode.play() // SKSceneੜ let skScene = SKScene(size: skSceneSize) skScene.addChild(skVideoNode) // SCNMaterialੜ let material = SCNMaterial() material.diffuse.contents = skScene material.isDoubleSided = true // SCNNodeੜ let node = SCNNode() // SCNPlane(=SCNGeometryΛܧঝͨ͠Ϋϥε)ੜ node.geometry = SCNPlane(width: size, height: size) node.geometry?.materials = [material] node.scale = SCNVector3(1, 0.5625, 1) return node } !28 "71MBZFS 4,7JEFP/PEF 4,4DFOF 4$/.BUFSJBM 4$/(FPNFUSZ 4$//PEF -
func createVideoNode(size: CGFloat, videoUrl: URL) -> SCNNode { // αΠζ͕খ͍͞ͱϏσΦͷղ૾͕མͪΔ
let skSceneSize = CGSize(width: 1024, height: 1024) // AVPlayerੜ let avPlayer = AVPlayer(url: videoUrl) // SKVideoNodeੜ let skVideoNode = SKVideoNode(avPlayer: avPlayer) skVideoNode.position = CGPoint(x: skSceneSize.width / 2.0, y: skSceneSize.height / 2.0) skVideoNode.size = skSceneSize skVideoNode.yScale = -1.0 // ࠲ඪܥΛ্Լٯʹ͢Δ skVideoNode.play() // SKSceneੜ let skScene = SKScene(size: skSceneSize) skScene.addChild(skVideoNode) // SCNMaterialੜ let material = SCNMaterial() material.diffuse.contents = skScene material.isDoubleSided = true // SCNNodeੜ let node = SCNNode() // SCNPlane(=SCNGeometryΛܧঝͨ͠Ϋϥε)ੜ node.geometry = SCNPlane(width: size, height: size) node.geometry?.materials = [material] node.scale = SCNVector3(1, 0.5625, 1) return node } !29 "71MBZFS 4,7JEFP/PEF 4,4DFOF 4$/.BUFSJBM 4$/(FPNFUSZ 4$//PEF -
override func viewDidLoad() { super.viewDidLoad() sceneView.delegate = self sceneView.scene =
SCNScene() let videoUrl = Bundle.main.url(forResource: "video001", withExtension: "mp4")! let videoNode = createVideoNode(size: 1, videoUrl: videoUrl) videoNode.position = SCNVector3(0, 0, -3.0) sceneView.scene.rootNode.addChildNode(videoNode) } !30 -
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() } !40 -
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() } !42 -
private let videoOutput = AVPlayerItemVideoOutput.init(pixelBufferAttributes: [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
] as [String: Any]) func setupPlayer(url: URL) { player = AVPlayer(url: url) guard let player = player, let videoItem = player.currentItem else { return } videoItem.add(videoOutput) } 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) } !43 -
private let videoOutput = AVPlayerItemVideoOutput.init(pixelBufferAttributes: [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
] as [String: Any]) func setupPlayer(url: URL) { player = AVPlayer(url: url) guard let player = player, let videoItem = player.currentItem else { return } videoItem.add(videoOutput) } 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) } !44 -
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() } !46 -
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() } !48 -
.FUBMγΣʔμʔ !52 छྨ ֓ཁ 7FSUFY ֤ͷ࠲ඪใΛฦ٫͢Δ'VODUJPO 'SBHNFOU ֤ͷ৭ใΛฦ٫͢Δ'VODUJPO $PNQVUF ,FSOFM
େنͳσʔλΛฒྻॲཧ͢Δࡍͷ൚༻తͳΧελϜ 'VODUJPO -
#include <metal_stdlib> using namespace metal; /// - SeeAlso: http://www.fundza.com/rman_shaders/smoothstep/index.html kernel
void ChromaKeyFilter( // ೖྗը૾ใ texture2d<float, access::read> inTexture [[ texture(0) ]], // ग़ྗը૾ใ texture2d<float, access::write> outTexture [[ texture(1) ]], // ϚεΫରͷ const device float *colorRed [[ buffer(0) ]], // ϚεΫରͷ const device float *colorGreen [[ buffer(1) ]], // ϚεΫରͷ੨ const device float *colorBlue [[ buffer(2) ]], // ಁա͕0-1ͷྖҬͷԼݶ const device float *threshold [[ buffer(3) ]], // ಁա͕0-1ͷྖҬͷԼݶ͔Β্ݶ·Ͱͷઈର const device float *smoothing [[ buffer(4) ]], // ࠲ඪใ uint2 gid [[ thread_position_in_grid ]]) { const float4 inColor = inTexture.read(gid); // maskͷରͷ৭ɻ৭Λಁա͢ΔͨΊmaskColorfloat3(0, 1, 0)ʹͳΔ const float3 maskColor = float3(*colorRed, *colorGreen, *colorBlue); // RGB͔ΒYͷࣹ const float3 YVector = float3(0.2989, 0.5866, 0.1145); // maskColor(৭)ΛYCrCbม const float maskY = dot(maskColor, YVector); const float maskCr = 0.7131 * (maskColor.r - maskY); const float maskCb = 0.5647 * (maskColor.b - maskY); // ࠲ඪͷRGBΛYCrCbม const float Y = dot(inColor.rgb, YVector); const float Cr = 0.7131 * (inColor.r - Y); const float Cb = 0.5647 * (inColor.b - Y); // YCrCbɺᮢɺ৭ͱͷڑʹΑΓಁաΛࢉग़ const float alpha = smoothstep( *threshold, *threshold + *smoothing, distance(float2(Cr, Cb), float2(maskCr, maskCb)) ); // ࠲ඪͷRGBΛࢉग़ͨ͠ಁաͰग़ྗ͢Δ৭Λܭࢉ const float4 outColor = alpha * float4(inColor.r, inColor.g, inColor.b, 1.0); outTexture.write(outColor, gid); } !54 -
#include <metal_stdlib> using namespace metal; /// - SeeAlso: http://www.fundza.com/rman_shaders/smoothstep/index.html kernel
void ChromaKeyFilter( // ೖྗը૾ใ texture2d<float, access::read> inTexture [[ texture(0) ]], // ग़ྗը૾ใ texture2d<float, access::write> outTexture [[ texture(1) ]], // ϚεΫରͷ const device float *colorRed [[ buffer(0) ]], // ϚεΫରͷ const device float *colorGreen [[ buffer(1) ]], // ϚεΫରͷ੨ const device float *colorBlue [[ buffer(2) ]], // ಁա͕0-1ͷྖҬͷԼݶ const device float *threshold [[ buffer(3) ]], // ಁա͕0-1ͷྖҬͷԼݶ͔Β্ݶ·Ͱͷઈର const device float *smoothing [[ buffer(4) ]], // ࠲ඪใ uint2 gid [[ thread_position_in_grid ]]) { !55 -
{ const float4 inColor = inTexture.read(gid); // maskͷରͷ৭ɻ৭Λಁա͢ΔͨΊmaskColorfloat3(0, 1, 0)ʹͳΔ
const float3 maskColor = float3(*colorRed, *colorGreen, *colorBlue); // RGB͔ΒYͷࣹ const float3 YVector = float3(0.2989, 0.5866, 0.1145); // maskColor(৭)ΛYCrCbม const float maskY = dot(maskColor, YVector); const float maskCr = 0.7131 * (maskColor.r - maskY); const float maskCb = 0.5647 * (maskColor.b - maskY); // ࠲ඪͷRGBΛYCrCbม const float Y = dot(inColor.rgb, YVector); const float Cr = 0.7131 * (inColor.r - Y); const float Cb = 0.5647 * (inColor.b - Y); // YCrCbɺᮢɺ৭ͱͷڑʹΑΓಁաΛࢉग़ const float alpha = smoothstep( *threshold, *threshold + *smoothing, distance(float2(Cr, Cb), float2(maskCr, maskCb)) ); // ࠲ඪͷRGBΛࢉग़ͨ͠ಁաͰग़ྗ͢Δ৭Λܭࢉ const float4 outColor = alpha * float4(inColor.r, inColor.g, inColor.b, 1.0); outTexture.write(outColor, gid); } !56 -
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() } !67 -
override func draw(_ dirtyRect: CGRect) { guard let device =
device, let drawable = currentDrawable, let tempDrawable = bufferMtkView.currentDrawable, let image = makeCurrentViewImage() 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() } !68 -
func makeCurrentViewImage(view: UIView) -> CIImage? { UIGraphicsBeginImageContextWithOptions(view.frame.size, true, 0) view.drawHierarchy(in:
view.bounds, afterScreenUpdates: false) let image = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext(); return CIImage(image: image) } !69 -
ؔ࿈ใɾΫϨδοτ άϦʔϯόοΫΞΠυϧɹ.JLB 3JLB IUUQTXXXZPVUVCFDPNXBUDI WX0OTBMKG"P )PMPHSBQIJD1SPKFDUJPO IUUQTXXXTIBEFSUPZDPNWJFX.UK9[N <J04><"3,JU>ۙॴͷறंͰɺେܕσΟεϓϨΠͰϏσΦΛݟΔʂ IUUQTEFWDMBTTNFUIPEKQTNBSUQIPOFJQIPOFJPTBSLJUWJEFP "3,JUͷͨΊͷ%ֶ
IUUQTRJJUBDPNLCPZJUFNTGFGEEBDGC "3,JU4QSJUF,JUTFUQJYFM#V⒎FS"UUSJCVUFTUP4,7JEFP/PEFPSNBLFUSBOTQBSFOUQJYFMTJOWJEFP DISPNBLFZF⒎FDU BOPUIFSXBZ IUUQTTUBDLPWFSqPXDPNRVFTUJPOTBSLJUTQSJUFLJUTFUQJYFMCV⒎FSBUUSJCVUFTUPTLWJEFPOPEFPSNBLFUSBOTQBSFOU )&7$7JEFPXJUI"MQIB IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED !80 -
!86 ΫϩϚΩʔॲཧ$*'JMUFSΛDBQUVSF0VUQVU @EJE0VUQVUGSPN Ͱద༻ 4,&⒎FDU/PEFʹΫϩϚΩʔॲཧ$*'JMUFSઃఆ 4$/.BUFSJBMͷTIBEFS.PEJpFSTʹΫϩϚΩʔγΣʔμʔॲཧઃఆ
4$/.BUFSJBMʹΞϧϑΝઃఆγΣʔμʔॲཧɺUSBOTQBSFOUDPOUFOUTʹϚεΫಈըઃఆ όοϑΝྖҬʹΫϩϚΩʔγΣʔμʔద༻݁ՌΛอ࣋͠ඳըʹ༻