从 CIRectangleFeature 坐标转换为视图坐标
Convert from CIRectangleFeature coordinates to view coordinates
我正在使用 IOS 中的 CIDetector class 在我的 UIImage 中查找 CIRectangleFeatures。之后,我的目标是显示绘制到图层中的角点,然后依次将其添加到我的 UIImageView 中。不幸的是,CIRectangleFeature 给出的坐标在图像 space 中。而且,即使我尝试使用 CGContextConvertToUserSpace 函数转换它们,绘制的矩形与图像中的实际矩形完全不同。
这是我的代码,当拍摄图像时,将调用 workWithTheImage:
func analyzeImage(image: UIImage) -> [RectanglePoint]
{
guard let ciImage = CIImage(image: image)
else { return [] }
let context = CIContext(options: nil)
let detector = CIDetector(ofType: CIDetectorTypeRectangle, context: context, options: nil)
let features = detector.featuresInImage(ciImage)
UIGraphicsBeginImageContext(ciImage.extent.size)
let currentContext = UIGraphicsGetCurrentContext()
var points: [RectanglePoint] = []
for feature in features as! [CIRectangleFeature]
{
let topLeft = CGContextConvertPointToUserSpace(currentContext, feature.topLeft)
let topRight = CGContextConvertPointToUserSpace(currentContext, feature.topRight)
let bottomRight = CGContextConvertPointToUserSpace(currentContext, feature.bottomRight)
let bottomLeft = CGContextConvertPointToUserSpace(currentContext, feature.bottomLeft)
let point = RectanglePoint(bottomLeft: bottomLeft, topLeft: topLeft, bottomRight: bottomRight, topRight: topRight)
points.append(point)
}
UIGraphicsEndImageContext()
return points
}
func workWithImage(image: UIImage)
{
let imageView = UIImageView(frame: view.frame)
imageView.image = image
let path = UIBezierPath()
let shapeLayer = CAShapeLayer()
shapeLayer.frame = imageView.bounds
for i in analyzeImage(image)
{
path.moveToPoint(i.topLeft)
path.addLineToPoint(i.topRight)
path.addLineToPoint(i.bottomRight)
path.addLineToPoint(i.bottomLeft)
path.addLineToPoint(i.topLeft)
}
shapeLayer.path = path.CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = UIColor.redColor().CGColor
imageView.layer.addSublayer(shapeLayer)
}
如果您的路径仅在 Y 维度偏离:
我认为他们还没有将 CIDetector 完全移植到 UIKit。地物的坐标在Cocoa坐标系中。只需执行 container.height - point.y
即可将其转换。
我还为您的结构指定了正确的名称。剩下的东西在那里,我曾经弄清楚发生了什么。可能对你有用。
代码:
func analyzeImage(image: UIImage) -> [Quadrilateral]
{
guard let ciImage = CIImage(image: image)
else { return [] }
let flip = true // set to false to prevent flipping the coordinates
let context = CIContext(options: nil)
let detector = CIDetector(ofType: CIDetectorTypeRectangle, context: context, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
let features = detector.featuresInImage(ciImage)
UIGraphicsBeginImageContext(ciImage.extent.size)
let currentContext = UIGraphicsGetCurrentContext()
var frames: [Quadrilateral] = []
for feature in features as! [CIRectangleFeature]
{
var topLeft = CGContextConvertPointToUserSpace(currentContext, feature.topLeft)
var topRight = CGContextConvertPointToUserSpace(currentContext, feature.topRight)
var bottomRight = CGContextConvertPointToUserSpace(currentContext, feature.bottomRight)
var bottomLeft = CGContextConvertPointToUserSpace(currentContext, feature.bottomLeft)
if flip {
topLeft = CGPoint(x: topLeft.x, y: image.size.height - topLeft.y)
topRight = CGPoint(x: topRight.x, y: image.size.height - topRight.y)
bottomLeft = CGPoint(x: bottomLeft.x, y: image.size.height - bottomLeft.y)
bottomRight = CGPoint(x: bottomRight.x, y: image.size.height - bottomRight.y)
}
let frame = Quadrilateral(topLeft: topLeft, topRight: topRight, bottomLeft: bottomLeft, bottomRight: bottomRight)
frames.append(frame)
}
UIGraphicsEndImageContext()
return frames
}
四边形结构:
struct Quadrilateral {
var topLeft : CGPoint = CGPointZero
var topRight : CGPoint = CGPointZero
var bottomLeft : CGPoint = CGPointZero
var bottomRight : CGPoint = CGPointZero
var path : UIBezierPath {
get {
let tempPath = UIBezierPath()
tempPath.moveToPoint(topLeft)
tempPath.addLineToPoint(topRight)
tempPath.addLineToPoint(bottomRight)
tempPath.addLineToPoint(bottomLeft)
tempPath.addLineToPoint(topLeft)
return tempPath
}
}
init(topLeft topLeft_I: CGPoint, topRight topRight_I: CGPoint, bottomLeft bottomLeft_I: CGPoint, bottomRight bottomRight_I: CGPoint) {
topLeft = topLeft_I
topRight = topRight_I
bottomLeft = bottomLeft_I
bottomRight = bottomRight_I
}
var frame : CGRect {
get {
let highestPoint = max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y)
let lowestPoint = min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y)
let farthestPoint = max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x)
let closestPoint = min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x)
// you might want to set origin to (0,0)
let origin = CGPoint(x: closestPoint, y: lowestPoint)
let size = CGSize(width: farthestPoint, height: highestPoint)
return CGRect(origin: origin, size: size)
}
}
var size : CGSize {
get {
return frame.size
}
}
var origin : CGPoint {
get {
return frame.origin
}
}
}
我正在使用 IOS 中的 CIDetector class 在我的 UIImage 中查找 CIRectangleFeatures。之后,我的目标是显示绘制到图层中的角点,然后依次将其添加到我的 UIImageView 中。不幸的是,CIRectangleFeature 给出的坐标在图像 space 中。而且,即使我尝试使用 CGContextConvertToUserSpace 函数转换它们,绘制的矩形与图像中的实际矩形完全不同。
这是我的代码,当拍摄图像时,将调用 workWithTheImage:
func analyzeImage(image: UIImage) -> [RectanglePoint]
{
guard let ciImage = CIImage(image: image)
else { return [] }
let context = CIContext(options: nil)
let detector = CIDetector(ofType: CIDetectorTypeRectangle, context: context, options: nil)
let features = detector.featuresInImage(ciImage)
UIGraphicsBeginImageContext(ciImage.extent.size)
let currentContext = UIGraphicsGetCurrentContext()
var points: [RectanglePoint] = []
for feature in features as! [CIRectangleFeature]
{
let topLeft = CGContextConvertPointToUserSpace(currentContext, feature.topLeft)
let topRight = CGContextConvertPointToUserSpace(currentContext, feature.topRight)
let bottomRight = CGContextConvertPointToUserSpace(currentContext, feature.bottomRight)
let bottomLeft = CGContextConvertPointToUserSpace(currentContext, feature.bottomLeft)
let point = RectanglePoint(bottomLeft: bottomLeft, topLeft: topLeft, bottomRight: bottomRight, topRight: topRight)
points.append(point)
}
UIGraphicsEndImageContext()
return points
}
func workWithImage(image: UIImage)
{
let imageView = UIImageView(frame: view.frame)
imageView.image = image
let path = UIBezierPath()
let shapeLayer = CAShapeLayer()
shapeLayer.frame = imageView.bounds
for i in analyzeImage(image)
{
path.moveToPoint(i.topLeft)
path.addLineToPoint(i.topRight)
path.addLineToPoint(i.bottomRight)
path.addLineToPoint(i.bottomLeft)
path.addLineToPoint(i.topLeft)
}
shapeLayer.path = path.CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = UIColor.redColor().CGColor
imageView.layer.addSublayer(shapeLayer)
}
如果您的路径仅在 Y 维度偏离:
我认为他们还没有将 CIDetector 完全移植到 UIKit。地物的坐标在Cocoa坐标系中。只需执行 container.height - point.y
即可将其转换。
我还为您的结构指定了正确的名称。剩下的东西在那里,我曾经弄清楚发生了什么。可能对你有用。
代码:
func analyzeImage(image: UIImage) -> [Quadrilateral]
{
guard let ciImage = CIImage(image: image)
else { return [] }
let flip = true // set to false to prevent flipping the coordinates
let context = CIContext(options: nil)
let detector = CIDetector(ofType: CIDetectorTypeRectangle, context: context, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])
let features = detector.featuresInImage(ciImage)
UIGraphicsBeginImageContext(ciImage.extent.size)
let currentContext = UIGraphicsGetCurrentContext()
var frames: [Quadrilateral] = []
for feature in features as! [CIRectangleFeature]
{
var topLeft = CGContextConvertPointToUserSpace(currentContext, feature.topLeft)
var topRight = CGContextConvertPointToUserSpace(currentContext, feature.topRight)
var bottomRight = CGContextConvertPointToUserSpace(currentContext, feature.bottomRight)
var bottomLeft = CGContextConvertPointToUserSpace(currentContext, feature.bottomLeft)
if flip {
topLeft = CGPoint(x: topLeft.x, y: image.size.height - topLeft.y)
topRight = CGPoint(x: topRight.x, y: image.size.height - topRight.y)
bottomLeft = CGPoint(x: bottomLeft.x, y: image.size.height - bottomLeft.y)
bottomRight = CGPoint(x: bottomRight.x, y: image.size.height - bottomRight.y)
}
let frame = Quadrilateral(topLeft: topLeft, topRight: topRight, bottomLeft: bottomLeft, bottomRight: bottomRight)
frames.append(frame)
}
UIGraphicsEndImageContext()
return frames
}
四边形结构:
struct Quadrilateral {
var topLeft : CGPoint = CGPointZero
var topRight : CGPoint = CGPointZero
var bottomLeft : CGPoint = CGPointZero
var bottomRight : CGPoint = CGPointZero
var path : UIBezierPath {
get {
let tempPath = UIBezierPath()
tempPath.moveToPoint(topLeft)
tempPath.addLineToPoint(topRight)
tempPath.addLineToPoint(bottomRight)
tempPath.addLineToPoint(bottomLeft)
tempPath.addLineToPoint(topLeft)
return tempPath
}
}
init(topLeft topLeft_I: CGPoint, topRight topRight_I: CGPoint, bottomLeft bottomLeft_I: CGPoint, bottomRight bottomRight_I: CGPoint) {
topLeft = topLeft_I
topRight = topRight_I
bottomLeft = bottomLeft_I
bottomRight = bottomRight_I
}
var frame : CGRect {
get {
let highestPoint = max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y)
let lowestPoint = min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y)
let farthestPoint = max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x)
let closestPoint = min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x)
// you might want to set origin to (0,0)
let origin = CGPoint(x: closestPoint, y: lowestPoint)
let size = CGSize(width: farthestPoint, height: highestPoint)
return CGRect(origin: origin, size: size)
}
}
var size : CGSize {
get {
return frame.size
}
}
var origin : CGPoint {
get {
return frame.origin
}
}
}