HomeiOS Developmentios - Swift: Algorithm for drawing define of picture form in BezierPath...

ios – Swift: Algorithm for drawing define of picture form in BezierPath (Canny edge detector)


I am making an attempt to attract the define of a picture utilizing BezierPath based mostly on the transparency of every pixel.

Nevertheless, I am having a problem with the logic; my logic additionally attracts the inner outlines.

I solely need to draw the exterior define with BezierPath.
What’s I get (the primary form it is the unique picture, the second is the bezierPath):

enter image description here

My code:

func processImage(_ picture: UIImage) -> UIBezierPath? {
        guard let cgImage = picture.cgImage else {
               print("Error: Could not get CGImage from UIImage")
               return nil
           }

           let width = cgImage.width
           let top = cgImage.top

           // Create a context to carry out picture processing
           let colorSpace = CGColorSpaceCreateDeviceGray()
           let context = CGContext(information: nil, width: width, top: top, bitsPerComponent: 8, bytesPerRow: width, area: colorSpace, bitmapInfo: CGImageAlphaInfo.none.rawValue)

           guard let context = context else {
               print("Error: Could not create CGContext")
               return nil
           }

           // Draw the picture into the context
           context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, top: top))

           // Carry out Canny edge detection
           guard let edgeImage = context.makeImage() else {
               print("Error: Could not create edge picture")
               return nil
           }

           // Create a bezier path for the define of the form
           let bezierPath = UIBezierPath()
           
           // Iterate over the picture pixels to seek out the perimeters
           for y in 0..<top {
               for x in 0..<width {
                   let pixel = edgeImage.pixel(x: x, y: y)
                   
                   if pixel > 0 {
                       let leftPixel = (x > 0) ? edgeImage.pixel(x: x - 1, y: y) : 0
                       let rightPixel = (x < width - 1) ? edgeImage.pixel(x: x + 1, y: y) : 0
                       let abovePixel = (y > 0) ? edgeImage.pixel(x: x, y: y - 1) : 0
                       let belowPixel = (y < top - 1) ? edgeImage.pixel(x: x, y: y + 1) : 0
                       
                       if leftPixel == 0 || rightPixel == 0 || abovePixel == 0 || belowPixel == 0 {
                           bezierPath.transfer(to: CGPoint(x: CGFloat(x), y: CGFloat(y)))
                           bezierPath.addLine(to: CGPoint(x: CGFloat(x) + 1.0, y: CGFloat(y) + 1.0))
                       }
                   }
               }
           }

           return bezierPath
    }

extension CGImage {
    func pixel(x: Int, y: Int) -> UInt8 {
        let information = self.dataProvider!.information
        let pointer = CFDataGetBytePtr(information)
        let bytesPerRow = self.bytesPerRow
        
        let pixelInfo = (bytesPerRow * y) + x
        return pointer![pixelInfo]
    }
    
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments