Skip to content

Instantly share code, notes, and snippets.

@btomtom5
Last active December 6, 2018 03:03
Show Gist options
  • Select an option

  • Save btomtom5/bf9609d2cac176dca5e9074af5f2fdae to your computer and use it in GitHub Desktop.

Select an option

Save btomtom5/bf9609d2cac176dca5e9074af5f2fdae to your computer and use it in GitHub Desktop.
PixelBuffer Operations
func drawSolidCircle(imageBuffer: CVPixelBuffer, pnt: (Int, Int), radius: Int) {
/*
Marks CVPixelBuffer with a solid green circle of radius r
imageBuffer: CVPixelBuffer needs to be already locked and available for write access.
*/
CVPixelBufferLockBaseAddress(imageBuffer, .init(rawValue: 0))
let width: Int = CVPixelBufferGetWidth(imageBuffer)
let height: Int = CVPixelBufferGetHeight(imageBuffer)
var positionsEarmarked: [Int] = []
for i in -radius...radius {
for j in -radius...radius {
let x = pnt.0 + i
let y = pnt.1 + j
if (x >= 0 && x < width) && (y >= 0 && y < height) {
positionsEarmarked.append(x + y * width)
}
}
}
let baseAddress: UnsafeMutablePointer<UInt8> = CVPixelBufferGetBaseAddress(imageBuffer)!.assumingMemoryBound(to: UInt8.self)
for position in positionsEarmarked {
let offset = position * 4
baseAddress[offset] = 0
baseAddress[offset + 1] = 255
baseAddress[offset + 2] = 0
// Alpha channel [offset + 3] is left unmodified
}
CVPixelBufferUnlockBaseAddress(imageBuffer, .init(rawValue: 0))
}
func drawBoundingBox(imageBuffer: CVPixelBuffer, boundingBox: CGRect) {
for xCoord in 0..<Int(boundingBox.width) {
drawSolidCircle(imageBuffer: imageBuffer, pnt: (Int(boundingBox.minX) + xCoord, Int(boundingBox.minY)), radius: 1)
drawSolidCircle(imageBuffer: imageBuffer, pnt: (Int(boundingBox.minX) + xCoord, Int(boundingBox.maxY)), radius: 1)
}
for yCoord in 0..<Int(boundingBox.height) {
drawSolidCircle(imageBuffer: imageBuffer, pnt: (Int(boundingBox.minX), Int(boundingBox.minY) + yCoord), radius: 1)
drawSolidCircle(imageBuffer: imageBuffer, pnt: (Int(boundingBox.maxX), Int(boundingBox.minY) + yCoord), radius: 1)
}
}
func buffer(from image: UIImage) -> CVPixelBuffer? {
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
var pixelBuffer : CVPixelBuffer?
let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(image.size.width), Int(image.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
guard (status == kCVReturnSuccess) else {
return nil
}
CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let context = CGContext(data: pixelData, width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue)
context?.translateBy(x: 0, y: image.size.height)
context?.scaleBy(x: 1.0, y: -1.0)
UIGraphicsPushContext(context!)
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
UIGraphicsPopContext()
CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
return pixelBuffer
}
func fillPixelBuffer(imageBuffer: CVPixelBuffer, newValue: UInt8) -> Void{
CVPixelBufferLockBaseAddress(imageBuffer, [])
let width: Int = CVPixelBufferGetWidth(imageBuffer)
let height: Int = CVPixelBufferGetHeight(imageBuffer)
let baseAddress: UnsafeMutablePointer<UInt8> = CVPixelBufferGetBaseAddress(imageBuffer)!.assumingMemoryBound(to: UInt8.self)
for rowIndex in 0..<width {
for colIndex in 0..<height{
let offset = rowIndex * width * 4 + colIndex * 4
baseAddress[offset] = newValue
baseAddress[offset + 1] = newValue
baseAddress[offset + 2] = newValue
// Alpha channel [offset + 3] is left unmodified
}
}
CVPixelBufferUnlockBaseAddress(imageBuffer, [])
}
func drawFacialLandmarks(imageBuffer: CVPixelBuffer, facialLandmarksX: [Double], facialLandmarksY: [Double]) -> Void{
guard facialLandmarksX.count == facialLandmarksY.count && facialLandmarksY.count == 68 else {
fatalError("improper shape for facialLandmarks. landmarksX:\(facialLandmarksX.count) | landmarksY:\(facialLandmarksY.count)")
}
CVPixelBufferLockBaseAddress(imageBuffer, [])
for index in 0..<facialLandmarksX.count {
let newPoint = (Int(facialLandmarksX[index]), Int(facialLandmarksY[index]))
drawSolidCircle(imageBuffer: imageBuffer, pnt: newPoint, radius: 2)
}
CVPixelBufferUnlockBaseAddress(imageBuffer, [])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment