首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

SpringBoot2.0 基础案例(13):基于Cache注解模式,管理Redis缓存

一、Cache缓存简介 从Spring3开始定义Cache和CacheManager接口来统一不同的缓存技术;Cache接口为缓存的组件规范定义,包含缓存的各种操作集合;Cache接口下Spring提供了各种缓存的实现;如RedisCache,EhCacheCache ,ConcurrentMapCache等; 二、核心API 1、Cache缓存接口定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等2、CacheManager缓存管理器,管理各种缓存(cache)组件3、@Cacheable 主要针对方法配置,能够根据方法的请求参数对其进行缓存 Cacheable 执行流程 1)方法运行之前,按照cacheNames指定的名字先去查询Cache 缓存组件 2)第一次获取缓存如果没有Cache组件会自动创建 3)Cache中查找缓存的内容,使用一个key,默认就是方法的参数 4)key是按照某种策略生成的;默认是使用keyGenerator生成的,这里使用自定义配置 5)没有查到缓存就调用目标方法; 6)将目标方法返回的结果,放进缓存中 Cacheable 注解属性 cacheNames/value:指定方法返回结果使用的缓存组件的名字,可以指定多个缓存 key:缓存数据使用的key key/keyGenerator:key的生成器,可以自定义 cacheManager:指定缓存管理器 cacheResolver:指定缓存解析器 condition:指定符合条件的数据才缓存 unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存 sync:是否使用异步模式 4、@CacheEvict清除缓存 CacheEvict:缓存清除 key:指定要清除的数据 allEntries = true:指定清除这个缓存中所有的数据 beforeInvocation = false:方法之前执行清除缓存,出现异常不执行 beforeInvocation = true:代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除 5、@CachePut 保证方法被调用,又希望结果被缓存。与@Cacheable区别在于是否每次都调用方法,常用于更新,写入 CachePut:执行方法且缓存方法执行的结果 修改了数据库的某个数据,同时更新缓存; 执行流程 1)先调用目标方法 2)然后将目标方法的结果缓存起来 6、@EnableCaching开启基于注解的缓存7、keyGenerator 缓存数据时key生成策略8、@CacheConfig统一配置本类的缓存注解的属性 三、与SpringBoot2.0整合 1、核心依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 2、Cache缓存配置 import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.lang.reflect.Method; @Configuration public class CacheConfig { /** * 自定义 Cache 的 key 生成器 */ @Bean("oneKeyGenerator") public KeyGenerator getKeyGenerator (){ return new KeyGenerator() { @Override public Object generate(Object obj, Method method, Object... objects) { return "KeyGenerator:"+method.getName(); } } ; } } 3、启动类注解开启Cache @EnableCaching // 开启Cache 缓存注解 @SpringBootApplication public class CacheApplication { public static void main(String[] args) { SpringApplication.run(CacheApplication.class,args) ; } } 4、Cache注解使用代码 1)封装增删改查接口 import com.boot.cache.entity.User; public interface UserService { // 增、改、查、删 User addUser (User user) ; User updateUser (Integer id) ; User selectUser (Integer id) ; void deleteUser (Integer id); } 2)Cache注解使用案例 import com.boot.cache.entity.User; import com.boot.cache.service.UserService; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService { // 使用自定义的key生成策略 // 缓存结果key:addUser::KeyGenerator:addUser @CachePut(value = "addUser",keyGenerator="oneKeyGenerator") @Override public User addUser(User user) { return user ; } // 缓存结果key:updateUser::2 @CachePut(value = "updateUser",key = "#result.id") @Override public User updateUser(Integer id) { User user = new User() ; user.setId(id); user.setName("smile"); return user; } // 缓存结果key: selectUser::3 @Cacheable(cacheNames = "selectUser",key = "#id") @Override public User selectUser(Integer id) { User user = new User() ; user.setId(id); user.setName("cicadaSmile"); return user; } // 删除指定key: selectUser::3 @CacheEvict(value = "selectUser",key = "#id",beforeInvocation = true) @Override public void deleteUser(Integer id) { } } 5、测试代码块 @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = CacheApplication.class) public class CacheTest { @Resource private UserService userService ; // 分别测试:增、改、查、删,四个方法 @Test public void testAdd (){ User user = new User() ; user.setId(1); user.setName("cicada"); userService.addUser(user) ; } @Test public void testUpdate (){ userService.updateUser(2) ; } @Test public void testSelect (){ userService.selectUser(3) ; } @Test public void testDelete (){ userService.deleteUser(3) ; } } 四、源代码地址 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 码云地址:知了一笑 https://gitee.com/cicadasmile/spring-boot-base

优秀的个人博客,低调大师

Java面试题大全系列之Java基础类库(一)

动力节点Java学院整理 1、java 中有几种类型的流?JDK 为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类? 字节流,字符流。字节流继承于 InputStream OutputStream,字符流继承于 Reader Writer。在 java.io 包中还有许多其他的流,低层流与调层流,高层流主要是为了提高性能和使用方便。 2、启动一个线程是用 run()还是 start()?启动一个线程是调用 start()方法,启动线程并调用 run 方法。 3、线程的基本概念、线程的基本状态以及状态之间的关系 线程是进程内的并发,没有自已内存空间,共享进程的,线程间的通信成本较低。Java 中的线程有四种状态分别是:运行、就绪、挂起、结束。 4、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 用什么关键字修饰同步方法?stop()和 suspend()方法为何不推荐使用?Extends ThreadImplements Runnable同步Public synchronized aa(){}Public void cc(object aa){synchronized(aa){}}用 synchoronized 修饰同步方法。答:多线程有两种实现方法,分别是继承 Thread 类与实现 Runnable 接口同步的实现方面有两种,分别是 synchronized,wait 与 notify反对使用 stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用 suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用 suspend(),而应在自己的 Thread 类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用 wait()命其进入等待状态。若标志指出线程应当恢复,则用一个 notify()重新启动线程。 5、集合框架有什么?Collection MapList set HashMapArrayList linkedList HashSet TreeSet 动力节点Java学院整理发布 转载请注明出处

优秀的个人博客,低调大师

Python零基础学习笔记(四十一)—— 面向对象编程思想

面向对象三大特点: 封装、继承、多态 封装: 在python中,封装就是将有相同属性和功能的事物归纳好之后放在同一个类(class)中 优点:简化代码、便于日后修改和维护 下面定义一个人类作为例子: 里面包含了对象的初始化(构造函数),变量的访问限制(共有变量和私有变量) class Person(object): def __init__(self, name, age, money, height): self.__name__ = name #特殊变量,可以直接访问 self.age = age #普通变量 self.__money = money #私有变量,不能直接访问 self._height = height #可以直接访问,但是请视为私有变量,尽量不要直接访问 def show(self): print("My name is %s, I am %d years old. I have %d $$."%(self.__name__, self.age, self.__money)) def setMoney(self, money): if money < 0: pass else: self.__money = money def getMoney(self): return self.money per = Person("Jjking", 23, 50, 60) per.show() per.money = 200 per.age = 24 per.show() per.__money = 200 print(per.__money) per.setMoney(200) per.show() print(per.getMoney()) #动态数据语言的体现,在执行过程中可以添加属性 per.a = 34 print(per.a) 执行结果: 继承: 子类继承父类的属性,父类有的功能和属性(私有除外),子类都可以用 下面是例子: 因为父类是Animal类,定义了eat的行为,子类是Cat类继承了Animal的eat的行为,所以在创建一个cat的对象的时候,这个对象就直接有了cat的行为,因此执行结果就是小白eat class Animal(object): def __init__(self, namne): self.name = namne def eat(self): print(self.name + "eat") class Cat(Animal): def __init__(self, name): Animal.__init__(self, name) cat = Cat("小白") cat.eat() #执行结果 小白eat 多态: 用一个例子来理解一下多态,就是有继承,有函数重写,父类引用指向子类对象 #人类 class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def whoAmI(self): return 'I am a Person, my name is %s' % self.name #学生类 class Student(Person): def __init__(self, name, gender, score): super(Student, self).__init__(name, gender) self.score = score def whoAmI(self): return 'I am a Student, my name is %s' % self.name #老师类 class Teacher(Person): def __init__(self, name, gender, course): super(Teacher, self).__init__(name, gender) self.course = course def whoAmI(self): return 'I am a Teacher, my name is %s' % self.name def who_am_i(x): print(x.whoAmI()) p = Person('Tim', 'Male') s = Student('Bob', 'Male', 88) t = Teacher('Alice', 'Female', 'English') who_am_i(p) who_am_i(s) who_am_i(t)

优秀的个人博客,低调大师

Python零基础学习笔记(十二)—— 字符串及其常用方法

''' 什么是字符串 字符串就是以单引号或双引号括起来的任意文本 ''' #创建字符串 str1 = "My name is jjking" str2 = "I am a Little White" ''' 字符串运算 ''' #字符串连接 str3 = "My name is " str4 = "jjking. " str5 = str3 + str4 print("str5 = ",str5) #输入重复字符串 str6 = str5 * 3 print(str6) #访问字符转中的某一个字符,通过索引下标查找字符,从0开始 str7 = "My name is jjking" print(str7[0]) print(str7[1]) print(str7[2]) print(str7[3]) #第 0 个为 M, 第1个为 y, 第 2 个是空格没打印出来,以此类推... #截取字符串中的一部分 str8 = "My name is jjking" str9 = str8[0:7] #[包含,不包含] str10 = str8[:7] #默认为0开始 str11 = str8[4:] #默认截取到最后 print(str9) print(str10) print(str11) #成员运算符测试jjking是否在str8 的字符串中 if "jjking" in str8: print("jjking 在 str8中出现了") print("name" in str8) #输出格式化 num = 1 str12 = "My name is jjking." f = 1.23 print("num = ", num, "str12 =", str12, "f =", f ) #使用%s %d %f 占位符 print("num = %d, str = %s, f = %f" % (num, str12, f)) #%3.f 表示保留小数点后3位,四舍五入法 print("f = %.3f"% f) ''' 转义字符 \ \n 输出 换行 \\ 输出 \ \" 输出 " \t 制表符 ''' print("num = %d\nstr = %s\nf = %f" % (num, str12, f)) print("num = %d\n\"str = %s\"\nf = %f\\" % (num, str12, f)) print("one\tsecond") print("\\\t\\") # r 字符串中有好多字符需要转移时使用,python允许使用 r 表示内部字符串默认不转义 # windows系统下的路径打印常用 print(r"\\\t\\") print(r"C:\Users\Administrator\PycharmProjects\untitled\day003") #按照格式输出 print('''--------------- first second Third ''') str12 = "My name is jjking." #eval(str) #功能:将字符串str当成有效的表达式来求值并返回计算结果 num1 = eval("123") print(num1) print(type(num1)) print(eval("+123")) print(eval("-123")) print(eval("12+3")) print(eval("12-3")) #len(str) #功能:返回字符串的长度 print(len("My name is jjking!")) print(len(str12)) #lower() 转换字符串中的大写字母为小写字母 print(str12.lower()) #upper() 转换字符串中的小写字母为大写字母 print(str12.upper()) #swapcase() 大小写互换 print(str12.swapcase()) #capitalize() 首字母大写 print(str12.capitalize()) #title() 单词的首字母大写 print(str12.title()) #center(width, fillchar) 返回指定宽度的居中的字符串用后面的字符填充 print(str12.center(30,"#")) #ljust(width[, fillchar]) 返回指定宽度的左对齐的字符串用后面的字符填充 print(str12.ljust(30,"*")) #rjust(width[, fillchar]) 返回指定宽度的右对齐的字符串用后面的字符填充 print(str12.rjust(30,"*")) #zfill(width) 返回指定宽度右对齐前面用 0 填充的字符串 print(str12.zfill(30)) #count([str[, start][, end]) 返回字符串中str出现的次数,可以指定一个范围,默认从头到尾 print(str12.count("is")) #find(str[, start][, end]) # 从左向右检测str字符串是否包含在字符串中,可以指定范围,默认从头到尾得到的是第一次出现的开始下标,没有返回-1 print(str12.find("is")) #rfind(str[, start][, end]) # 从右向左检测str字符串是否包含在字符串中,可以指定范围,默认从头到尾得到的是第一次出现的开始下标,没有返回-1 print(str12.rfind("is")) #index(str,start=0, end=len(str)) 和find()一样,但在str不存在的时候会报异常 print(str12.index("is")) #rindex(str,start=0, end=len(str)) 和rfind()一样,但在str不存在的时候会报异常 print(str12.rindex("is")) #lstrip() 截掉字符串左侧指定的字符,要从头开始,默认为空格 print(str12.lstrip("My")) #lstrip() 截掉字符串右侧制定的字符,,要从最后面开始,默认为空格 print(str12.rstrip("jjking.")) #split("", a) 以“ ”中的内容为分隔符截取字符串,a默认为1 print(str12.split(" ")) #splitlines([keepends]) 按照# ('\r', '\r\n', '\n')分隔 stra = (''' My name is jjking. I am a boy! ''') print(stra.splitlines()) #join(seq) 以一个特定的字符串分隔符,将seq中的所有元素组合成一个字符串 strjo =["a", "s", "s"] str_join = "##".join(strjo) print(str_join) #max() 返回字符串中ascii码值最大的 print(max(str12)) #min() 返回字符串中ascii码值最小的 print("$" + min(str12) + "$") #replace(oldstr, newstr, count) 默认全部替换,如果指定了count数量,那么只替换前count个 str_replace = str12.replace("is", "isn't", 1) print(str_replace) #创建一个字符串映射表 str_maketrans = str12.maketrans("is", "nt") # i->n s->t str13 = "P is is kjs is;" str_translate = str13.translate(str_maketrans) print(str_translate) #startswith(str, start = 0, end = len(str)) #在给定的范围内判断是否以给定的字符串开头的,如果没有给定范围,默认整个字符串 print(str12.startswith("is" )) #endwith(str, start = 0, end = len(str)) #在给定的范围内判断是否以给定的字符串结尾的,如果没有给定范围,默认整个字符串 print(str12.endswith("is" )) #编码 #encode(encoding="utf-8", error="strict") print(str12.encode()) data = str12.encode("utf-8", "ignore") #解码 注意:要和编码使用的码制一致 python3之后没有decode()了 str_encode = data.decode("utf-8","ignore") print("###",str_encode, "###") print(type(str_encode)) #isalpha() #如果字符串中至少有一个字符且所有字符都是字母返回True,否则返回False print(str12.isalpha()) #isalnum() #如果字符串中至少有一个字符且所有字符都是字母或数字返回True,否则返回False print(str12.isalnum()) #isupper() #如果字符串中至少有一个英文字符且所有字符都是大写字母或数字或特殊字符返回True,否则返回False str_upper = "ACSD" print(str_upper.isupper()) print("ASD1".isupper()) print("ASD1#".isupper()) #islower() #如果字符串中至少有一个英文字符且所有字符都是小写字母或数字或特殊字符返回True,否则返回False str_upper = "acs" print(str_upper.islower()) print("asd1".islower()) print("asd1#".islower()) #istitle() #如果字符串是标题化的返回True,否则返回False print("My name".istitle()) #错的 print("My Name".istitle()) #对的 #isdigit() #如果字符串只包含数字字符返回True,否则返回False print("123".isdigit()) print("ade".isdigit()) #错的 #isnumeric() #如果字符串只包含数字返回True,否则返回False print("123".isnumeric()) print("ade".isnumeric()) #错的 #isdecimal() #如果字符串只包含十进制字符返回True,否则返回False print("123".isdecimal()) print("ade".isdecimal()) #错的 #isspace() #如果字符串中只包含空格则返回True,否则返回False print(" ".isspace()) print("\t".isspace()) print("\r".isspace()) print("\n".isspace()) #都是对的 执行结果: C:\Users\Administrator\AppData\Local\Programs\Python\Python37-32\python.exe C:/Users/Administrator/PycharmProjects/untitled/day003/String.py str5 = My name is jjking. My name is jjking. My name is jjking. My name is jjking. M y n My name My name ame is jjking jjking 在 str8中出现了 True num = 1 str12 = My name is jjking. f = 1.23 num = 1, str = My name is jjking., f = 1.230000 f = 1.230 num = 1 str = My name is jjking. f = 1.230000 num = 1 "str = My name is jjking." f = 1.230000\ one second \ \ \\\t\\ C:\Users\Administrator\PycharmProjects\untitled\day003 --------------- first second Third 123 <class 'int'> 123 -123 15 9 18 18 my name is jjking. MY NAME IS JJKING. mY NAME IS JJKING. My name is jjking. My Name Is Jjking. ######My name is jjking.###### My name is jjking.************ ************My name is jjking. 000000000000My name is jjking. 1 8 8 8 8 name is jjking. My name is ['My', 'name', 'is', 'jjking.'] ['', 'My name is jjking.', 'I am a boy!'] a##s##s y $ $ My name isn't jjking. P nt nt kjt nt; False False b'My name is jjking.' ### My name is jjking. ### <class 'str'> False False True True True True True True False True True False True False True False True True True True Process finished with exit code 0

优秀的个人博客,低调大师

基础目标检测算法介绍:CNN、RCNN、Fast RCNN和Faster RCNN

每次丢了东西,我们都希望有一种方法能快速定位出失物。现在,目标检测算法或许能做到。目标检测的用途遍布多个行业,从安防监控,到智慧城市中的实时交通监测。简单来说,这些技术背后都是强大的深度学习算法。 在这篇文章中,我们会进一步地了解这些用在目标检测中的算法,首先要从RCNN家族开始,例如RCNN、Fast RCNN和Faster RCNN。 1. 解决目标检测任务的简单方法(利用深度学习) 下图是描述目标检测算法如何工作的典型例子,图中的每个物体(不论是任务还是风筝),都能以一定的精确度被定位出来。 首先我们要说的就是在图像目标检测中用途最广、最简单的深度学习方法——卷积神经网络(CNN)。我要讲的是CNN的内部工作原理,首先让我们看看下面这张图片。 向网络中输入一张图片,接着将它传递到多个卷积和池化层中。最后输出目标所属的类别,听上去非常直接。 对每张输入的图片,我们都有对应的输出类别,那么这一技术能检测图片中多种目标吗?答案是肯定的!下面就让我们看看如何用一个卷积神经网络解决通用的目标检测问题。 1.首先,我们把下面的图片用作输入: 2.之后,我们将图片分成多个区域: 3.将每个区域看作单独的图片。 4.把这些区域照片传递给CNN,将它们分到不同类别中。 5.当我们把每个区域都分到对应的类别后,再把它们结合在一起,完成对原始图像的目标检测: 使用这一方法的问题在于,图片中的物体可能有不同的长宽比和空间位置。例如,在有些情况下,目标物体可能占据了图片的大部分,或者非常小。目标物体的形状也可能不同。 有了这些考虑因素,我们就需要分割很多个区域,需要大量计算力。所以为了解决这一问题,减少区域的分割,我们可以使用基于区域的CNN,它可以进行区域选择。 2. 基于区域的卷积神经网络介绍 2.1 RCNN简介 和在大量区域上工作不同,RCNN算法提出在图像中创建多个边界框,检查这些边框中是否含有目标物体。RCNN使用选择性搜索来从一张图片中提取这些边框。 首先,让我们明确什么是选择性搜索,以及它是如何辨别不同区域的。组成目标物体通常有四个要素:变化尺度、颜色、结构(材质)、所占面积。选择性搜索会确定物体在图片中的这些特征,然后基于这些特征突出不同区域。下面是选择搜索的一个简单案例: 首先将一张图片作为输入: 之后,它会生成最初的sub-分割,将图片分成多个区域: 基于颜色、结构、尺寸、形状,将相似的区域合并成更大的区域: 最后,生成最终的目标物体位置(Region of Interest)。 用RCNN检测目标物体的步骤如下: 我们首先取一个预训练卷积神经网络。 根据需要检测的目标类别数量,训练网络的最后一层。 得到每张图片的感兴趣区域(Region of Interest),对这些区域重新改造,以让其符合CNN的输入尺寸要求。 得到这些区域后,我们训练支持向量机(SVM)来辨别目标物体和背景。对每个类别,我们都要训练一个二元SVM。 最后,我们训练一个线性回归模型,为每个辨识到的物体生成更精确的边界框。 下面我们就用具体的案例解释一下。 首先,将以下图片作为输入: 之后,我们会用上文中的选择性搜索得到感兴趣区域: 将这些区域输入到CNN中,并经过卷积网络: CNN为每个区域提取特征,利用SVM将这些区域分成不同类别: 最后,用边界框回归预测每个区域的边界框位置: 这就是RCNN检测目标物体的方法。 2.2 RCNN的问题 现在,我们了解了RCNN能如何帮助进行目标检测,但是这一技术有自己的局限性。训练一个RCNN模型非常昂贵,并且步骤较多: 根据选择性搜索,要对每张图片提取2000个单独区域; 用CNN提取每个区域的特征。假设我们有N张图片,那么CNN特征就是N*2000; 用RCNN进行目标检测的整个过程有三个模型: 用于特征提取的CNN 用于目标物体辨别的线性SVM分类器 调整边界框的回归模型。 这些过程合并在一起,会让RCNN的速度变慢,通常每个新图片需要40—50秒的时间进行预测,基本上无法处理大型数据集。 所以,这里我们介绍另一种能突破这些限制的目标检测技术。 3. Fast RCNN 3.1 Fast RCNN简介 想要减少RCNN算法的计算时间,可以用什么方法?我们可不可以在每张图片上只使用一次CNN即可得到全部的重点关注区域呢,而不是运行2000次。 RCNN的作者Ross Girshick提出了一种想法,在每张照片上只运行一次CNN,然后找到一种方法在2000个区域中进行计算。在Fast RCNN中,我们将图片输入到CNN中,会相应地生成传统特征映射。利用这些映射,就能提取出感兴趣区域。之后,我们使用一个Rol池化层将所有提出的区域重新修正到合适的尺寸,以输入到完全连接的网络中。 简单地说,这一过程含有以下步骤: 输入图片。 输入到卷积网络中,它生成感兴趣区域。 利用Rol池化层对这些区域重新调整,将其输入到完全连接网络中。 在网络的顶层用softmax层输出类别。同样使用一个线性回归层,输出相对应的边界框。 所以,和RCNN所需要的三个模型不同,Fast RCNN只用了一个模型就同时实现了区域的特征提取、分类、边界框生成。 同样,我们还用上面的图像作为案例,进行更直观的讲解。 首先,输入图像: 图像被传递到卷积网络中,返回感兴趣区域: 之后,在区域上应用Rol池化层,保证每个区域的尺寸相同: 最后,这些区域被传递到一个完全连接的网络中进行分类,并用softmax和线性回归层同时返回边界框: 3.2 Fast RCNN的问题 但是即使这样,Fast RCNN也有某些局限性。它同样用的是选择性搜索作为寻找感兴趣区域的,这一过程通常较慢。与RCNN不同的是,Fast RCNN处理一张图片大约需要2秒。但是在大型真实数据集上,这种速度仍然不够理想。 4.Faster RCNN 4.1 Faster RCNN简介 Faster RCNN是Fast RCNN的优化版本,二者主要的不同在于感兴趣区域的生成方法,Fast RCNN使用的是选择性搜索,而Faster RCNN用的是Region Proposal网络(RPN)。RPN将图像特征映射作为输入,生成一系列object proposals,每个都带有相应的分数。 下面是Faster RCNN工作的大致过程: 输入图像到卷积网络中,生成该图像的特征映射。 在特征映射上应用Region Proposal Network,返回object proposals和相应分数。 应用Rol池化层,将所有proposals修正到同样尺寸。 最后,将proposals传递到完全连接层,生成目标物体的边界框。 那么Region Proposal Network具体是如何工作的呢?首先,将CNN中得来的特征映射输入到Faster RCNN中,然后将其传递到Region Proposal Network中。RPN会在这些特征映射上使用一个滑动窗口,每个窗口会生成具有不同形状和尺寸的k个anchor box: Anchor boxes是固定尺寸的边界框,它们有不同的形状和大小。对每个anchor,RPN都会预测两点: 首先是anchor就是目标物体的概率(不考虑类别) 第二个就是anchor经过调整能更合适目标物体的边界框回归量 现在我们有了不同形状、尺寸的边界框,将它们传递到Rol池化层中。经过RPN的处理,proposals可能没有所述的类别。我们可以对每个proposal进行切割,让它们都含有目标物体。这就是Rol池化层的作用。它为每个anchor提取固定尺寸的特征映射: 之后,这些特征映射会传递到完全连接层,对目标进行分类并预测边界框。 4.2 Faster RCNN的问题 目前为止,我们所讨论的所有目标检测算法都用区域来辨别目标物体。网络并非一次性浏览所有图像,而是关注图像的多个部分。这就会出现两个问题: 算法需要让图像经过多个步骤才能提取出所有目标 由于有多个步骤嵌套,系统的表现常常取决于前面步骤的表现水平 5. 上述算法总结 下表对本文中提到的算法做了总结: 目标检测是很有趣的领域,在商业中也大有前景。得益于现代硬件和计算资源的发展,才能让这一技术有重要的突破。 本文只是目标检测算法的开门介绍,想了解更多的朋友可以直接私我。(关注主页) 如果你有不同见解也可直接在评论下方指教!

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册