前提・実現したいこと
swift・プログラミング初心者です。
該当のソースコードは連写機能のカメラアプリのコードです。
そのソースコード内の↓↑の間にUIimageをグレー化し、
一枚ずつ数値を出せるようなコード入れたいのですが…
(関数を追加、UIImageを呼び出して計算…etc)
『試したこと』にあるコードではグレー化、数値化はともにできています。
そこでそれらのコードを使い、グレー化、数値化機能を導入しようと考えています。
ですがそのコードをどのように書き換え、追加すればいいのかわからない状況です。
※↓↑内は『試したこと』欄にあるコードなどを使えないかと思い書いただけです。
どうかご教示お願いいたします。
発生している問題・エラーメッセージ
エラーメッセージ
該当のソースコード
class ViewController: UIViewController ,AVCaptureVideoDataOutputSampleBufferDelegate,AVAudioPlayerDelegate { @IBOutlet weak var previewView: UIImageView! @IBOutlet weak var snapButton: UIButton! @IBOutlet weak var scrollView: UIScrollView! var videoDataOutput: AVCaptureVideoDataOutput? var images:[UIImage] = [] var isShooting = false // 連写中 var counter = 0 var audioPlayer:AVAudioPlayer! // シャッター音用 override func viewDidLoad() { super.viewDidLoad() // シャッター音 let audioPath = Bundle.main.path(forResource: "nc66359", ofType:"wav")! //再生する音源のURL let audioUrl = URL(fileURLWithPath: audioPath) audioPlayer = try! AVAudioPlayer(contentsOf: audioUrl) audioPlayer.delegate = self //デリゲートセット audioPlayer.currentTime = 0 // セッションのインスタンス生成 let captureSession = AVCaptureSession() //設定 // 入力(背面カメラ) let videoDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) videoDevice?.activeVideoMinFrameDuration = CMTimeMake(1, 30)// フレームレート 1/30秒 let videoInput = try! AVCaptureDeviceInput.init(device: videoDevice) captureSession.addInput(videoInput) // 出力(ビデオデータ) videoDataOutput = AVCaptureVideoDataOutput() // ピクセルフォーマット(32bit BGRA) videoDataOutput?.videoSettings = [kCVPixelBufferPixelFormatTypeKey as AnyHashable : Int(kCVPixelFormatType_32BGRA)]//色情報 // キューのブロック中に新しいフレームが来たら削除する videoDataOutput?.alwaysDiscardsLateVideoFrames = true // フレームをキャプチャするためのキューを指定 videoDataOutput?.setSampleBufferDelegate(self, queue: DispatchQueue.main) captureSession.addOutput(videoDataOutput) // クオリティ(1920x1080ピクセル) captureSession.sessionPreset = AVCaptureSessionPreset1920x1080//画像の質 // プレビュー if let videoLayer = AVCaptureVideoPreviewLayer.init(session: captureSession) { videoLayer.frame = previewView.bounds videoLayer.videoGravity = AVLayerVideoGravityResizeAspectFill previewView.layer.addSublayer(videoLayer) } // セッションの開始 DispatchQueue.global(qos: .userInitiated).async { captureSession.startRunning() } } // 新しいキャプチャの追加で呼ばれる(1/30秒に1回) func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) { if counter % 3 == 0 { // 1/10秒だけ処理する if isShooting { // let image:UIImage = captureImage(sampleBuffer) //let image = UIImage(named: "003.jpg") let image = imageFromSampleBuffer(sampleBuffer: sampleBuffer) addImage(image: image) } } counter += 1 } ↓↓↓ func ImageData(){ let image = Image<RGBA<UInt8>>(uiImage: imageView.image!) var x,y:Int x = 0 y = 0 var sum:Int = 0 for x in 0..<photowidth { for y in 0..<photoheight { sum = sum + (image[x,y].gray as AnyObject as! Int) } } var average = sum / photosize print("ave:", average) } ↑↑↑ @IBAction func touchUpButton(_ sender: UIButton) { isShooting = false // 連写終了 audioPlayer.stop() } @IBAction func touchDownButton(_ sender: UIButton) { // 前回撮影の画像を削除 images = [] for imageView in scrollView.subviews { imageView.removeFromSuperview() } isShooting = true // 連写中 audioPlayer.play() } // 連写音の連続再生 func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { if isShooting { audioPlayer.play() } } //CMSampleBufferをUIImageに変換する func imageFromSampleBuffer(sampleBuffer :CMSampleBuffer) -> UIImage { let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)! // サンプルバッファからimageバッファを取り出す // イメージバッファのロック CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) // 画像情報を取得 let base = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)! let bytesPerRow = UInt(CVPixelBufferGetBytesPerRow(imageBuffer)) let width = UInt(CVPixelBufferGetWidth(imageBuffer)) let height = UInt(CVPixelBufferGetHeight(imageBuffer)) // ビットマップコンテキスト作成 let colorSpace = CGColorSpaceCreateDeviceRGB() let bitsPerCompornent = 8 let bitmapInfo = CGBitmapInfo(rawValue: (CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue) as UInt32) let newContext = CGContext(data: base, width: Int(width), height: Int(height), bitsPerComponent: Int(bitsPerCompornent), bytesPerRow: Int(bytesPerRow), space: colorSpace, bitmapInfo: bitmapInfo.rawValue)! as CGContext // 画像作成 let imageRef = newContext.makeImage()! let image = UIImage(cgImage: imageRef, scale: 1.0, orientation: UIImageOrientation.right) // イメージバッファのアンロック CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) return image } func addImage(image: UIImage) { let height:CGFloat = 100 // 基準の高さ let margin = 10 let magnification = height / image.size.height let width = image.size.width * magnification let x = (margin + Int(width)) * images.count let y = margin let imageView = UIImageView(image: image) imageView.frame = CGRect(x: x, y: y, width: Int(width), height: Int(height)) scrollView.addSubview(imageView) let w = x + Int(width) scrollView.contentSize = CGSize(width: CGFloat(w), height: scrollView.frame.size.height) images.append(image) } }
試したこと
import UIKit
import EasyImagy
class ViewController: UIViewController {
override func viewDidLoad() { super.viewDidLoad() // 画面に出る子供の画像はプロジェクトに組み込み済み。 Main.storyboard で指定している initImageView() } func initImageView(){ print("(in initImageView) ") // 画像データファイルの読み込み:Main.storyboard に指定したものと同一 let imageUI1:UIImage = UIImage(named:"Baby1x.jpg")! // サイズは 593x896 let imageView = UIImageView(image:imageUI1) /* // 画面の中心を求めて let screenWidth:CGFloat = view.frame.size.width let screenHeight:CGFloat = view.frame.size.height imageView.center = CGPoint(x:screenWidth/2, y:screenHeight/2) // 下の行を実行すれば Main.storyboard に指定しなくても表示される? //self.view.addSubview(imageView) */ let photowidth = imageUI1.size.width as AnyObject as! Int let photoheight = imageUI1.size.height as AnyObject as! Int let photosize = photowidth * photoheight print(photosize) print(photoheight) print(photowidth) // Image にデータを代入 let myimage = Image<RGBA<UInt8>>(uiImage: imageView.image!) var x,y:Int x = 0 y = 0 //myimage[x,y]のデータをRGBAで表示する print( myimage[x,y] ) print( myimage[250,450] ) print( myimage[592,895] ) print( myimage[592,895].gray) //print( myimage[895,592] ) // 配列からはみ出でてエラーになる var sum:Int = 0 for x in 0..<photowidth { for y in 0..<photoheight { sum = sum + (myimage[x,y].gray as AnyObject as! Int) } } var average = sum / photosize print("ave:", average) print("(end of initImageView)") }
}
補足情報(FW/ツールのバージョンなど)
EasyImageというフレームワークを使わせていただいています