画板

1.把一条条路径当成model,有线宽,颜色,存进数组,画到视图上,

PathModel.h

// line --- model

//颜色\路径\宽度


@interface PathModel : NSObject


@property (nonatomic, assign) CGMutablePathRef path;

@property (nonatomic, strong) UIColor *color;

@property (nonatomic, assign) CGFloat width;


PathModel.m

- (void)dealloc

{

//释放路径

    CGPathRelease(_path);

}


- (void)setPath:(CGMutablePathRef)path

{

    if (_path != path) {

        CGPathRelease(_path);

        _path = (CGMutablePathRef)CGPathRetain(path);

    }

}


2.自定义Button(UIControl 画)

ToolButton.h


#import <UIKit/UIKit.h>

//定义button的类型

typedef enum : NSUInteger{

    kToolButtonTitleType,

    kToolButtonColorType,

    kToolButtonWidthType,

    kToolButtonNoneType

} kToolButtonType;


@interface ToolButton : UIControl

//是否选中

@property (nonatomic, assign) BOOL checked;


@property (nonatomic, copy) NSString *title;

@property (nonatomic, strong) UIColor *color;

@property (nonatomic, assign) CGFloat width;


@property (nonatomic, assign) kToolButtonType type;


@end

ToolButton.m

#import "ToolButton.h"


@implementation ToolButton


- (void)drawRect:(CGRect)rect {


    CGContextRef context = UIGraphicsGetCurrentContext();

    

    if (self.type == kToolButtonTitleType || self.type == kToolButtonWidthType) {

        //绘制标题

        NSMutableParagraphStyle *style = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];

        style.alignment = NSTextAlignmentCenter;

        

        NSDictionary *attr = @{

                               NSFontAttributeName: [UIFont boldSystemFontOfSize:20],

                               NSParagraphStyleAttributeName : style

                               };

        

        [self.title drawInRect:rect withAttributes:attr];

        

       

    } else if (self.type == kToolButtonColorType) {

        

        //画内切圆

        CGContextAddEllipseInRect(context, rect);

        

        //CGContextSetFillColorWithColor(context, self.color.CGColor);

        [self.color setFill];

        

        CGContextDrawPath(context, kCGPathFill);

    }

    

    //绘制选中效果

    if (self.checked) {

        [[UIColor blackColor] set];

        UIRectFrame(rect);

    }

   

    

}


- (void)setChecked:(BOOL)checked

{

    _checked = checked;

    

    [self setNeedsDisplay];

}


@end

3.工具栏
ToolView.h

#import <UIKit/UIKit.h>


//block类型

typedef void(^ChangeColorBlock)(UIColor *);

typedef void(^ChangeWidthBlock)(CGFloat);


typedef void(^ChangeBlock)(void);


@class ToolButton;

@interface ToolView : UIView

{

    UIView *_buttonView;    //菜单栏

    UIView *_colorView;     //颜色

    UIView *_widthView;     //线宽

    

    

    //声明block

    ChangeColorBlock _colorBlock;

    ChangeWidthBlock _widthBlock;

    

    ChangeBlock _eraseBlock;

    ChangeBlock _undoBlock;

    ChangeBlock _clearBlock;

}


@property (nonatomic, strong) ToolButton *lastButton;

@property (nonatomic, strong) ToolButton *lastColor;

@property (nonatomic, strong) ToolButton *lastWidth;


@property (nonatomic, copy) ChangeColorBlock colorBlock;

@property (nonatomic, copy) ChangeWidthBlock widthBlock;


- (void)addErase:(ChangeBlock)eraseBlock undo:(ChangeBlock)undoBlock clear:(ChangeBlock)clearBlock;


ToolView.m

- (instancetype)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

        

        [self createMenuView];

        

        [self creatColorView];

        

        [self createLineWidthView];

        

    }

    return self;

}


#pragma mark - 创建子视图

//菜单栏

- (void)createMenuView

{

    //菜单栏的父视图

    _buttonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), 25)];

    _buttonView.backgroundColor = [UIColor clearColor];

    [self addSubview:_buttonView];

    

    NSArray *titles = @[@"颜色", @"线宽", @"橡皮", @"撤销", @"清屏"];


    CGFloat width = CGRectGetWidth(self.bounds) / titles.count;

    

    //创建5个按钮

    for (int i = 0; i < titles.count; i++) {

        ToolButton *button = [[ToolButton allocinitWithFrame:CGRectMake(i * width, 0, width, 25)];

        //指定buttontitle类型

        button.type = kToolButtonTitleType;

        button.title = titles[i];

        

        button.backgroundColor = [UIColor clearColor];

        button.tag = 100 + i;

        

        [button addTarget:self

                   action:@selector(buttonAction:)

         forControlEvents:UIControlEventTouchUpInside];

        

        [_buttonView addSubview:button];

    }

}


//颜色栏

- (void)creatColorView

{

    _colorView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_buttonView.frame), CGRectGetWidth(self.bounds), 40)];

    _colorView.backgroundColor = [UIColor clearColor];

    _colorView.hidden = YES;

    [self addSubview:_colorView];

    

    NSArray *colors = @[

                        [UIColor darkGrayColor],

                        [UIColor redColor],

                        [UIColor greenColor],

                        [UIColor blueColor],

                        [UIColor yellowColor],

                        [UIColor orangeColor],

                        [UIColor purpleColor],

                        [UIColor brownColor],

                        [UIColor blackColor]

                        ];

    

    CGFloat width = CGRectGetWidth(self.bounds) / colors.count;

    //创建按钮

    for (int i = 0; i < colors.count; i++) {

        ToolButton *button = [[ToolButton allocinitWithFrame:CGRectMake(i * width, 0, width, width)];

        

        button.type = kToolButtonColorType;

        button.color = colors[i];

        

        button.backgroundColor = [UIColor clearColor];

        

        [button addTarget:self

                   action:@selector(tapColor:)

         forControlEvents:UIControlEventTouchUpInside];

        

        [_colorView addSubview:button];

    }

}


//线宽栏

- (void)createLineWidthView

{

    _widthView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_buttonView.frame), CGRectGetWidth(self.bounds), 40)];

    _widthView.hidden = YES;

    _widthView.backgroundColor = [UIColor clearColor];

    [self addSubview:_widthView];

    

    NSArray *widths = @[@1.0,@3.0,@5.0,@8.0,@10.0,@15.0,@20.0];

    

    CGFloat width = CGRectGetWidth(self.bounds) / widths.count;

    //创建按钮

    for (int i = 0; i < widths.count; i++) {

        ToolButton *button = [[ToolButton allocinitWithFrame:CGRectMake(i * width, 0, width, 25)];

        

        button.type = kToolButtonWidthType;

        button.title = [NSString stringWithFormat:@"%@", widths[i]];

        button.width = [widths[i] floatValue];

        

        button.backgroundColor = [UIColor clearColor];

        

        [button addTarget:self

                   action:@selector(tapWidth:)

         forControlEvents:UIControlEventTouchUpInside];

        

        [_widthView addSubview:button];

    }

}


#pragma mark - Actions

- (void)buttonAction:(ToolButton *)sender

{

    //1.把上一个button选中状态取消

    self.lastButton.checked = NO;

    

    //2.把点击的button设置为选中

    sender.checked = YES;

    

    //3.记录下选择的button

    self.lastButton = sender;

    

    //点击button,切换视图

    switch (sender.tag - 100) {

        case 0:

            _colorView.hidden = NO;

            _widthView.hidden = YES;

            break;

        case 1:

            _colorView.hidden = YES;

            _widthView.hidden = NO;

            break;

        case 2: //橡皮

            _eraseBlock();

            break;

        case 3: //撤销

            _undoBlock();

            break;

        case 4: //清屏

            _clearBlock();

            break;

        default:

            break;

    }

 

}


//颜色

- (void)tapColor:(ToolButton *)sender

{

    //1.把上一个button选中状态取消

    self.lastColor.checked = NO;

    

    //2.把点击的button设置为选中

    sender.checked = YES;

    

    //3.记录下选择的button

    self.lastColor = sender;


    //block调用

    if (_colorBlock != nil) {

        _colorBlock(sender.color);

    }

}


//线宽

- (void)tapWidth:(ToolButton *)sender

{

    //1.把上一个button选中状态取消

    self.lastWidth.checked = NO;

    

    //2.把点击的button设置为选中

    sender.checked = YES;

    

    //3.记录下选择的button

    self.lastWidth = sender;

    

    if (_widthBlock != nil) {

        _widthBlock(sender.width);

    }

}


- (void)addErase:(ChangeBlock)eraseBlock undo:(ChangeBlock)undoBlock clear:(ChangeBlock)clearBlock

{

    _eraseBlock = eraseBlock;

    _undoBlock = undoBlock;

    _clearBlock = clearBlock;

}


@end

4.绘画视图
PanelView.h

#import <UIKit/UIKit.h>


@interface PanelView : UIView

{

    NSMutableArray *_pathes;

}


@property (nonatomic, assign) CGMutablePathRef currentPath;

@property (nonatomic, strong) UIColor *currentColor;

@property (nonatomic, assign) CGFloat currentWidth;


//清屏

- (void)clear;

//撤销

- (void)undo;


@end

PanelView.m

@implementation PanelView

/*

 * 绘制多条线:

 * 1. 初始化就创建路径,一直使用同一条路径

 * 2. 每创建一个路径,就保存在数组中

 */


- (instancetype)initWithFrame:(CGRect)frame

{

    self = [super initWithFrame:frame];

    if (self) {

//       _path = CGPathCreateMutable();

        

        _pathes = [NSMutableArray array];

        

        //设置默认的画笔

        _currentColor = [UIColor blackColor];

        _currentWidth = 5;


    }

    return self;

}



- (void)drawRect:(CGRect)rect {

    

    //上下文

    CGContextRef context = UIGraphicsGetCurrentContext();

    

    /*

    //从数组中取出路径,绘制

    for (id path in _pathes) {

        

        CGMutablePathRef lastPath = (__bridge CGMutablePathRef)(path);

        

        CGContextAddPath(context, lastPath);

        

        //设置颜色和线宽

        //[[UIColor redColor] set];

        

//        CGContextSetRGBStrokeColor(context, 0, 0, 0, 1)

        

//        CGContextSetLineWidth(context, <#CGFloat width#>)

        

        CGContextDrawPath(context, kCGPathStroke);

        

    }

     */

    //遍历所有的路径,把路径绘制

    for (PathModel *model in _pathes) {

        //路径添加到上下文

        CGContextAddPath(context, model.path);

        //设置上下文(颜色)

        [model.color set];

        //(线宽)

        CGContextSetLineWidth(context, model.width);

        //绘制

        CGContextDrawPath(context, kCGPathStroke);

    }

    

    //第一次绘制的路径如果为空,就不绘制

    if (_currentPath != nil) {

        

        //路径添加到上下文

        CGContextAddPath(context, _currentPath);

        

        //设置上下文

        CGContextSetLineWidth(context, _currentWidth);

        [_currentColor set];

        

        //绘制

        CGContextDrawPath(context, kCGPathStroke);

        

        /*

        PathModel *model = [_pathes objectAtIndex:0];

        CGContextAddPath(context, model.path);

        [model.color set];

        CGContextSetLineWidth(context, model.width);

         */

    }

}


//触摸开始

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

    UITouch *touch = [touches anyObject];

    CGPoint location = [touch locationInView:self];

    

    //创建路径

    _currentPath = CGPathCreateMutable();

    //设置起始点

    CGPathMoveToPoint(_currentPath, NULL, location.x, location.y);

    

}


//触摸移动

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{

    UITouch *touch = [touches anyObject];

    CGPoint location = [touch locationInView:self];

    

    //移动,路径上添加线

    CGPathAddLineToPoint(_currentPath, NULL, location.x, location.y);

    

    //手动调用drawRect:

    [self setNeedsDisplay];

    

}


//触摸结束

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

    /*

    UITouch *touch = [touches anyObject];

    CGPoint location = [touch locationInView:self];

    

    //路径上添加结束点

    CGPathAddLineToPoint(_currentPath, NULL, location.x, location.y);

     */

    

    //把路径保存 注意桥接

    //[_pathes addObject:(__bridge id)(_currentPath)];

    

//    if (_pathes == nil) {

//        _pathes = [NSMutableArray array];

//    }

    

    //创建model,保存绘图的属性

    PathModel *model = [[PathModel alloc] init];

    model.path = _currentPath;

    model.color = _currentColor;

    model.width = _currentWidth;

    

    [_pathes addObject:model];

    

    //释放路径

    CGPathRelease(_currentPath);_currentPath = nil;

}



#pragma mark - 图形界面方法

- (void)clear

{

    [_pathes removeAllObjects];

//    _pathes = [NSMutableArray array];

    

//    _pathes = nil;

    

    //调用drawRect方法,重绘界面

    [self setNeedsDisplay];

}


- (void)undo

{

    [_pathes removeLastObject];

    

    [self setNeedsDisplay];

}



@end


ViewController.m

#define kStatusBarHeight    20

#define kScreenWidth        ([UIScreen mainScreen].bounds.size.width)

@interface ViewController ()


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    

    PanelView *panel = [[PanelView alloc] initWithFrame:self.view.bounds];

    panel.backgroundColor = [UIColor whiteColor];

    [self.view addSubview:panel];


    

    ToolView *tool = [[ToolView alloc] initWithFrame:CGRectMake(0, kStatusBarHeight, kScreenWidth, 100)];

    tool.backgroundColor = [UIColor grayColor];

    [self.view addSubview:tool];

    

    //block赋值,设置block来修改相应的属性

    tool.colorBlock = ^(UIColor *color){

        panel.currentColor = color;

    };

    

    tool.widthBlock = ^(CGFloat width){

        panel.currentWidth = width;

    };

    

    [tool addErase:^{

        panel.currentColor = [UIColor whiteColor];

        panel.currentWidth = 20;

    } undo:^{

        [panel undo];

    } clear:^{

        [panel clear];

    }];


}

效果图






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值