- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
目前我正在使用 CIDetector 来检测我的 UIImage 中的矩形。我正在按照建议的方式将坐标传递到过滤器中,以取回 CIImage 以覆盖获取的 UIImage。它看起来像这样:
func performRectangleDetection(image: UIKit.CIImage) -> UIKit.CIImage? {
var resultImage: UIKit.CIImage?
let detector:CIDetector = CIDetector(ofType: CIDetectorTypeRectangle, context: nil, options: [CIDetectorAccuracy : CIDetectorAccuracyHigh])
// Get the detections
let features = detector.featuresInImage(image)
for feature in features as! [CIRectangleFeature] {
resultImage = self.drawHighlightOverlayForPoints(image, topLeft: feature.topLeft, topRight: feature.topRight,
bottomLeft: feature.bottomLeft, bottomRight: feature.bottomRight)
}
return resultImage
}
func drawHighlightOverlayForPoints(image: UIKit.CIImage, topLeft: CGPoint, topRight: CGPoint,
bottomLeft: CGPoint, bottomRight: CGPoint) -> UIKit.CIImage {
var overlay = UIKit.CIImage(color: CIColor(red: 1.0, green: 0.55, blue: 0.0, alpha: 0.45))
overlay = overlay.imageByCroppingToRect(image.extent)
overlay = overlay.imageByApplyingFilter("CIPerspectiveTransformWithExtent",
withInputParameters: [
"inputExtent": CIVector(CGRect: image.extent),
"inputTopLeft": CIVector(CGPoint: topLeft),
"inputTopRight": CIVector(CGPoint: topRight),
"inputBottomLeft": CIVector(CGPoint: bottomLeft),
"inputBottomRight": CIVector(CGPoint: bottomRight)
])
return overlay.imageByCompositingOverImage(image)
}
调用 performRectangleDetection 通过 CIImage 显示检测到的矩形。
它看起来像上面的图片。我需要使用设置为描边的 UIBezierPath 来显示相同的红色矩形。我需要这个,以便用户可以调整检测,以防它不是 100% 准确。我试图画出一条路径,但没有成功。这是我绘制路径的方式。我使用一个名为 rect 的自定义类来保存 4 个点。这是检测:
func detectRect() -> Rect{
var rect:Rect?
let detector:CIDetector = CIDetector(ofType: CIDetectorTypeRectangle, context: nil, options: [CIDetectorAccuracy : CIDetectorAccuracyHigh])
// Get the detections
let features = detector.featuresInImage(UIKit.CIImage(image: self)!)
for feature in features as! [CIRectangleFeature] {
rect = Rect(tL: feature.topLeft, tR: feature.topRight, bR: feature.bottomRight, bL: feature.bottomLeft)
}
return rect!
}
接下来,我必须缩放坐标。这是 Rect 类中的函数:
func scaleRect(image:UIImage, imageView:UIImageView) ->Rect{
let scaleX = imageView.bounds.width/image.size.width
var tlx = topLeft.x * scaleX
var tly = topLeft.y * scaleX
tlx += (imageView.bounds.width - image.size.width * scaleX) / 2.0
tly += (imageView.bounds.height - image.size.height * scaleX) / 2.0
let tl = CGPointMake(tlx, tly)
var trx = topRight.x * scaleX
var trY = topRight.y * scaleX
trx += (imageView.bounds.width - image.size.width * scaleX) / 2.0
trY += (imageView.bounds.height - image.size.height * scaleX) / 2.0
let tr = CGPointMake(trx, trY)
var brx = bottomRight.x * scaleX
var bry = bottomRight.y * scaleX
brx += (imageView.bounds.width - image.size.width * scaleX) / 2.0
bry += (imageView.bounds.height - image.size.height * scaleX) / 2.0
let br = CGPointMake(brx, bry)
var blx = bottomLeft.x * scaleX
var bly = bottomLeft.y * scaleX
blx += (imageView.bounds.width - image.size.width * scaleX) / 2.0
bly += (imageView.bounds.height - image.size.height * scaleX) / 2.0
let bl = CGPointMake(blx, bly)
let rect = Rect(tL: tl, tR: tr, bR: br, bL: bl)
return rect
}
最后画出路径:
var tet = image.detectRect()
tet = tet.scaleRect(image, imageView: imageView)
let shapeLayer = CAShapeLayer()
let path = ViewController.drawPath(tet.topLeft, p2: tet.topRight, p3: tet.bottomRight, p4: tet.bottomLeft)
shapeLayer.path = path.CGPath
shapeLayer.lineWidth = 5
shapeLayer.fillColor = nil
shapeLayer.strokeColor = UIColor.orangeColor().CGColor
imageView.layer.addSublayer(shapeLayer)
该路径已超出屏幕且不准确。我知道我必须将坐标从 CoreImage 坐标调整到 UIKit 坐标,然后为 UIImageView 缩放它们。不幸的是,我不知道如何正确地做到这一点。我知道我可以重复使用我的一些检测代码来完成此操作,但我不知道要采取的正确步骤。任何帮助,将不胜感激!谢谢。这是正在发生的事情的示例:
更新
为了测试我在 scaleRect() 中执行的缩放,我决定使我的 ImageView 大小与我的图像大小相同。然后我打印了缩放前后的坐标。我认为因为它们是相同的,所以我的缩放比例是正确的。这是代码:
var tet = image.detectRect()
//Before scaling
print(tet.topLeft)
print(tet.topRight)
print(tet.bottomRight)
print(tet.bottomLeft)
print("**************************************************")
//After scaling
tet = tet.scaleRect(image, imageView: imageView)
print(tet.topLeft)
print(tet.topRight)
print(tet.bottomRight)
print(tet.bottomLeft)
这是输出:
(742.386596679688, 927.240844726562)
(1514.93835449219, 994.811096191406)
(1514.29675292969, 155.2802734375)
(741.837524414062, 208.55403137207)
(742.386596679688, 927.240844726562)
(1514.93835449219, 994.811096191406)
(1514.29675292969, 155.2802734375)
(741.837524414062, 208.55403137207)
更新
为了尝试和缩放我的坐标,我又尝试了两件事。
1 号:我尝试使用 UIView convertPoint 函数将点从图像转换为 UIImageView。这是我的编码方式:我用
替换了 scaleRect() 函数let view_image = UIView(frame: CGRectMake(0, 0, image.size.width, image.size.height))
let tL = view_image.convertPoint(self.topLeft, toView: imageView)
let tR = view_image.convertPoint(self.topRight, toView: imageView)
let bR = view_image.convertPoint(self.bottomRight, toView: imageView)
let bL = view_image.convertPoint(self.bottomLeft, toView: imageView)
然后我用这些点返回了一个新的矩形。
2 号:我尝试根据图像和imageView的宽度和高度的差异对坐标进行简单的翻译。继承人的代码:
let widthDiff = (image.size.width - imageView.frame.size.width)
let highDiff = (image.size.height - imageView.frame.size.height)
let tL = CGPointMake(self.topLeft.x-widthDiff, self.topLeft.y-highDiff)
let tR = CGPointMake(self.topRight.x-widthDiff, self.topRight.y-highDiff)
let bR = CGPointMake(self.bottomRight.x-widthDiff, self.bottomRight.y-highDiff)
let bL = CGPointMake(self.bottomLeft.x-widthDiff, self.bottomLeft.y-highDiff)
更新我也尝试过使用 CGAffineTransform。代码:
var transform = CGAffineTransformMakeScale(1, -1)
transform = CGAffineTransformTranslate(transform, 0, -imageView.bounds.size.height)
let tL = CGPointApplyAffineTransform(self.topLeft, transform)
let tR = CGPointApplyAffineTransform(self.topRight, transform)
let bR = CGPointApplyAffineTransform(self.bottomRight, transform)
let bL = CGPointApplyAffineTransform(self.bottomLeft, transform)
没有一个有效。我不知道我还能尝试什么。请帮忙。这将不胜感激。谢谢!
最佳答案
如果您只需要显示路径,那么在 CAShapeLayer 中绘制路径会更容易一些。
如果您需要支持缩放图像或具有方向的图像(即来自用户相机的任何图像),则在第 4 步中会出现一些复杂情况。
下面是一个例子。这支持此代码假定图像显示在 contentMode 为 AspectFit、AspectFill、ScaleToFill 或 Centre 的 UIImageView 中。它还支持方向为上、下、右和左的图像。
// Extension for calculating the image scale in an image view.
// See: http://stackoverflow.com/questions/6856879/iphone-getting-the-size-of-an-image-after-aspectft
extension UIImageView {
var imageScale: CGSize? {
guard let image = image else {
return nil
}
let sx = Double(self.frame.size.width / image.size.width)
let sy = Double(self.frame.size.height / image.size.height)
var s = 1.0
switch (self.contentMode) {
case .ScaleAspectFit:
s = fmin(sx, sy)
return CGSize (width: s, height: s)
case .ScaleAspectFill:
s = fmax(sx, sy)
return CGSize(width:s, height:s)
case .ScaleToFill:
return CGSize(width:sx, height:sy)
default:
return CGSize(width:s, height:s)
}
}
}
// Extension which provides a transform to rotate the image based on it's orientation metadata.
extension UIImageView {
var normalizedTransformForOrientation: CGAffineTransform? {
guard let image = image else {
return nil
}
let r: CGFloat
switch image.imageOrientation {
case .Up:
r = 0
case .Down:
r = +1.0
case .Left:
r = -0.5
case .Right:
r = +0.5
default:
fatalError()
}
let cx = CGRectGetMidX(bounds)
let cy = CGRectGetMidY(bounds)
var transform = CGAffineTransformIdentity
transform = CGAffineTransformTranslate(transform, cx, cy)
transform = CGAffineTransformRotate(transform, CGFloat(M_PI) * r)
transform = CGAffineTransformTranslate(transform, -cx, -cy)
return transform
}
}
class ViewController: UIViewController {
// Shape layer for displaying the path.
let pathLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.fillColor = UIColor.greenColor().colorWithAlphaComponent(0.3).CGColor
layer.strokeColor = UIColor.greenColor().colorWithAlphaComponent(0.9).CGColor
layer.lineWidth = 2.0
return layer
}()
// Image view where the preview and path overlay will be displayed.
@IBOutlet var imageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
// Add the path overlay to the image view.
imageView?.layer.addSublayer(pathLayer)
// Load a sample image from the assets.
selectImage(UIImage(named: "sample"))
}
func selectImage(image: UIImage?) {
imageView?.image = image
if let image = image {
processImage(image)
}
}
// Detect rectangles in image, and draw the path on the screen.
func processImage(input: UIImage) {
let path = pathsForRectanglesInImage(input)
let transform = pathTransformForImageView(imageView!)
path?.applyTransform(transform)
pathLayer.path = path?.CGPath
}
// Detect rectangles in an image and return a UIBezierPath.
func pathsForRectanglesInImage(input: UIImage) -> UIBezierPath? {
guard let sourceImage = CIImage(image: input) else {
return nil
}
let features = performRectangleDetection(sourceImage)
return pathForFeatures(features)
}
// Detect rectangles in image.
func performRectangleDetection(image: CIImage) -> [CIFeature] {
let detector:CIDetector = CIDetector(
ofType: CIDetectorTypeRectangle,
context: nil,
options: [CIDetectorAccuracy : CIDetectorAccuracyHigh]
)
let features = detector.featuresInImage(image)
return features
}
// Compose a UIBezierPath from CIRectangleFeatures.
func pathForFeatures(features: [CIFeature]) -> UIBezierPath {
let path = UIBezierPath()
for feature in features {
guard let rect = feature as? CIRectangleFeature else {
continue
}
path.moveToPoint(rect.topLeft)
path.addLineToPoint(rect.topRight)
path.addLineToPoint(rect.bottomRight)
path.addLineToPoint(rect.bottomLeft)
path.closePath()
}
return path
}
// Calculate the transform to orient the preview path to the image shown inside the image view.
func pathTransformForImageView(imageView: UIImageView) -> CGAffineTransform {
guard let image = imageView.image else {
return CGAffineTransformIdentity
}
guard let imageScale = imageView.imageScale else {
return CGAffineTransformIdentity
}
guard let imageTransform = imageView.normalizedTransformForOrientation else {
return CGAffineTransformIdentity
}
let frame = imageView.frame
let imageWidth = image.size.width * imageScale.width
let imageHeight = image.size.height * imageScale.height
var transform = CGAffineTransformIdentity
// Rotate to match the image orientation.
transform = CGAffineTransformConcat(imageTransform, transform)
// Flip vertically (flipped in CIDetector).
transform = CGAffineTransformTranslate(transform, 0, CGRectGetHeight(frame))
transform = CGAffineTransformScale(transform, 1.0, -1.0)
// Centre align.
let tx: CGFloat = (CGRectGetWidth(frame) - imageWidth) * 0.5
let ty: CGFloat = (CGRectGetHeight(frame) - imageHeight) * 0.5
transform = CGAffineTransformTranslate(transform, tx, ty)
// Scale to match UIImageView scaling.
transform = CGAffineTransformScale(transform, imageScale.width, imageScale.height)
return transform
}
}
关于ios - 用 UIBezierPath 表示 CIRectangleFeature - Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38215593/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!