グレースケール変換

はじめに

前回のチェンネル入れ替えに続き、画像処理100本ノックの2問目グレースケール化をSwiftで実装してみました。

前回の記事でSwiftでのピクセルの操作を行う為のクラスを作成したため今回はサクッと実装することができました。

問題文

問題文は以下のような文章でした。

画像をグレースケールにせよ。
グレースケールとは、画像の輝度表現方法の一種であり下式で計算される。

Y = 0.2126 R + 0.7152 G + 0.0722 B

https://github.com/yoyoyo-yo/Gasyori100knock/tree/master/Question_01_10

0.2126 R + 0.7152 G + 0.0722 B この数値はなんなんだろうと調べてみたところHDTVという企画だということがわかりました。

どうやら日本のテレビのデジタル放送に使われているものらしいです。

Swiftでの回答

グレイスケールにするということはBT.709の式に乗っ取って計算した値をRGBそれぞれに入れてあげれば良いわけです。

UIImageのextensionにcreateGrayImageというメソッドを作成し、グレースケールに変換してみました。

extension UIImage {
    func createGrayImage(r:[CGFloat], g: [CGFloat], b:[CGFloat], a:[CGFloat]) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        let wid:Int = Int(size.width)
        let hei:Int = Int(size.height)
        
        for w in 0..<wid {
            for h in 0..<hei {
                let index = (w * wid) + h
                let color = 0.2126 * r[index] + 0.7152 * g[index] + 0.0722 * b[index]
                UIColor(red: color, green: color, blue: color, alpha: a[index]).setFill()
                let drawRect = CGRect(x: w, y: h, width: 1, height: 1)
                UIRectFill(drawRect)
                draw(in: drawRect, blendMode: .destinationIn, alpha: 1)
            }
        }
        let grayImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return grayImage
    }
}

呼び出し元と、PixelBufferクラスについては前回の記事とほとんどおなじでcreateImageメソッドを呼んでいたところをcreateGrayImageメソッドに帰るだけなので省略しちゃいます。

入力画像

出力画像

参考文献

グレースケール画像のうんちく