You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift实现透视校正与裁剪后如何获取正确图像?

图像透视校正与裁剪的坐标/尺寸错误问题

我已实现基于可拖动覆盖层的图像透视校正与裁剪逻辑,图像会缩放至适配视图尺寸并居中显示,但correctPerspectiveAndCropImage函数根据传入的点进行透视校正和裁剪后,生成的图像始终存在坐标或尺寸错误。

图像透视校正错误示例

核心逻辑代码

private func correctPerspectiveAndCropImage(
  image: UIImage, topLeft: CGPoint, topRight: CGPoint, bottomLeft: CGPoint, bottomRight: CGPoint,
  in geometry: GeometryProxy
) -> UIImage? {
  print("Correcting perspective")
  print("TopLeft: \(topLeft), TopRight: \(topRight), BottomLeft: \(bottomLeft), BottomRight: \(bottomRight)")

  // Ensure the image can be converted to CIImage
  guard let ciImage = CIImage(image: image) else { return nil }
  let viewSize = geometry.size
  let imageSize = image.size

  // Calculate aspect ratios
  let imageAspect = imageSize.width / imageSize.height
  let viewAspect = viewSize.width / viewSize.height

  var scale: CGFloat
  var offsetX: CGFloat = 0
  var offsetY: CGFloat = 0

  if imageAspect > viewAspect {
    // Image is wider: scale based on height
    scale = viewSize.height / imageSize.height
    offsetX = (viewSize.width - imageSize.width * scale) / 2
  } else {
    // Image is taller: scale based on width
    scale = viewSize.width / imageSize.width
    offsetY = (viewSize.height - imageSize.height * scale) / 2
  }

  // Convert points from view coordinates to image coordinates
  func convertPoint(_ point: CGPoint) -> CGPoint {
    let x = (point.x - offsetX) / scale
    let y = (viewSize.height - point.y - offsetY) / scale
    return CGPoint(x: x, y: y)
  }

  // Convert points to image coordinates
  let tl = convertPoint(topLeft)
  let tr = convertPoint(topRight)
  let bl = convertPoint(bottomLeft)
  let br = convertPoint(bottomRight)

  // Create perspective correction filter
  guard let perspectiveCorrection = CIFilter(name: "CIPerspectiveCorrection") else { return nil }
  perspectiveCorrection.setValue(ciImage, forKey: kCIInputImageKey)
  perspectiveCorrection.setValue(CIVector(cgPoint: tl), forKey: "inputTopLeft")
  perspectiveCorrection.setValue(CIVector(cgPoint: tr), forKey: "inputTopRight")
  perspectiveCorrection.setValue(CIVector(cgPoint: bl), forKey: "inputBottomLeft")
  perspectiveCorrection.setValue(CIVector(cgPoint: br), forKey: "inputBottomRight")

  // Get the corrected image
  guard let correctedImage = perspectiveCorrection.outputImage else { return nil }

  // Create CGImage from corrected CIImage
  let context = CIContext(options: nil)
  guard let cgImage = context.createCGImage(correctedImage, from: correctedImage.extent) else {
    return nil
  }

  // Return the corrected UIImage with the same orientation as the original image
  return UIImage(cgImage: cgImage, scale: image.scale, orientation: image.imageOrientation)
}

已完成的排查工作:

  • 检查过视图传递的geometry参数
  • 分析过代码逻辑
  • 将所有视图移入同一结构体以避免尺寸差异

现需解决问题,获取透视校正与裁剪后的正确图像。

内容的提问来源于stack exchange,提问作者BearD01001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:47:33