簡體   English   中英

從圖像中提取選定區域

[英]Extract selected area from image

我在 UIImageView 中有圖像,用戶可以在圖像上繪制特定的選擇,我想借助在圖像上繪制的路徑從該圖像中剪切或提取特定區域。

源圖像:

頭選: 尾巴選擇:

我已遵循此圖像背景刪除,但我想對圖像進行選擇並提取選擇。

這是我的代碼:

class RemoveBackgroundViewController: UIViewController {
    
    var theDrawingView: DrawingImageView = DrawingImageView(frame: .zero)
    var imgView = UIImageView()
    var drawView = DrawView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        guard let img = UIImage(named: "IMG_4725") else {
            fatalError("Could not load image!!!")
        }
        
        view.backgroundColor = .white
        imgView.backgroundColor = .yellow
        imgView.image = img
        imgView.contentMode = .scaleAspectFit
        
        theDrawingView.contentMode = .scaleAspectFit
        theDrawingView.image = img
        
        let btn = UIButton()
        btn.setTitle("Apply Mask", for: [])
        btn.setTitleColor(.white, for: .normal)
        btn.setTitleColor(.gray, for: .highlighted)
        btn.backgroundColor = .red
        
        let btn1 = UIButton()
        btn1.setTitle("extract", for: [])
        btn1.setTitleColor(.white, for: .normal)
        btn1.setTitleColor(.gray, for: .highlighted)
        btn1.backgroundColor = .red
        
        let btn2 = UIButton()
        btn2.setTitle("cancel", for: [])
        btn2.setTitleColor(.white, for: .normal)
        btn2.setTitleColor(.gray, for: .highlighted)
        btn2.backgroundColor = .red
        
        [btn2, btn1, btn, theDrawingView, imgView, drawView].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
        }
        
        drawView.isHidden = true
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            
            // center the drawing image view, with 20-pts on each side
            //  sized proportionally to the loaded image
            //            theDrawingView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            theDrawingView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            //            theDrawingView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            theDrawingView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            theDrawingView.widthAnchor.constraint(equalToConstant: 250),
            theDrawingView.heightAnchor.constraint(equalTo: theDrawingView.widthAnchor, multiplier: 1.0),
            
            // constrain button above the image
            btn.bottomAnchor.constraint(equalTo: theDrawingView.topAnchor, constant: -8.0),
            btn.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            btn.widthAnchor.constraint(equalToConstant: 160.0),
            
            // constrain btn1 above the btn
            btn1.bottomAnchor.constraint(equalTo: btn.topAnchor, constant: -8.0),
            btn1.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            btn1.widthAnchor.constraint(equalToConstant: 160.0),
            
            // constrain btn1 above the btn
            btn2.bottomAnchor.constraint(equalTo: btn1.topAnchor, constant: -8.0),
            btn2.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            btn2.widthAnchor.constraint(equalToConstant: 160.0),
            
            imgView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0),
            imgView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8.0),
            imgView.heightAnchor.constraint(equalToConstant: 250),
            imgView.widthAnchor.constraint(equalToConstant: 250),
            
            //            drawView.leadingAnchor.constraint(equalTo: theDrawingView.leadingAnchor),
            //            drawView.topAnchor.constraint(equalTo: theDrawingView.topAnchor),
            //            drawView.trailingAnchor.constraint(equalTo: theDrawingView.trailingAnchor),
            //            drawView.bottomAnchor.constraint(equalTo: theDrawingView.bottomAnchor),
        ])
        
        btn.addTarget(self, action: #selector(self.toggleActivity(_:)), for: .touchUpInside)
        btn1.addTarget(self, action: #selector(self.cropActivity(_:)), for: .touchUpInside)
        btn2.addTarget(self, action: #selector(self.cancelActivity(_:)), for: .touchUpInside)
    }
    
    @objc func cropActivity(_ sender: Any) {
        if let imag = theDrawingView.cropImage() {
            imgView.image = imag
        } else {
            print("\n...Ooops...\n")
        }
        //        drawView.maskPreview(previewView: imgView)
    }
    
    @objc func cancelActivity(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }
    
    @objc func toggleActivity(_ sender: Any) {
        guard let btn = sender as? UIButton else { return }
        if theDrawingView.isDrawing {
            theDrawingView.applyMask() //sPath: drawView.bezierPath)
            btn.setTitle("Draw More", for: [])
        } else {
            theDrawingView.drawMore()
            btn.setTitle("Apply Mask", for: [])
        }
    }
}

class DrawingImageView: UIImageView {
    var path = UIBezierPath()
    var previousTouchPoint = CGPoint.zero
    var shapeLayer = CAShapeLayer()
    
    var isDrawing: Bool = true
    
    var isClear: Bool = false {
        didSet {
            updateView()
        }
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        setupView()
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    func updateView() {
        self.shapeLayer.shadowOffset = .init(width: 1, height: 1)
        self.shapeLayer.shadowColor = UIColor.black.cgColor
        self.shapeLayer.shadowOpacity = 1
        
        self.shapeLayer.lineWidth = 20
        self.shapeLayer.lineCap = .round
        self.shapeLayer.strokeColor = isClear ? UIColor.clear.cgColor : UIColor.blue.cgColor
        self.shapeLayer.opacity = 0.3
        self.isUserInteractionEnabled = true
    }
    
    func setupView() {
        self.layer.addSublayer(shapeLayer)
        updateView()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        
        if !isDrawing { return }
        if let location = touches.first?.location(in: self){
            previousTouchPoint = location
        }
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        
        if !isDrawing { return }
        if let location = touches.first?.location(in: self) {
            path.move(to: location)
            path.addLine(to: previousTouchPoint)
            previousTouchPoint = location
            shapeLayer.path = path.cgPath
        }
    }
    
    func applyMask(sPath: UIBezierPath? = nil) -> Void {
        shapeLayer.opacity = 1.0
        // use it as a mask
        layer.mask = shapeLayer
        isDrawing = false
    }
    
    func drawMore() -> Void {
        // remove the mask
        layer.mask = nil
        // set opacity back to 0.3
        shapeLayer.opacity = 0.3
        // add shapeLayer back as sublayer
        self.layer.addSublayer(shapeLayer)
        isDrawing = true
    }
    
    func cropImage() -> UIImage? {
        shapeLayer.fillColor = UIColor.black.cgColor
        layer.mask = shapeLayer
        layer.masksToBounds = true
        
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 1)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return newImage
    }
    
    var bezierPath = UIBezierPath()
    
    override func setNeedsLayout() {
        bezierPath.reversing()
        let shapeLayer = CAShapeLayer()
        shapeLayer.frame = self.bounds
        shapeLayer.path = bezierPath.cgPath
        self.layer.mask = shapeLayer
        self.layer.masksToBounds = true
    }
}

輸入: 輸出:

let vc = RemoveBackgroundViewController()
vc .modalPresentationStyle = .overFullScreen
self.present(vc, animated: true, completion: nil)

最后,我找到了一個庫ZImageCropper ,它有助於選擇具有隨機形狀或圖像選擇的圖像的所需部分。

謝謝

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM