ios动画学习(三)

使用Core Animation声明动画

CoreAnimation框架最基本的抽象类是CAAnimation类,这个类按照CAMediaTiming协议,提供了动画执行时间、速度,及重复次数这些基本设定,同时,它也遵循了CAAction协议,可提供该动画被图层驱动时的响应。
CAAnimation类之下定义了一系列的类,用来定义更具体的渐变动画类。层级如下:



下面是CABasicAnimation类使用:
- (IBAction)down:(id)sender {
    //使用CABasicAnimation建立动画,fromValue、toValue、byValue数值以oc对象形式存在
    CABasicAnimation * moveDown = [CABasicAnimation animationWithKeyPath:@"position.y"];
    //是视图在动画执行完成后,停留在最后位置
    //moveDown.removedOnCompletion = NO;
    //moveDown.fillMode = kCAFillModeForwards;
    
    //动画执行完成后,自动以动画形式原路返回
    //moveDown.autoreverses = YES;
    
    //动画重复执行的次数
    //moveDown.repeatCount = 2;
    moveDown.duration = 2.0;
    moveDown.toValue = [NSNumber numberWithInt:layer.position.y+100];
    //把动画应用到图层上,并且给动画加一个标识符moveDown
    [layer addAnimation:moveDown forKey:@"moveDown"];
}

- (IBAction)up:(id)sender {
    //使用CABasicAnimation建立动画
    //这种声明动画的方式改变的只有界面本身,而非对象属性。这和设定对象属性制作成的动画有非常大的区别。
    CABasicAnimation * moveUp = [CABasicAnimation animationWithKeyPath:@"position.y"];
    moveUp.duration = 5.0;
    //把正数封装成对象类型
    moveUp.toValue = [NSNumber numberWithInt:layer.position.y-100];
    //把动画应用到图层上,并且给动画加一个标识符moveUp
    [layer addAnimation:moveUp forKey:@"moveUp"];
}

- (IBAction)stopdown:(id)sender {
    //通过动画标识符取消动画
    [layer removeAnimationForKey:@"moveDown"];
}

- (IBAction)stopup:(id)sender {
    //通过动画标识符取消动画
    [layer removeAnimationForKey:@"moveUp"];
}

- (IBAction)dr:(id)sender {
    CABasicAnimation * downAndRight = [CABasicAnimation animationWithKeyPath:@"position"];
    downAndRight.duration = 5.0;
    //把c结构封装成对象类型
    NSValue * endPoint = [NSValue valueWithCGPoint:CGPointMake(layer.position.x + 100, layer.position.y+100)];
    downAndRight.toValue = endPoint;
    [layer addAnimation:downAndRight forKey:@"downAndRight"];
}

- (IBAction)ul:(id)sender {
    CABasicAnimation * upAndLeft = [CABasicAnimation animationWithKeyPath:@"position"];
    upAndLeft.duration = 5.0;
    NSValue * endPoint = [NSValue valueWithCGPoint:CGPointMake(layer.position.x - 100, layer.position.y-100)];
    upAndLeft.toValue = endPoint;
    [layer addAnimation:upAndLeft forKey:@"upAndLeft"];
}

- (IBAction)stopall:(id)sender {
    //停止该图层上所有动画
    [layer removeAllAnimations];
}

效果如下:



CAAnimation类对象也可以设定它的委托对象,当动画开始与结束时做自定义操作。CAAnimation的delegate属性如下:

可以看到它与其他类的delegate属性有些不同的是,它不需要遵循协议,只要委托对象中有如下函数即可:
- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

下面介绍CAPropertyAnimation的另一个子类CAKeyframeAnimation的用法。
CAKeyframeAnimation可以指定动画执行的路径,能够制作出非常“不规则”的动画。比如沿贝塞尔曲线的动画。
下面就来看看如何来实现贝塞尔曲线动画。
先看头文件:
//
//  PathView.h
//  LearnAnimation
//
//  Created by zg on 15/6/7.
//  Copyright (c) 2015年 zg. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface PathView : UIView{
    CAShapeLayer * shapeLayer;
}

-(void)go;

@end

定义一个圆形图层shapeLayer来执行动画,定义一个执行方法go
再看实现文件:
//
//  PathView.m
//  LearnAnimation
//
//  Created by zg on 15/6/7.
//  Copyright (c) 2015年 zg. All rights reserved.
//

#import "PathView.h"

@implementation PathView


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    [self drawPath];
    [self drawCircle];
}

//定义角度转弧度宏
#define DEGREES_TO_RADIANS(degrees) ((M_PI * degrees)/180)
//画路径
-(void)drawPath{
    UIBezierPath * path = [UIBezierPath bezierPath];
    path.lineCapStyle = kCGLineCapRound;//路径端点圆状
    [[UIColor blackColor]setStroke];
    [[UIColor blackColor]setFill];
    [path moveToPoint:CGPointMake(0, 100)];
    [path addCurveToPoint:CGPointMake(300, 100) controlPoint1:CGPointMake(75, 25) controlPoint2:CGPointMake(225, 175)];
    [path stroke];
    path.lineWidth = 3;
    [self setNeedsDisplay];
}

//画圆形图层
-(void)drawCircle{
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(4 , 100) radius:8 startAngle:0 endAngle:DEGREES_TO_RADIANS(360) clockwise:YES];
    [path closePath];
    shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = path.CGPath;
    [self.layer addSublayer:shapeLayer];
}

//执行动画
-(void)go{
    CAKeyframeAnimation * pathAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    pathAnim.duration = 5;
    //生成可变路径
    CGMutablePathRef mutablePath = CGPathCreateMutable();
    //坐标点,相对于当前图层pathLayer自身坐标系
    CGPathMoveToPoint(mutablePath, NULL, 0 , 0);
    CGPathAddCurveToPoint(mutablePath, NULL, 75, -75, 225, 75, 300, 0);
    pathAnim.path = mutablePath;
    [shapeLayer addAnimation:pathAnim forKey:nil];

}

@end

主要解释下实现函数go:
1、因为CAKeyframeAnimation是CAPropertyAnimation的子类,所以也会有animationWithKeyPath的动画声明方法。
2、CAKeyframeAnimation的path属性可以指定动画要执行的路径。
3、要重点说明的是CGMutablePathRef路径的坐标点是相对于执行动画的图层shapeLayer自身坐标系来计算的。
下面看效果:


三度空间的旋转:
layer有一个属性叫sublayerTransform,是渐变属性。通过CABasicAnimation动画来改变sublayerTransform属性,即可实现图层的三度空间旋转。
实现如下:
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self initSubLayer1];
    [self initSubLayer2];
    [self initSubLayer3];
    [self initPerspective];
}

-(void)initPerspective{
    //建立视点
    CATransform3D perspective = CATransform3DIdentity;
    int distance = 150;
    perspective.m34 = -1/distance;
    currentTransform = perspective;
    mContentView.layer.sublayerTransform = currentTransform;
}

-(void)initSubLayer1{
    subLayer1 = [CALayer layer];
    subLayer1.bounds = CGRectMake(0, 0, 100, 100);
    subLayer1.position = CGPointMake(140, 140);
    subLayer1.backgroundColor = [[UIColor blueColor]CGColor];
    subLayer1.cornerRadius = 10;//圆角半径
    subLayer1.borderColor = [[UIColor blackColor]CGColor];
    subLayer1.borderWidth= 2;
    subLayer1.opacity = 0.5;
    [mContentView.layer addSublayer:subLayer1];
}

-(void)initSubLayer2{
    subLayer2 = [CALayer layer];
    subLayer2.bounds = CGRectMake(0, 0, 100, 100);
    subLayer2.position = CGPointMake(150, 150);
    subLayer2.backgroundColor = [[UIColor greenColor]CGColor];
    subLayer2.cornerRadius = 10;//圆角半径
    subLayer2.borderColor = [[UIColor blackColor]CGColor];
    subLayer2.borderWidth= 2;
    subLayer2.opacity = 0.5;
    [mContentView.layer addSublayer:subLayer2];
}

-(void)initSubLayer3{
    subLayer3 = [CALayer layer];
    subLayer3.bounds = CGRectMake(0, 0, 100, 100);
    subLayer3.position = CGPointMake(160, 160);
    subLayer3.backgroundColor = [[UIColor redColor]CGColor];
    subLayer3.cornerRadius = 10;//圆角半径
    subLayer3.borderColor = [[UIColor blackColor]CGColor];
    subLayer3.borderWidth= 2;
    subLayer3.opacity = 0.5;
    [mContentView.layer addSublayer:subLayer3];
}

- (IBAction)rotateZ:(id)sender {
    CABasicAnimation * rotateAnim = [CABasicAnimation animationWithKeyPath:@"sublayerTransform"];
    rotateAnim.fillMode = kCAFillModeForwards;
    rotateAnim.removedOnCompletion = NO;
    
    rotateAnim.duration = 3;
    CATransform3D rotateX3D = CATransform3DRotate(currentTransform, M_PI/6, 0, 0, 1);
    NSValue  * toValue = [NSValue valueWithCATransform3D:rotateX3D];
    rotateAnim.toValue = toValue;
    [mContentView.layer addAnimation:rotateAnim forKey:nil];
    currentTransform = rotateX3D;
}

当执行rotateZ函数可实现如下效果:






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值