裁剪图像包含在 4 边(非矩形)多边形中

Posted

技术标签:

【中文标题】裁剪图像包含在 4 边(非矩形)多边形中【英文标题】:Crop image enclosed in a 4 sided (not rectangle) polygon 【发布时间】:2016-02-24 17:24:50 【问题描述】:

如何裁剪包含在随机多边形(4 边而非矩形)内的图像部分。只是想知道要遵循哪种方法而不是代码。

【问题讨论】:

对多边形视图进行快照。 获取与该四边形等效的CGRect:“包含”多边形的最小矩形。然后裁剪。找到CGRect 的方法是您的问题吗?您还可以将多边形区域之外的图像部分设置为透明。 @Teja Nandamuri:我想裁剪多边形内的区域。多边形可以动态改变其尺寸 @Larme:通过选择最小矩形,我不会得到包含在多边形中的精确图像 之后必须敷面膜!你的多边形是如何创建的? 【参考方案1】:

您可以在 Core Graphics 中轻松做到这一点。

您只需要创建一个新的图像上下文,将路径添加到上下文,然后将上下文裁剪到路径。然后,您可以在其中绘制图像并得到裁剪的图像。

-(UIImage*) cropImage:(UIImage*)image withPath:(UIBezierPath*)path  // where the UIBezierPath is defined in the UIKit coordinate system (0,0) is top left

    CGRect r = CGPathGetBoundingBox(path.CGPath); // the rect to draw our image in (minimum rect that the path occupies).

    UIGraphicsBeginImageContextWithOptions(r.size, NO, image.scale); // begin image context, with transparency & the scale of the image.
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(ctx, -r.origin.x, -r.origin.y); // translate context so that when we add the path, it starts at (0,0).

    CGContextAddPath(ctx, path.CGPath); // add path.
    CGContextClip(ctx); // clip any future drawing to the path region.

    [image drawInRect:(CGRect)CGPointZero, image.size]; // draw image

    UIImage* i = UIGraphicsGetImageFromCurrentImageContext(); // get image from context
    UIGraphicsEndImageContext(); // clean up and finish context

    return i; // return image

例如,如果我们截取您的问题的屏幕截图(我找不到任何其他图片在说谎!)

并使用以下代码....

UIImage* i = [UIImage imageNamed:@"3.png"];

UIBezierPath* p = [UIBezierPath bezierPath];
[p moveToPoint:CGPointMake(0, 0)];
[p addLineToPoint:CGPointMake(1500, 500)];
[p addLineToPoint:CGPointMake(500, 1200)];

UIImage* i1 = [self cropImage:i withPath:p];

这将是输出...

如果您要定期裁剪图像,您甚至可以将其添加到 UIImage 类别中。

【讨论】:

我已经使用了代码,但它没有给出我用 UIBezeir 路径选择的区域,而是在裁剪后给出了一些其他区域。需要帮助 @aman 我怀疑你试图在 UIKit 坐标系中指定你的路径((0,0) 在左上角)。我的答案旨在在图像坐标系中工作((0,0) 位于左下角)。我已经修改了它以在 UIKit 坐标系中工作,所以它现在应该适合你了。 swift 版本好吗? @DeyaEldeen 您无法将哪个部分转换为 Swift?由于问题被标记为objective-c,我不想用 Swift 版本混淆我的答案 - 但转换应该相当简单。 Core Graphics 函数调用保持不变,只需将变量声明中的类型更改为let,将drawInRect: 调用替换为image.drawInRect(...),并将方法签名替换为等效的Swift (func cropImage(image:UIImage, withPath:UIBezierPath) -> UIImage ...)。跨度> @originaluser2:感谢您的所有帮助,我已经使用了您的新代码。我仍然面临一个问题。我正在使用 JBCroppableView 来选择图像的随机区域。我正在尝试使用所选区域的 UIBezeir 路径来裁剪图像(JBCroppableView 仅掩盖额外区域)。但裁剪后的图像并不完全是我选择的区域。它还裁剪了一些调整非选定区域。裁剪的区域也接近所选区域的 1/4。我已经尝试了一切,但我不知道我错过了什么。【参考方案2】:

为 Swift 3 更新。

我注意到那里的许多实现似乎都希望背景为白色或透明,而我真的只希望背景颜色为黑色。

extension UIImage 

    func crop(withPath: UIBezierPath, andColor: UIColor) -> UIImage 
        let r: CGRect = withPath.cgPath.boundingBox
        UIGraphicsBeginImageContextWithOptions(r.size, false, self.scale)
        if let context = UIGraphicsGetCurrentContext() 
            let rect = CGRect(origin: .zero, size: size)
            context.setFillColor(andColor.cgColor)
            context.fill(rect)
            context.translateBy(x: -r.origin.x, y: -r.origin.y)
            context.addPath(withPath.cgPath)
            context.clip()
        
        draw(in: CGRect(origin: .zero, size: size))
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else 
            return UIImage()
        
        UIGraphicsEndImageContext()
        return image
    


【讨论】:

以上是关于裁剪图像包含在 4 边(非矩形)多边形中的主要内容,如果未能解决你的问题,请参考以下文章

在Java中按多边形区域裁剪图像

使用 php 从图像中裁剪多边形

任意多边形中的最大内接矩形

OpenCV - 检测矩形或五边形

如何用ENVI和ARCGIS切割出图像的制定区域

计算多边形的最小面积矩形