The document discusses hacking images for faster OpenCV processing in an iOS application. Specifically, it explores sharing memory between OpenCV's Mat class and Core Graphics contexts and images to avoid unnecessary copying. It shows how to expose the Mat data as a Swift-compatible type and create a CGContext and CGImage directly from the Mat's memory pointer. This allows operating directly on the image data without copying, simplifying operations and improving performance. In testing, a performance gain was not achieved likely due to other processing needs, but the simpler data flow was beneficial.
7. ● Estimate segmentation from input marker
● OpenCV has the implementation, so it’s
easy to integrate!
Grabcut
8. ● Estimate segmentation from input seed
● OpenCV has the implementation, so it’s
easy to integrate!
Grabcut
9. Convenience
● We’re using application instead of WEB for “convenience”
● Performance is essential
C++
● We cannot catch errors (crashes immediately)
● We cannot share types (Only Obj-C can bridge)
Difficulties
12. Grabcut flow
Mask Image
Original Image Input Image
Input Mask
Grabcut
Initial Path
Marker
We have to copy every
time we add markers
convert
convert
19. CGContext(
data: image.data,
width: image.cols(),
height: image.rows(),
bitsPerComponent: image.elemSize1() * 8,
bytesPerRow: image.step[0],
space: CGColorSpaceCreateDeviceGray(),
bitmapInfo: CGImageAlphaInfo.none.rawValue
)
※depends on color mode, this is case for Mask
Create CGContext
20. let bufferSize = context.bytesPerRow * context.height
let dataProvider = CGDataProvider(data: Data(bytesNoCopy: data, count: bufferSize, deallocator: .none) as
CFData)!
let maskImage = CGImage(maskWidth: context.width,
height: context.height,
bitsPerComponent: context.bitsPerComponent,
bitsPerPixel: context.bitsPerPixel,
bytesPerRow: context.bytesPerRow,
provider: dataProvider,
decode: nil,
shouldInterpolate: false)!
※depends on color mode, this is case for Mask
Read from CGContext as CGImage
21. We can share memory between
cv::Mat,
CGContext,
CGImage
Conclusion
22. ● We can clone CGImage using
`pointer.copyMemory(from:byteCount:)`
● We can reset mask using `assign(repeating:count:)`
Easy undo/redo/initialize
Simpler image operations
23. ● Performance was not so improved…
● We had to build masks to show
● We had to copy to push undo stack
● Simple & Clear data-flow made us happy!
Result