I am doing some realtime image analysis on a live videostream. I am using vImage to calculate histograms and vDSP for some further processing. I have Objective-C code that has been working well over the years. I am now about to convert it to Swift. And while it works it is too slow. I have found that the main problem is converting the vImage histogram, which is UInt (vImagePixelCount), to Float that vDSP can handle. In Objective-C I am using vDSP to do the conversion:
err = vImageHistogramCalculation_Planar8(&vBuffY,histogramY, 0);
vDSP_vfltu32((const unsigned int*)histogramY,2,histFloatY,1,256);
However, the vImage histogram is UInt, not UInt32, so I can't use vDSP_vfltu32 in Swift. Instead I am using
let err = vImageHistogramCalculation_Planar8(&vBuffY, &histogramY, 0)
let histFloatY = histogramY.compactMap{ Float($0) }
The problem is that this code is more than 100 times slower than the objective-C version. Are there any alternatives that are faster?
vImageHistogramCalculation_Planar8()
writes the histogram into a buffer with 256 elements of typevImagePixelCount
which is a type alias forunsigned long
in C, and that is a 64-bit integer on 64-bit platforms.Your Objective-C code “cheats” by casting the unsigned long pointer to an unsigned int pointer in the call to
vDSP_vfltu32 ()
and setting the stride to2
. So what happens here is that the lower 32-bit of eachunsigned long
are converted to afloat
. That works as long as the counts do not exceed the value 232-1.You can do exactly the same in Swift, only that the type casting is here done by “rebinding” the memory: