• 第十八节、基于传统图像处理的目标检测与识别(HOG+SVM附代码)
  • 人工智能-图像识别

    2019-04-18 15:41:10
    图像识别技术是信息时代的一门重要的技术,其产生目的是为了让计算机代替人类去处理大量的物理信息。随着计算机技术的发展,人类对图像识别技术的认识越来越深刻。图像识别技术的过程...从中可以总结出图像处理技...

    图像识别

      图像识别技术是信息时代的一门重要的技术,其产生目的是为了让计算机代替人类去处理大量的物理信息。随着计算机技术的发展,人类对图像识别技术的认识越来越深刻。图像识别技术的过程分为信息的获取、预处理、特征抽取和选择、分类器设计和分类决策。简单分析了图像识别技术的引入、其技术原理以及模式识别等,之后介绍了神经网络的图像识别技术和非线性降维的图像识别技术及图像识别技术的应用。从中可以总结出图像处理技术的应用广泛,人类的生活将无法离开图像识别技术,研究图像识别技术具有重大意义。

    1、图像识别技术的引入

      图像识别是人工智能的一个重要领域。图像识别的发展经历了三个阶段:文字识别、数字图像处理与识别、物体识别。图像识别,顾名思义,就是对图像做出各种处理、分析,最终识别我们所要研究的目标。今天所指的图像识别并不仅仅是用人类的肉眼,而是借助计算机技术进行识别。虽然人类的识别能力很强大,但是对于高速发展的社会,人类自身识别能力已经满足不了我们的需求,于是就产生了基于计算机的图像识别技术。这就像人类研究生物细胞,完全靠肉眼观察细胞是不现实的,这样自然就产生了显微镜等用于精确观测的仪器。通常一个领域有固有技术无法解决的需求时,就会产生相应的新技术。图像识别技术也是如此,此技术的产生就是为了让计算机代替人类去处理大量的物理信息,解决人类无法识别或者识别率特别低的信息。

    1.1 图像识别技术原理

      其实,图像识别技术背后的原理并不是很难,只是其要处理的信息比较繁琐。计算机的任何处理技术都不是凭空产生的,它都是学者们从生活实践中得到启发而利用程序将其模拟实现的。计算机的图像识别技术和人类的图像识别在原理上并没有本质的区别,只是机器缺少人类在感觉与视觉差上的影响罢了。人类的图像识别也不单单是凭借整个图像存储在脑海中的记忆来识别的,我们识别图像都是依靠图像所具有的本身特征而先将这些图像分了类,然后通过各个类别所具有的特征将图像识别出来的,只是很多时候我们没有意识到这一点。当看到一张图片时,我们的大脑会迅速感应到是否见过此图片或与其相似的图片。其实在“看到”与“感应到”的中间经历了一个迅速识别过程,这个识别的过程和搜索有些类似。在这个过程中,我们的大脑会根据存储记忆中已经分好的类别进行识别,查看是否有与该图像具有相同或类似特征的存储记忆,从而识别出是否见过该图像。机器的图像识别技术也是如此,通过分类并提取重要特征而排除多余的信息来识别图像。机器所提取出的这些特征有时会非常明显,有时又是很普通,这在很大的程度上影响了机器识别的速率。总之,在计算机的视觉识别中,图像的内容通常是用图像特征进行描述。

    1.2 模式识别

      模式识别是人工智能和信息科学的重要组成部分。模式识别是指对表示事物或现象的不同形式的信息做分析和处理从而得到一个对事物或现象做出描述、辨认和分类等的过程。

      计算机的图像识别技术就是模拟人类的图像识别过程。在图像识别的过程中进行模式识别是必不可少的。模式识别原本是人类的一项基本智能。但随着计算机的发展和人工智能的兴起,人类本身的模式识别已经满足不了生活的需要,于是人类就希望用计算机来代替或扩展人类的部分脑力劳动。这样计算机的模式识别就产生了。简单地说,模式识别就是对数据进行分类,它是一门与数学紧密结合的科学,其中所用的思想大部分是概率与统计。模式识别主要分为三种:统计模式识别、句法模式识别、模糊模式识别。

    2、图像识别技术的过程

      既然计算机的图像识别技术与人类的图像识别原理相同,那它们的过程也是大同小异的。图像识别技术的过程分以下几步:信息的获取、预处理、特征抽取和选择、分类器设计和分类决策。

      信息的获取是指通过传感器,将光或声音等信息转化为电信息。也就是获取研究对象的基本信息并通过某种方法将其转变为机器能够认识的信息。

      预处理主要是指图像处理中的去噪、平滑、变换等的操作,从而加强图像的重要特征。

      特征抽取和选择是指在模式识别中,需要进行特征的抽取和选择。简单的理解就是我们所研究的图像是各式各样的,如果要利用某种方法将它们区分开,就要通过这些图像所具有的本身特征来识别,而获取这些特征的过程就是特征抽取。在特征抽取中所得到的特征也许对此次识别并不都是有用的,这个时候就要提取有用的特征,这就是特征的选择。特征抽取和选择在图像识别过程中是非常关键的技术之一,所以对这一步的理解是图像识别的重点。

      分类器设计是指通过训练而得到一种识别规则,通过此识别规则可以得到一种特征分类,使图像识别技术能够得到高识别率。分类决策是指在特征空间中对被识别对象进行分类,从而更好地识别所研究的对象具体属于哪一类。

    3、图像识别技术的分析

      随着计算机技术的迅速发展和科技的不断进步,图像识别技术已经在众多领域中得到了应用。2015年2月15日新浪科技发布一条新闻:“微软最近公布了一篇关于图像识别的研究论文,在一项图像识别的基准测试中,电脑系统识别能力已经超越了人类。人类在归类数据库Image Net中的图像识别错误率为5.1%,而微软研究小组的这个深度学习系统可以达到4.94%的错误率。”从这则新闻中我们可以看出图像识别技术在图像识别方面已经有要超越人类的图像识别能力的趋势。这也说明未来图像识别技术有更大的研究意义与潜力。而且,计算机在很多方面确实具有人类所无法超越的优势,也正是因为这样,图像识别技术才能为人类社会带来更多的应用。

    3.1神经网络的图像识别技术

      神经网络图像识别技术是一种比较新型的图像识别技术,是在传统的图像识别方法和基础上融合神经网络算法的一种图像识别方法。这里的神经网络是指人工神经网络,也就是说这种神经网络并不是动物本身所具有的真正的神经网络,而是人类模仿动物神经网络后人工生成的。在神经网络图像识别技术中,遗传算法与BP网络相融合的神经网络图像识别模型是非常经典的,在很多领域都有它的应用。在图像识别系统中利用神经网络系统,一般会先提取图像的特征,再利用图像所具有的特征映射到神经网络进行图像识别分类。以汽车拍照自动识别技术为例,当汽车通过的时候,汽车自身具有的检测设备会有所感应。此时检测设备就会启用图像采集装置来获取汽车正反面的图像。获取了图像后必须将图像上传到计算机进行保存以便识别。最后车牌定位模块就会提取车牌信息,对车牌上的字符进行识别并显示最终的结果。在对车牌上的字符进行识别的过程中就用到了基于模板匹配算法和基于人工神经网络算法。

    3.2非线性降维的图像识别技术

      计算机的图像识别技术是一个异常高维的识别技术。不管图像本身的分辨率如何,其产生的数据经常是多维性的,这给计算机的识别带来了非常大的困难。想让计算机具有高效地识别能力,最直接有效的方法就是降维。降维分为线性降维和非线性降维。例如主成分分析(PCA)和线性奇异分析(LDA)等就是常见的线性降维方法,它们的特点是简单、易于理解。但是通过线性降维处理的是整体的数据集合,所求的是整个数据集合的最优低维投影。经过验证,这种线性的降维策略计算复杂度高而且占用相对较多的时间和空间,因此就产生了基于非线性降维的图像识别技术,它是一种极其有效的非线性特征提取方法。此技术可以发现图像的非线性结构而且可以在不破坏其本征结构的基础上对其进行降维,使计算机的图像识别在尽量低的维度上进行,这样就提高了识别速率。例如人脸图像识别系统所需的维数通常很高,其复杂度之高对计算机来说无疑是巨大的“灾难”。由于在高维度空间中人脸图像的不均匀分布,使得人类可以通过非线性降维技术来得到分布紧凑的人脸图像,从而提高人脸识别技术的高效性。

    3.3 图像识别技术的应用及前景 

      计算机的图像识别技术在公共安全、生物、工业、农业、交通、医疗等很多领域都有应用。例如交通方面的车牌识别系统;公共安全方面的人脸识别技术、指纹识别技术;农业方面的种子识别技术、食品品质检测技术;医学方面的心电图识别技术等。随着计算机技术的不断发展,图像识别技术也在不断地优化,其算法也在不断地改进。图像是人类获取和交换信息的主要来源,因此与图像相关的图像识别技术必定也是未来的研究重点。以后计算机的图像识别技术很有可能在更多的领域崭露头角,它的应用前景也是不可限量的,人类的生活也将更加离不开图像识别技术。

      图像识别技术虽然是刚兴起的技术,但其应用已是相当广泛。并且,图像识别技术也在不断地成长,随着科技的不断进步,人类对图像识别技术的认识也会更加深刻。未来图像识别技术将会更加强大,更加智能地出现在我们的生活中,为人类社会的更多领域带来重大的应用。在21世纪这个信息化的时代,我们无法想象离开了图像识别技术以后我们的生活会变成什么样。图像识别技术是人类现在以及未来生活必不可少的一项技术。

    人工智能

      Fly-AI竞赛服务平台是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台。每周免费提供项目开源算法样例,支持算法能力变现以及快速的迭代算法模型。有兴趣参与图像识别、语音、自然语言处理的AI开发者,可以参与竞赛并且有奖金可以赚取。

      https://www.flyai.com/d/OCRWords    3981个中文文字图像识别

      https://www.flyai.com/d/BirdClassification     200种鸟类图像分类

     

     

     

     

     

     

    展开全文
  • 最近各种事情耽搁,OpenCV的学习也...做一个鸟类检测模型首先需要训练出一个识别用的.xml文件,下面就开始进行训练。   一、准备样本集 样本集需要正样本集和负样本集。 正样本集:正样本集为包含“鸟类”的灰...

    最近各种事情耽搁,OpenCV的学习也没有进展。

    因为项目需求,所以自己做了这样一个基于Haar特征级联分类器的鸟类检测模型,记录下来。

    OpenCV官方文档中有一个Haar级联分类器做的人脸检测例程,自行参阅文档。

    做一个鸟类检测模型首先需要训练出一个识别用的.xml文件,下面就开始进行训练。

     

    一、准备样本集

    样本集需要正样本集和负样本集。

    正样本集:正样本集为包含“鸟类”的灰度图,一般大于等于2000张,尺寸不能太大(20*40),尺寸太大会导致训练时间过长。

    负样本集:负样本集为不含“鸟类”的任何图片,一般大于等于5000张,尺寸比正样本集稍大(60*60)。

    由于项目要求不高,所有的样本集都是我自己在网上找的图片,然后用python脚本对尺寸进行了调整,全部为灰度图。

    左边是正样本集(40*40),右边是负样本集(100*100)。PS:由于自己做的样本集数量不大,所有尺寸稍大

     

    二、准备文件夹

    将正负样本集分别放入pos和neg文件夹,存放在路径D:\Anaconda\pkgs\opencv-3.3.0-py35_200\Library\bin(PS:个人的安装环境不同,路径有差异)。

    在该路径下新建xml文件夹。

     

    三、cmd打开dos命令窗口,进入pos路径下

    输入以下命令,创建pos.txt文件

    dir/b >pos.txt

     

                                   

     

    打开pos.txt,将jpg全部替换为jpg 1 0 0 40 40

    删除最后一行路径pos.txt

    保存

    "1"为图片数量,“0,0”为坐标(Left,Top),“40,40”为图片尺寸(width, height)。

     

    同理,进入neg文件夹,输入以下命令生成neg.txt

    dir/b >neg.txt

     

     

    打开neg.txt,将图片名前面加入路径:

    neg/

    删除最后一行路径neg.txt

     

    四、生成pos.vec

    dos窗口进入路径D:\Anaconda\pkgs\opencv-3.3.0-py35_200\Library\bin,及pos、neg、xml文件夹所在的路径,输入下列命令生成pos.vec文件。

     

    opencv_createsamples.exe -info pos\pos.txt -vec pos.vec -bg neg\neg.txt -num 50 -w 40 -h 40

     

     

     

     

     

    -bg 作为背景

    -num 正样本数量

    -w 正样本宽度

    -h 正样本高度

    生成成功后出现如下界面:

     

    五、开始训练

    接下来输入以下命令,开始进行训练

     

    opencv_traincascade.exe -data xml -vec pos.vec -bg neg\neg.txt -numPos 50 -numNeg 100 -numStages 20 -featureType HAAR -w 40 -h 40

     

     

     

     

     

    -data 后面跟文件夹名

    -vec vec文件

    -bg 作为背景的文件

    -numPos 正样本数量

    -numNeg 负样本数量

    -numStages 级数

    -featureType 特征类型,可以跟HAAR、LBP、HOG

    接下来就是等待训练结果的过程。

    训练完成后会在xml文件夹中出现一个***.xml文件,这就是我们需要的东西。检验过程类似人脸检测(官方教程中可以找到),只是将haarcascade_frontalface_default.xml换成了我们自己训练的***.xml文件。

    在上面这些过程中可能会遇到各种问题,各个论坛的大神都给出了解答,这里就不献丑了。

    补:

    昨天又将样本扩大进行了训练,识别正确率有了明显提升。不过训练过程中也遇到了更多细节问题,比如因为minhirateh(最小正确测试率)和maxfalsealarm(最大错误接受率)设置得不恰当,导致训练提前结束,还有根据HAAR特征、LBP特征、HOG特征各自的特性,似乎HOG更适合做此类检测。下面给出一个链接,可以参考:

    参考链接

     

     

    展开全文
  • 基于Tensorflow实现CNN物体识别系统 摘要 随着计算机的不断发展,人工智能、机器学习的热潮不断上涨。智能化是这个时代不断追求的目标。图像识别就是人工智能的产物,这项技术在很大的程度上给人们带来了很多便利,...

    基于Tensorflow实现CNN物体识别系统

    目录

    1.获取数据集
    2.数据预处理
    3.建立模型
    4.GUI界面

    一、获取数据集

    该项目所使用的数据集通过爬虫从百度中获取数据

    import requests
    import os
    import urllib.parse
    import json
    import jsonpath
    
    header = {
        'User-Agent': 'Mozilla/5.0(Macintosh;Inter Mac OS X 10_13_3) AppleWebkit/537.36 (KHTML,like Gecko)'
                      'Chrom/65.0.3325.162 Safari/537.36'
    }
    
    # https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=%E5%8F%AF%E7%88%B1%E5%A4%B4%E5%83%8F&cl=2&word=%E5%8F%AF%E7%88%B1%E5%A4%B4%E5%83%8F&pn=30&rn=30
    #https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=%E7%8C%AB&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&word=%E7%8C%AB&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn=30&rn=30&gsm=1e&1581575909562=
    # url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={}&word={}&pn={}&rn=30'
    url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&hd=&latest=&copyright=&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn={}&rn=30'
    # queryWord字段可自行更改,想搜什么写什么
    queryWord = '自行车'
    queryWords = urllib.parse.quote(queryWord)
    word = queryWords
    # print(queryWords)
    num = 1
    for pn in range(0, 2000, 30):
        try:
            urls = url.format(queryWords, word, pn)
            response = requests.get(urls, headers=header).text
            html = json.loads(response)
            photos = jsonpath.jsonpath(html, '$..thumbURL')
    
        except:
            pass
    
    
        # print(html)
        # photos = jsonpath.jsonpath(html,'$..thumbURL')
        # print(photos)
        def mkdir(path):
    
            folder = os.path.exists(path)
    
            if not folder:  # 判断是否存在文件夹如果不存在则创建为文件夹
                os.mkdir(path)  # mkdir 创建文件时如果路径不存在会创建这个路径
                print
                "---  new folder...  ---"
                print
                "---  OK  ---"
    
            else:
                print
                "---  There is this folder!  ---"
    
    
        path = 'img/%s' % queryWord  # 自行更改存储地
        mkdir(path)
        if type(photos) is not bool:
            for i in photos:
                try:
                    a = requests.get(i, headers=header)
                    with open('{}/{}.jpg'.format(path, num), 'wb')as f:
                        print("正在下载第%s张图片" % num)
                        f.write(a.content)
                        num += 1
                except:
                    pass
        else:
            pn += 1
    
    
    

    二、数据预处理

    自己爬取的图片有很多图片并不是该分类的东西所以剔除对训练有影响的数据。
    提出后的数据,图片的规格不同所以统一规格

    from PIL import Image
    import os
    def process_image_channels(image_path):
    #将4通道,A通道的统一成三通道的图像;
    #  process the 4 channels .png
        print("正在转换图片通道数。。。。。。。")
        for img_name in os.listdir(image_path):
            img_path = image_path + "/" + img_name
            # 获取该图片全称
            image = Image.open(img_path)              # 打开特定一张图片
            image = image.resize((64, 64))            # 设置需要转换的图片大小
            if image.mode == 'RGBA':
                r, g, b, a = image.split()
                image = Image.merge("RGB", (r, g, b))
                os.remove(img_path)
                # 用新生成的3通道的图片代替原来的;
                image.save(img_path)
                print("这是个四通道的,处理完了!")
            #  process the 1 channel image
            elif image.mode != 'RGB':
                image = image.convert("RGBA")
                r, g, b, a = image.split()
                image = Image.merge("RGB", (r, g, b))
                os.remove(img_path)
                image.save(img_path)
                print("这是个A通道的,处理完了!")
        print("-----------通道数变换完毕-----------")
    
    def image_reshape(image_path, size):
        i = 1
        print("正在统一图片尺寸。。。。。。。")
        for img_name in os.listdir(image_path):
            img_path = image_path + "/" + img_name    # 获取该图片全称
            image = Image.open(img_path)              # 打开特定一张图片
            image = image.resize(size)            # 设置需要转换的图片大小
            os.remove(img_path)
            image.save(img_path)
            print("-----------尺寸统一完毕-----------",i)
            i += 1
    
    image_path = 'img/飞机'
    process_image_channels(image_path)
    image_reshape(image_path, (100, 100))
    

    后续还得将图片转化为神经网络能够识别的数据

    import numpy as np
    import os
    import matplotlib.pyplot as plt
    
    train_path = "img/train/"  # 图片存储位置
    test_path = "img/test/"  # 图片存储位置
    
    # 获取数据
    train_x_path = []
    train_y_data = []
    
    test_x_path = []
    test_y_data = []
    
    
    def img_data(path, x, y):
        # 读取图片路径以及生成标签数据
        for item in os.listdir(path):
            file_path = path+item
            x.append(file_path)
            if "T" in item:
                y.append([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])
            elif "r" in item:
                y.append([0, 1, 0, 0, 0, 0, 0, 0, 0, 0])
            elif "w" in item:
                y.append([0, 0, 1, 0, 0, 0, 0, 0, 0, 0])
            elif "m" in item:
                y.append([0, 0, 0, 1, 0, 0, 0, 0, 0, 0])
            elif "d" in item:
                y.append([0, 0, 0, 0, 1, 0, 0, 0, 0, 0])
            elif "cat" in item:
                y.append([0, 0, 0, 0, 0, 1, 0, 0, 0, 0])
            elif "s" in item:
                y.append([0, 0, 0, 0, 0, 0, 1, 0, 0, 0])
            elif "watermelon" in item:
                y.append([0, 0, 0, 0, 0, 0, 0, 1, 0, 0])
            elif "C" in item:
                y.append([0, 0, 0, 0, 0, 0, 0, 0, 1, 0])
            else:
                y.append([0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
    
        # 转化为矩阵
        x_path = np.array(x)
        y_data = np.array(y)
    
        # 乱序原始数据
        np.random.seed(100)
        order = np.random.permutation(len(y_data))
        x_path = x_path[order]
        y_data = y_data[order]
    
        # 归一化图片
        def readimg(file_path):
            img = plt.imread(file_path)
            img = img/255
            return img
    
        # 加载图片数据
        x_data = []
        for path in x_path:
            img = readimg(path)
            x_data.append(img)
    
        return x_data, y_data
    
    train_x_data, train_y_data = img_data(train_path, train_x_path, train_y_data)
    
    test_x_data, test_y_data = img_data(test_path, test_x_path, test_y_data)
    np.savez("data/train_image_data.npz", train_image_list=train_x_data, train_image_label=train_y_data)
    np.savez("data/test_image_data.npz", test_image_list=test_x_data, test_image_label=test_y_data)
    print("图片信息存储完成")
    

    三、建立模型

    import tensorflow as tf
    import numpy as np
    import os
    os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
    
    tf.set_random_seed(23450)
    
    
    # 获取数据
    train_data = np.load("data/train_image_data.npz")
    test_data = np.load("data/test_image_data.npz")
    # 获取训练集
    train_image_list = train_data['train_image_list']
    train_image_label = train_data['train_image_label']
    # 获取测试集
    test_image_list = test_data['test_image_list']
    test_image_label = test_data['test_image_label']
    
    # 定义train_next_bach 函数
    g_b = 0
    
    def train_next_batch(size):
        global g_b
        x = train_image_list[g_b:g_b+size]
        y = train_image_label[g_b:g_b+size]
        g_b += size
        return x, y
    
    
    # 定义test_next_bach 函数
    g_b = 0
    def test_next_batch(size):
        global g_b
        x = test_image_list[g_b:g_b+size]
        y = test_image_label[g_b:g_b+size]
        g_b += size
        return x, y
    
    
    # 定义权重函数
    def init_weight(shape):
        return tf.Variable(tf.truncated_normal(shape, stddev=0.01))
    
    # 定义偏置函数
    def init_bit(shape):
        return tf.Variable(tf.constant(0.1, shape=shape))
    
    # 定义卷积操作
    def conv2d(x,w):
        return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding="SAME")
    
    #定义池化操作
    def max_pool(x):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
    
    
    # 用来计算权重和偏置的均值和方差
    def variable_summaries(var):
        # 统计参数的均值,并记录
        with tf.name_scope("summaries"):
            mean = tf.reduce_mean(var)
            tf.summary.scalar("mean", mean)
        # 计算参数的标准差
        with tf.name_scope("stddev"):
            stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
            tf.summary.scalar("stddev", stddev)
        # 统计参数的最大最小值
        tf.summary.scalar("max", tf.reduce_max(var))
        tf.summary.scalar("min", tf.reduce_min(var))
        # 用直方图统计参数的分布
        tf.summary.histogram("histogram", var)
    
    
    if __name__ == "__main__":
        with tf.name_scope("input"):
            # 定义占位符
            x = tf.placeholder(tf.float32, [None, 100, 100, 3], name="input")
            y = tf.placeholder(tf.float32, [None, 10])
    
        with tf.name_scope("conv1"):
            with tf.name_scope("weithts"):
                w1 = init_weight([5, 5, 3, 32])
                variable_summaries(w1)
    
            with tf.name_scope("bias"):
                b1 = init_bit([32])
                variable_summaries(b1)
    
            with tf.name_scope("relu_output"):
                conv_1 = conv2d(x, w1) + b1
                h_conv1 = tf.nn.relu(conv_1)
                # 100*100*32
            with tf.name_scope("max_pool"):
                h_pool1 = max_pool(h_conv1)
                # 50*50*32
        with tf.name_scope("conv2"):
            with tf.name_scope("weights"):
                w2 = init_weight([5, 5, 32, 64])
                variable_summaries(w2)
            with tf.name_scope("bias"):
                b2 = init_bit([64])
                variable_summaries(b2)
            with tf.name_scope("relu_output"):
                conv_2 = conv2d(h_pool1, w2) + b2
                h_conv2 = tf.nn.relu(conv_2)
                # 50*50*64
            with tf.name_scope("max_pool"):
                h_pool2 = max_pool(h_conv2)
                # 25*25*64
        with tf.name_scope("conv3"):
            with tf.name_scope("weights"):
                w3 = init_weight([5, 5, 64, 128])
                variable_summaries(w3)
            with tf.name_scope("bias"):
                b3 = init_bit([128])
                variable_summaries(b3)
            with tf.name_scope("relu_output"):
                conv_3 = conv2d(h_pool2, w3) + b3
                h_conv3 = tf.nn.relu(conv_3)
                # 25*25*128
            with tf.name_scope("max_pool"):
                h_pool3 = max_pool(h_conv3)
                # 13*13*128
        with tf.name_scope("conv4"):
            with tf.name_scope("weights"):
                w4 = init_weight([5, 5, 128, 256])
                variable_summaries(w4)
            with tf.name_scope("bias"):
                b4 = init_bit([256])
                variable_summaries(b4)
            with tf.name_scope("relu_output"):
                conv_4 = conv2d(h_pool3, w4) + b4
                h_conv4 = tf.nn.relu(conv_4)
                # 13*13*256
            with tf.name_scope("max_pool"):
                h_pool4 = max_pool(h_conv4)
                # 7*7*256
    
        with tf.name_scope("reverse_conv1") as scope:
            # 第四层
            reverse_weight7 = init_weight([5, 5, 128, 256])
            reverse_conv7 = tf.nn.conv2d_transpose(conv_4, reverse_weight7, [50, 13, 13, 128], strides=[1, 1, 1, 1],
                                                   padding="SAME")
            reverse_weight8 = init_weight([5, 5, 64, 128])
            reverse_conv8 = tf.nn.conv2d_transpose(reverse_conv7, reverse_weight8, [50, 25, 25, 64], strides=[1, 2, 2, 1],
                                                   padding="SAME")
            reverse_weight9 = init_weight([5, 5, 32, 64])
            reverse_conv9 = tf.nn.conv2d_transpose(reverse_conv8, reverse_weight9, [50, 50, 50, 32], strides=[1, 2, 2, 1],
                                                   padding="SAME")
            reverse_weight10 = init_weight([5, 5, 1, 32])
            reverse_conv10 = tf.nn.conv2d_transpose(reverse_conv9, reverse_weight10, [50, 100, 100, 1], strides=[1, 2, 2, 1],
                                                   padding="SAME")
            # 第三层
            reverse_weight1 = init_weight([5, 5, 64, 128])
            reverse_conv1 = tf.nn.conv2d_transpose(conv_3, reverse_weight1, [50, 25, 25, 64], strides=[1, 1, 1, 1],
                                                   padding="SAME")
            reverse_weight2 = init_weight([5, 5, 32, 64])
            reverse_conv2 = tf.nn.conv2d_transpose(reverse_conv1, reverse_weight2, [50, 50, 50, 32], strides=[1, 2, 2, 1],
                                                   padding="SAME")
            reverse_weight3 = init_weight([5, 5, 1, 32])
            reverse_conv3 = tf.nn.conv2d_transpose(reverse_conv2, reverse_weight3, [50, 100, 100, 1], strides=[1, 2, 2, 1],
                                                   padding="SAME")
    
            # 第二层
            reverse_weight4 = init_weight([5,5,32,64])
            reverse_conv4 = tf.nn.conv2d_transpose(conv_2, reverse_weight4, [50,50,50,32], strides=[1, 1, 1, 1],
                                                   padding="SAME")
            reverse_weight5 = init_weight([5, 5, 1, 32])
            reverse_conv5 = tf.nn.conv2d_transpose(reverse_conv4, reverse_weight5,[50, 100, 100,1],strides=[1, 2, 2, 1],
                                                   padding="SAME")
    
            # 第一层
            reverse_weight6 = init_weight([5, 5, 1, 32])
            reverse_conv6 = tf.nn.conv2d_transpose(conv_1, reverse_weight6,[50, 100, 100,1],strides=[1, 1, 1, 1],
                                                   padding="SAME")
        tf.summary.image("reverse_conv4", reverse_conv10, 10)
        tf.summary.image("reverse_conv3", reverse_conv3, 10)
        tf.summary.image("reverse_conv2", reverse_conv5, 10)
        tf.summary.image("reverse_conv1", reverse_conv6, 10)
    
        with tf.name_scope("fc1"):
            with tf.name_scope("weights"):
                w5 = init_weight([7 * 7 * 256, 1024])
                variable_summaries(w5)
            with tf.name_scope("bias"):
                b5 = init_bit([1024])
                variable_summaries(b5)
            with tf.name_scope("relu_output"):
                h_pool3_flat = tf.reshape(h_pool4, [-1, 7*7*256])
                h_fc1 = tf.nn.relu(tf.matmul(h_pool3_flat, w5) + b5)
            with tf.name_scope("dropout"):
                keep_prob = tf.placeholder("float", name="keep_prob")
                h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
        with tf.name_scope("fc2"):
            with tf.name_scope("weights"):
                w6 = init_weight([1024, 512])
                variable_summaries(w6)
            with tf.name_scope("bias"):
                b6 = init_bit([512])
                variable_summaries(b6)
            with tf.name_scope("relu_output"):
                y1 = tf.nn.relu(tf.matmul(h_fc1_drop, w6) + b6)
        with tf.name_scope("fc3"):
            with tf.name_scope("weights"):
                w7 = init_weight([512, 256])
                variable_summaries(w7)
            with tf.name_scope("bias"):
                b7 = init_bit([256])
                variable_summaries(b7)
            with tf.name_scope("relu_output"):
                y2 = tf.nn.relu(tf.matmul(y1, w7) + b7)
        with tf.name_scope("fc4"):
            with tf.name_scope("weights"):
                w8 = init_weight([256, 10])
                variable_summaries(w8)
            with tf.name_scope("bias"):
                b8 = init_bit([10])
                variable_summaries(b8)
            with tf.name_scope("output"):
                y_con = tf.nn.softmax(tf.matmul(y2, w8) + b8, name="output")
        with tf.name_scope("loss"):
            loss_function = tf.reduce_mean(-tf.reduce_sum(y * tf.log(tf.clip_by_value(y_con,1e-10,1.0))))
        tf.summary.scalar("loss", loss_function)
        with tf.name_scope("train"):
            train = tf.train.GradientDescentOptimizer(0.001).minimize(loss_function)
        with tf.name_scope("accuracy"):
            with tf.name_scope("correction_prediction"):
                correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_con, 1))
            with tf.name_scope("accuracy"):
                accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
                tf.summary.scalar("accurzcy", accuracy)
    
        with tf.Session() as sess:
            merged = tf.summary.merge_all()
            train_writer = tf.summary.FileWriter("logs/log1/train", sess.graph)
            test_writer = tf.summary.FileWriter("logs/log1/test")
            batch_size = 50
            tf.global_variables_initializer().run()
            train_batch = train_next_batch(batch_size)
            test_batch = test_next_batch(batch_size)
            for i in range(2001):
                sess.run(train, feed_dict={x: train_batch[0], y: train_batch[1], keep_prob: 1})
    
                if (i%100 == 0):
                    summary = sess.run(merged, feed_dict={x: train_batch[0], y: train_batch[1], keep_prob: 1})
                    train_writer.add_summary(summary, i)
    
                    summary = sess.run(merged, feed_dict={x: test_batch[0], y: test_batch[1], keep_prob: 1})
                    test_writer.add_summary(summary, i)
    
                    train_accuracy = sess.run(accuracy, feed_dict={x:train_batch[0], y: train_batch[1], keep_prob: 1})
                    print("after %d steps the trainnig accuracy is %g" % (i, train_accuracy))
    
                    test_accuracy = sess.run(accuracy, feed_dict={x: test_batch[0], y: test_batch[1], keep_prob: 1})
                    print("after %d steps the testnig accuracy is %g" % (i, test_accuracy))
                    print("")
    
    

    四、GUI界面

    import tkinter as tk
    from tkinter.filedialog import askopenfilename
    from PIL import Image, ImageTk
    import tensorflow as tf
    import numpy as np
    # 创建画布需要的库
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    # 导入绘图模块
    from matplotlib.figure import Figure
    import matplotlib.pyplot as plt
    
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    
    window = tk.Tk()
    window.title('img recognition system')
    window.geometry('700x500')
    
    ca1 = tk.Canvas(window, height=500, width=700)
    img_file = tk.PhotoImage(file='bg.gif')
    img = ca1.create_image(0, 0, anchor='nw', image=img_file)
    
    num_list = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    
    
    def recognition(file):
        global num_list
        sess = tf.Session()
        new_saver = tf.train.import_meta_graph('Model/saved_cnn.ckpt.meta')
        new_saver.restore(sess, 'Model/saved_cnn.ckpt')
        tf.get_default_graph().as_graph_def()
        a = sess.graph.get_tensor_by_name("input:0")
        y = sess.graph.get_tensor_by_name("output:0")
        b = sess.graph.get_tensor_by_name(("keep_prob:0"))
    
        image = Image.open(file)  # 打开特定一张图片
        image = image.resize((100, 100))  # 设置需要转换的图片大小
        image.save(file)
        img1 = plt.imread(file)
        img = img1 / 255
        img = np.array([img])
    
        result = sess.run(y, feed_dict={a: img, b: 0.5})
        i = 0
        for i in range(10):
            num_list[i] = result[0][i]
        print(num_list)
        fig = Figure(figsize=(2.95, 3), dpi=100)
        # 利用子图画图
    
        axc = fig.add_subplot(111)
        name_list = ['T恤', '兔子', '手表', '摩托车', '狗', '猫', '草莓', '西瓜', '轿车', '飞机']
    
        axc.barh(range(10), num_list, tick_label=name_list)
        for j in range(10):
            axc.text(+0.3, j - 0.3, num_list[j], ha='center', va='bottom', fontsize=11)
    
        # axc.bar(range(5),[0.1,0.2,0.3,0.1,0.3])
    
        # 创建画布控件
    
        canvas = FigureCanvasTkAgg(fig, master=window)  # A tk.DrawingArea.
    
        canvas.draw()
    
        # 显示画布控件
    
        canvas.get_tk_widget().place(x=385, y=55)
        # print(result[0])
    
        if sess.run(tf.argmax(result, 1)) == 0:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是一件T恤", "有{:.3f}%的概率是一件T恤".format(result[0][0] * 100))
            print("这有 {:.3f}%".format(result[0][0] * 100), "的概率是一件T恤")
            return "这有", result[0][0], "的概率是一件T恤"
        if sess.run(tf.argmax(result, 1)) == 1:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是一只兔子", "有{:.3f}%的概率是一只兔子".format(result[0][1] * 100))
            print("这有 {:.3f}%".format(result[0][1] * 100), "的概率是一只兔子")
            return "这有", result[0][0], "的概率是一只兔子"
        if sess.run(tf.argmax(result, 1)) == 2:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是一只手表", "有{:.3f}%的概率是一只手表".format(result[0][2] * 100))
            print("这有 {:.3f}%".format(result[0][2] * 100), "的概率是一只手表")
            return "这有", result[0][0], "的概率是一只手表"
        if sess.run(tf.argmax(result, 1)) == 3:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是一辆摩托车", "有{:.3f}%的概率是一辆摩托车".format(result[0][3] * 100))
            print("这有 {:.3f}%".format(result[0][3] * 100), "的概率是一辆摩托车")
            return "这有", result[0][3], "的概率是一辆摩托车"
        if sess.run(tf.argmax(result, 1)) == 4:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是一只狗", "有{:.3f}%的概率是一只狗".format(result[0][4] * 100))
            print("这有 {:.3f}%".format(result[0][4] * 100), "的概率是一只狗")
            return "这有", result[0][4], "的概率是一只狗"
        if sess.run(tf.argmax(result, 1)) == 5:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是一只猫", "有{:.3f}%的概率是一只猫".format(result[0][5] * 100))
            print("这有 {:.3f}%".format(result[0][5] * 100), "的概率是一只猫")
            return "这有", result[0][5], "的概率是一只猫"
        if sess.run(tf.argmax(result, 1)) == 6:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是草莓", "有{:.3f}%的概率是草莓".format(result[0][6] * 100))
            print("这有 {:.3f}%".format(result[0][6] * 100), "的概率是草莓")
            return "这有", result[0][6], "的概率是草莓"
        if sess.run(tf.argmax(result, 1)) == 7:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是西瓜", "有{:.3f}%的概率是西瓜".format(result[0][7] * 100))
            print("这有 {:.3f}%".format(result[0][7] * 100), "的概率是西瓜")
            return "这有", result[0][7], "的概率是西瓜"
        if sess.run(tf.argmax(result, 1)) == 8:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是轿车", "有{:.3f}%的概率是轿车".format(result[0][8] * 100))
            print("这有 {:.3f}%".format(result[0][8] * 100), "的概率是轿车")
            return "这有", result[0][8], "的概率是轿车"
    
        else:
            re.delete(0, tk.END)
            re.insert(tk.END, "这个最可能是一只猫", "有{:.3f}%的概率是飞机".format(result[0][9] * 100))
            print("这有 {:.3f}%".format(result[0][9] * 100), "的概率是飞机")
            return "这有", result[0][9], "的概率是飞机"
    
    
    files = None
    
    
    def selectPath():
        global files
        path_ = askopenfilename(title='选择文件')
        path.set(path_)
        files = path_
        return files
    
    
    def show_img(file):
        img = Image.open(file)
        img = img.resize((344, 394))
        photo = ImageTk.PhotoImage(img)
        img = tk.Label(window, image=photo)
        img.image = photo
        img.place(x=3, y=53)
        return file
    
    
    path = tk.StringVar()
    tk.Label(window, text='识别的图片', bg='yellow', width=13).place(x=19, y=10)
    tk.Entry(window, textvariable=path).place(x=120, y=14)
    tk.Button(window, text='选择文件', command=lambda: show_img(selectPath())).place(x=280, y=10)
    # tk.Text(window,width = 49, height = 30).place(x = 0,y = 50)
    ca = tk.Canvas(window, height=400, width=350, bg="white")
    rect = ca.create_rectangle(2, 2, 351, 401)
    ca.place(x=0, y=50)
    tk.Button(window, text='识别图片', command=lambda: recognition(show_img(files)), width=49).place(x=0, y=460)
    ca1.place(x=0, y=0)
    
    tk.Label(window, text='识别结果', bg='yellow', width=13).place(x=500, y=10)
    
    ca = tk.Canvas(window, height=400, width=300)
    fig = Figure(figsize=(2.95, 3), dpi=100)
    # 利用子图画图
    
    axc = fig.add_subplot(111)
    name_list = ['T恤', '兔子', '手表', '摩托车', '狗', '猫', '草莓', '西瓜', '轿车', '飞机']
    
    axc.barh(range(10), num_list, tick_label=name_list)
    # axc.bar(range(5),[0.1,0.2,0.3,0.1,0.3])
    
    # 创建画布控件
    
    canvas = FigureCanvasTkAgg(fig, master=window)  # A tk.DrawingArea.
    
    canvas.draw()
    
    # 显示画布控件
    
    canvas.get_tk_widget().place(x=385, y=55)
    
    re = tk.Listbox(window, font=('微软雅黑'), width=24, height=3)
    re.place(x=386, y=358)
    
    rect = ca.create_rectangle(2, 2, 300, 400)
    ca.place(x=380, y=50)
    button1 = tk.Button(window, text='退出', command=window.quit, width=42).place(x=380, y=460)
    
    window.mainloop()
    
    

    全部代码:github代码.

    展开全文
  • MATLAB运行代码 可实现对四种动物图像的分类识别 提取特征进行分类识别
  • 传统的图像识别一般都是识别花、鸟、汽车等不同类别物体,而细粒度图像识别则是要识别同一类物体下的不同子类。举个例子,识别一张图片是猫、狗、汽车还是飞机就是传统的图像识别,而识别一张图片是贵宾犬、边境牧羊...

    1 简介

    • 传统的图像识别一般都是识别花、鸟、汽车等不同类别物体,而细粒度图像识别则是要识别同一类物体下的不同子类。举个例子,识别一张图片是猫、狗、汽车还是飞机就是传统的图像识别,而识别一张图片是贵宾犬、边境牧羊犬、吉娃娃还是斗牛犬,则是细粒度图像识别。不同的犬类相似性一般都很高,比如下面的哈士奇和阿拉斯加雪橇犬,如果事先不知道它们有差别的部位,很难正确识别。现在图像识别大都使用卷积神经网络CNN,卷积层会针对整个图像(不论是背景还是物体)提取特征,而细粒度图像识别重点在于物体的一些关键部分,如此一来CNN提取的有很多特征向量都是没用的。

    这里写图片描述

    • 前人已经提出了很多先检测物体部位后识别的方法。本文提出了Mask-CNN模型(M-CNN),它在训练时仅需要part annotations和image-level标签这两个信息。其中part annotations分成两个集合:头部和躯干,如此part localization就成了一个三类分割问题。完整的网络可见下图,M-CNN是一个四线模型(four-stream),四个输入分别为完整图像、检测到的头部、检测到的躯干和检测到的完整物体,每条线程通过卷积最后都得到了deep descriptors(应该是常说的特征图),进而得到1024-d向量,将四个向量拼接在一起,通过l2l2正则化、全连接层和softmax,最后得到类别。

    这里写图片描述

    这里写图片描述

    • 文章做出了三大贡献: 1、在细粒度图像识别方面,M-CNN是首个端到端的,将深度卷积描述符运用到物体检测的模型;2、M-CNN的参数最少(40.96M),向量维度最小(8192-d),CUB200-2011上准确率最高(85.4%)。如果通过SVD压缩特征向量至4096-d,准确率还能提高到85.5%;3、part localization方面同样比其他细粒度识别方法的高,尤其是其他方法还需要额外的边界框(bounding boxes)头部定 位准确率要比state-of-the-art高10%。

    2 相关工作

    • 过去几年,细粒度识别方法可以分成三类。第一类单纯地增加网络深度;第二类试图消除物体姿势、相机位置等影响,在更加统一的环境下进行分类;第三类注重物体部分的细节,因为现实中不同子类的区别也正是在一些独特的细节方面。
    • part-based细粒度识别方法也有许多区别。例如有的方法在训练时既用到了bounding boxes又用到了part annotations。有的方法在测试阶段也使用了bounding boxes以确保准确率。有的方法不使用任何额外信息,只用图像级别的标签来训练(弱监督)。还有一些方法基于分割而非基于bounding box。

    3.1 Learning Object and Part Masks

    • 首先,整个M-CNN的设计基于全卷积网络(FCN),也就是说,前面的掩膜和特征提取只用到了卷积层。作者不仅用全卷积网络(FCN)定位细粒度图像中的目标和parts,还将预测的分割部分视为目标和parts的掩膜。
    • 在数据集CUB200-2011中,每个鸟类细粒度图像都有许多part annotations,比如左腿、右腿、喉、喙、眼睛、肚子、前额等等,它们都以key points的形式标注(见图2的第一张)。本论文将这些key points分成头、躯干两大类,简单地连接这些点来生成头和躯干两个Mask,剩下的都是背景。学习Mask的网络结构如下所示:

    这里写图片描述

    • 以下是部分图像学习到的Mask。红色的称作head mask,蓝色的称作torse mask,这两个合并在一起就是一个完整的物体,称作object mask。学习这三个mask就是标题说的Learning Object and Part Masks(不得不说一下,当时我愣是没看懂这标题的意思)。需要注意的是,虽然基于key points生成的ground-truth不是特别准确,但是FCN模型能够返回更加准确的Mask。

    这里写图片描述

    3.2 M-CNN训练

    • 经过了3.1的FCN,我们已经得到了head mask、torse mask和object mask三个Mask。接下来,前面提到的four-stream model就要派上用场了。

      1. 根据上面三个Mask,返回对应的 mallest rectangle bounding box,再加上原图本身,这四张图像就是four-stream model的输入;
      2. (a)->(b)->(c):作者选用VGG-16作为基础模型,四个输入通过五个卷积层、relu层和池化层,最终得到512维的特征向量。如果输入尺寸统一为224*224,那么它们特征向量为7*7*512,其实它也对应着一张图像7*7方格的空间位置;
      3. (c)->(d):对于后三条线程,把Mask用最近邻方法缩放成7*7大小地二值矩阵,并和对应的7*7*512的特征向量比较:如果某一条512-d向量对应位置的Mask值为1(表示有检测到东西),则向量的值保留,如果对应的Mask值为0,则向量的值置零。而第一条线程,也需要通过object mask的过滤;
      4. (d)->(e):每条线程中,对于被Mask选中的那么多条512-d特征向量,用求平均和求最大值两种方法得到两条512-d特征向量,并经过l2l2正则化处理。最后把两个向量拼接起来成为一条1024-d的向量。
      5. (e)->(f):经过上一步,每条线程都有一个1024-d的向量了,将它们拼接起来,送进全连接层 + softmax,得到结果。由于CUB200-2011有200个类别,所以最终向量也是长200。
    • 训练时,所有图像都保持原有的分辨率,并且只取中间384*384的部分(应该是为了统一尺寸+去除部分背景);

    • M-CNN的四个线程都是端到端训练的,而且参数同时学习;
    • 训练M-CNN时,前面的FCN参数保持不变。

    4 实验

    4.1 数据集和封装细节

    • Caltech-UCSD 2011 bird dataset有200种鸟类,其中每类都有30个训练图像,每张图像还有15个标注点,用来标记鸟类的身体部位。
    • 四线程网络中每一条都有一个VGG-16模型,其参数通过在ImageNet分类上预训练得到。
    • 作者还用水平翻转的方法使训练图像翻倍。在测试时将原图和对应的翻转图像的预测求平均,并输出得分最高的那个分类。
    • 直接使用softmax的结果要比使用logistic回归差

    4.2 分类准确度

    4.2.1 Baseline

    为了验证M-CNN的优越性,作者额外设计了两个Baseline方法:

    1. 在4-stream M-CNN中,把卷积网络替换成全连接层。于是(b)到(e)变成一个最后为全连接层的CNN,输出4096-d的向量,拼接起来为16384-d的向量。此方法称作“4-stream FCs”。
    2. 抛弃(d)部分的descriptor selection,把(c)的结果直接求平均和求最大值。此方法称作“4-stream Pooling”。

    三种方法的结果:

    这里写图片描述

    4.2.2 与state-of-the-art对比

    • M-CNN准确率的提升之路:

      1. 一开始,输入的图像是224*224,M-CNN的准确率有83.1%;
      2. 将输入图像变为448*448后,准确率提升到了85.3%;
      3. 提高4-stream M-CNN的输入大小到448*448后,准确率反而有些下降;
      4. 如果从relu5_2层来提取deep descriptors,并且用Mask过滤一遍,提取出4096-d向量,再和pool5提取出来的拼在一起,变成一个8096-d向量,后续操作相同。该模型称作“4-stream M-CNN+”,它的准确率提升到了85.4%;
      5. 用SVD whitening方法将上述的8096-d向量压缩到4096-d,准确率提升到了85.5%;
      6. 如果CNN部分采用和part-stacked CNN一样的 Alex-Net模型,准确率只有78.0%,但还是比part-stacked CNN高。关键是替换后的参数只有9.74M了。

    为了与其他方法公平比较,所有方法在测试时都不使用part annotations。实验结果如下:

    这里写图片描述

    4.3 Part定位结果

    • 为了评价定位效果,作者采用常用的PCP准则(Percentage of Correctly Localized Parts),该准则指的是与ground-truth相比,IOU大于50%的bounding box的比例;
    • 下表是和其他方法相比的分割结果。作者的方法和Deep LAC相比躯干的准确率更低,主要是因为Deep LAC在测试时有用到Bounding box,而M-CNN没有。

    这里写图片描述

    4.4 object分割结果

    下图是一个分割的结果。第一行是原图像,第二行是ground-truth,第三行是M-CNN的分割结果。M-CNN在分割鸟的细微部分(例如爪子)存在一些困难,但M-CNN的任务不是细致地分割出物体,因此可以不用做微调。

    这里写图片描述

    展开全文
  • 背景细粒度图像识别图像分类中的一个颇具挑战性的任务,它的目标是在一个大类中的众多子类中正确的识别目标。但是相同子类中物体的动作和姿态步态可能相同,不同子类间又有可能有着相同的姿态,这是识别的一大难点...

    背景

    细粒度图像识别是图像分类中的一个颇具挑战性的任务,它的目标是在一个大类中的众多子类中正确的识别目标。但是相同子类中物体的动作和姿态步态可能相同,不同子类间又有可能有着相同的姿态,这是识别的一大难点。
    总的来说,细粒度图像分类是寻找一些细微差别的局部区域,并利用这些局部区域的特性对原图进行分类。当然,如何有效的对前景对象进行检测,并从中发现重要的局部区域信息,成为了细粒度图像分类算法要结局的关键问题。
    对于细粒度图像模型,可以按照其使用的监督信息的强弱,分为“基于强监督信息的分类模型“和“基于弱监督信息的分类模型“两大类

    基于强监督信息的细粒度图像分类模型


    思想:

    为了获得更好的分类精度,除了图像的类别标签外,还使用了物体的标注框(Object Bounding Box)和部位标注点(Part Annotation)等额外的人工标注信息,这些标注信息主要包括物体的前景图片和物体本身重要区别部位的标注。

    ———-

    处理流程举例:

    一、

    利用Selective Search 算法在细粒度图像上产生物体或者物体部位可能出现的候选框(Object Proposal)

    二 、

    按照R-CNN的流程进行物体检测,借助细粒度图像中的Object Bounding Box 和 Part Annotation 可以训练处3 个检测模型:一个对应细粒度物体级别的检测;一个对应物体头部检测,另一个对应物体的身体躯干的检测。

    这里先介绍一下R-CNN的算法流程

    RCNN算法分为4个步骤

      - 一张图像生成1K~2K个候选区域 
      - 对每个候选区域,使用深度网络提取特征 
      - 特征送入每一类的SVM 分类器,判别是否属于该类 
      - 使用回归器精细修正候选框位置 
    

    R-CNN候选区域生成

    使用了Selective Search1方法从一张图像生成约2000-3000个候选区域。基本思路如下:

     - 使用一种过分割手段,将图像分割成小区域 
     - 查看现有小区域,合并可能性最高的两个区域。重复直到整张图像合并成一个区域位置 
     - 输出所有曾经存在过的区域,所谓候选区域
     - 
    

    候选区域生成和后续步骤相对独立,实际可以使用任意算法进行

    R-CNN合并规则

    优先合并以下四种区域:

    • 颜色(颜色直方图)相近的
    • 纹理(梯度直方图)相近的
    • 合并后总面积小的
    • 合并后,总面积在其BBOX中所占比例大的
      合并后的区域特征可以直接由子区域特征计算而来,速度较快。
      特征提取

    R-CNN预处理

    使用深度网络提取特征之前,首先把候选区域归一化成同一尺寸227×227。

    此处有一些细节可做变化:外扩的尺寸大小,形变时是否保持原比例,对框外区域直接截取还是补灰。会轻微影响性能。

    R-CNN预训练

    网络结构

    基本借鉴Hinton 2012年在Image Net上的分类网络2,略作简化3。
    这里写图片描述
    此网络提取的特征为4096维,之后送入一个4096->1000的全连接(fc)层进行分类。
    学习率0.01。

    R-CNN训练数据

    使用ILVCR 2012的全部数据进行训练,输入一张图片,输出1000维的类别标号。

    R-CNN调优训练

    网络结构如下:

    这里写图片描述

    同样使用上述网络,最后一层换成4096->21的全连接网络。
    学习率0.001,每一个batch包含32个正样本(属于20类)和96个背景。

    R-CNN训练数据

    使用PASCAL VOC 2007的训练集,输入一张图片,输出21维的类别标号,表示20类+背景。
    考察一个候选框和当前图像上所有标定框重叠面积最大的一个。如果重叠比例大于0.5,则认为此候选框为此标定的类别;否则认为此候选框为背景。

    R-CNN类别判断

    分类器

    对每一类目标,使用一个线性SVM二类分类器进行判别。输入为深度网络输出的4096维特征,输出是否属于此类。
    由于负样本很多,使用hard negative mining方法。

    正样本

    本类的真值标定框。

    负样本

    考察每一个候选框,如果和本类所有标定框的重叠都小于0.3,认定其为负样本

    R-CNN位置精修

    目标检测问题的衡量标准是重叠面积:许多看似准确的检测结果,往往因为候选框不够准确,重叠面积很小。故需要一个位置精修步骤。
    回归器
    对每一类目标,使用一个线性脊回归器进行精修。正则项λ=10000。
    输入为深度网络pool5层的4096维特征,输出为xy方向的缩放和平移。
    训练样本
    判定为本类的候选框中,和真值重叠面积大于0.6的候选框。

    三、

    以上是R-CNN的进本流程,现在我们接着来讲基于强监督信息的细粒度图像分类模型**处理流程的第三步:

      对三个检测模型得到的检测框加上几何位置的约束,如图:**
      ![这里写图片描述](https://img-blog.csdn.net/20171003151439072?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVhbmcyODE4MTM4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
    

    四、

    接下来将得到的图像块(Image Patch)作为输入,分别训练一个CNN,则该CNN可以学习到针对该物体\部位的特征。

    五、

    最终将三者的全连接层特征级联做为整张细粒度图像的特征表示



    总结:

    这样看来,最终的全连接层的特征表示即包含全局的特征又包含具有更强判别性的局部特征。因此分类精度较理想。但在Part-based R-CNN中,不仅在训练时需要借助Bounding Box和Part Annotation,为了取得满意的分类精度,在测试时甚至还要求测试图像提供Bounding Box。这便限制了Part-based R-CNN在实际场景中的应用。


    细粒度识别关注点在于局部特征,对于一张图片,局部特征是很多的,怎么在众多的局部特征学习到有用的特征,这是一个难题。特别是在图片很少的情况下,很容易学到错误的特征,这样就是过拟合于训练集了还有就是CNN浅层的卷积核空间分辨率高,但是携带语义特征少。怎么将局部特征与语义特征相结合也是一个难点。

    最近在做步态识别相关的工作,按照论文的结构自己跑了一遍代码,却发现屡次都不收敛,于是就想对于CASIA-B这个数据库来说运用细粒度识别的技术难点到底在哪里,最后仔细看了一下网络的结构以及损失函数的变化情况,才发现,对于这种小样本集合来说,尽管选出了候选区域,如果考虑单一角度下的步态能量图,比如90度下的正常行走的,仅仅只有744张,而且要分辨的类别为124类,而每张步态能量图所提取的候选区域有限,而且在这有限的候选区域当中还有一部分对识别并没有太大的帮助,所以总体的训练输出是处于欠拟合的状态,也就是网络不收敛导致实验失败。

    展开全文
  • https://zhuanlan.zhihu.com/p/24524583
  • ImageNet里面的图像(二维,彩色)没有医学图像,包含一些诸如鸟类、猫、狗、直升机等物体的识别,与医学图像(二维或三维,非彩色)相差很大。如果回答是肯定的话,是一件令人非常振奋的事情。
  • 传统的图像识别一般都是识别花、鸟、汽车等不同类别物体,而细粒度图像识别则是要识别同一类物体下的不同子类。举个例子,识别一张图片是猫、狗、汽车还是飞机就是传统的图像识别,而识别一张图片是贵宾犬、边境牧羊...
  • 机器学习原来这么有趣!第三章:图像识别【鸟or飞机】?深度学习与卷积神经网络,机器学习-人工智能
  • 图像的分类和识别一直是计算机视觉的热门研究领域,在医学图像领域,很多方法也都是从计算机视觉领域借鉴过来的,而计算机视觉的许多方法又离不开机器学习和人工智能的基础。 在典型的图像分类和识别问题中,通常有...
  • 向AI转型的程序员都关注了这个号???大数据挖掘DT数据分析 公众号: datadwKeras是一个简约,高度模块化的神经网络库。可以很容易和快速实现原型(通过总模块化,极简主义,和可扩展性)同时支持卷积网络(vision)和...
  • 摘要:关于在图像处理任务(图像分类、超分辨率、图像描述、图像分割等)中添加注意力机制的问题。
  • 各种多尺度物体检测方法   a)原图缩放,将目标缩放至与模板匹配的大小,多个Scale的原图对应不同Scale的Feature,该方法计算多次Scale,每个Scale提取一次Feature。   e)与方法a类似,但和 a全图计算不同,只...
  • 整理 | 专知本文主要介绍了一些经典的用于图像识别的深度学习模型,包括AlexNet、VGGNet、GoogLeNet、ResNet、DenseNet的网络结构及创新之处...
  • 是用于普通物体识别的小型数据集,一共包含 10个类别 的 RGB彩色图片(包含:(飞机、汽车、鸟类、猫、鹿、狗、蛙、马、船、卡车)。图片大小均为 3232像素*,数据集中一共有 50000 张训练图片和 1000 张测试图片。...
  • 导语:面对目前愈加严峻的野生动物生态系统,DeepMind开发了一个新的机器学习系统来为研究人员们提供更高效的解决方案。 智东西11月6日消息,前段时间,DeepMind与生态学家和环保人士合作开发了一个新的机器学习...
1 2 3 4 5 ... 20
收藏数 1,077
精华内容 430