LoginSignup
1
2

More than 1 year has passed since last update.

画像のヒストグラムを作る(1) (カラー画像編)

Last updated at Posted at 2021-05-09

画像のヒストグラムを作る

Swift5での画像のヒストグラムを作成する良いサンプルが無かったので覚書

公式サンプルに参考になるプロジェクトあり

Accelerate.vImageのvImageHistogramCalculation_ARGB8888を利用して計算するよう
https://developer.apple.com/documentation/accelerate/1545743-vimagehistogramcalculation_argb8

この方法では,カラーチャネルが1chでは計算できないが,ひとまず目的は達成したので良しとする

import Accelerate.vImage

    func histogramCalculation(imageRef: CGImage) -> (red: [UInt], green: [UInt], blue: [UInt], alpha:[UInt])
    {

        let imgProvider: CGDataProvider = imageRef.dataProvider!
        let imgBitmapData: CFData = imgProvider.data!

        var imgBuffer = vImage_Buffer(
            data: UnsafeMutableRawPointer(mutating: CFDataGetBytePtr(imgBitmapData)),
            height: vImagePixelCount(imageRef.height),
            width: vImagePixelCount(imageRef.width),
            rowBytes: imageRef.bytesPerRow)


        // bins: zero = red, green = one, blue = two, alpha = three
        var histogramBinZero = [vImagePixelCount](repeating: 0, count: 256)
        var histogramBinOne = [vImagePixelCount](repeating: 0, count: 256)
        var histogramBinTwo = [vImagePixelCount](repeating: 0, count: 256)
        var histogramBinThree = [vImagePixelCount](repeating: 0, count: 256)

        histogramBinZero.withUnsafeMutableBufferPointer { zeroPtr in
            histogramBinOne.withUnsafeMutableBufferPointer { onePtr in
                histogramBinTwo.withUnsafeMutableBufferPointer { twoPtr in
                    histogramBinThree.withUnsafeMutableBufferPointer { threePtr in

                        var histogramBins = [zeroPtr.baseAddress, onePtr.baseAddress,
                                             twoPtr.baseAddress, threePtr.baseAddress]

                        histogramBins.withUnsafeMutableBufferPointer { histogramBinsPtr in
                            let error =  vImageHistogramCalculation_ARGB8888(&imgBuffer,
                                                                            histogramBinsPtr.baseAddress!,
                                                                            vImage_Flags(kvImageNoFlags))

                            guard error == kvImageNoError else {
                                fatalError("Error calculating histogram: \(error)")
                            }
                        }
                    }
                }
            }
        }


        return (histogramBinZero, histogramBinOne, histogramBinTwo, histogramBinThree)
    }

iOSであれば,UIImageからcgImage作成は用意だが,macではNSImageなのでひと作業必要

var imageRect = NSRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
guard let cgImg1 =  img.cgImage(forProposedRect: &imageRect, context: nil, hints: nil) else {
      abort()
}

結果

スクリーンショット 2021-05-10 0.30.52.png
4000x3000の画像で試すと

 *func: load img, Time: 29.488ms
 *func: make cgImg 1, Time: 0.069ms
 *func: calc, Time: 162.501ms
 *func: make 3ch chart, Time: 0.109ms
 *func: draw, Time: 0.9739ms

十分な速度が出た
グラフはnsbezierPath curveを使うとなめらかになりそうだが
control point算出がめんどくさく,今回は直線でつないでいる

上記プロジェクトはGithubにおいておきます

ではまた

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2