zoukankan      html  css  js  c++  java
  • 根据直方图 histogram 进行简单的图像检索

    https://github.com/TouwaErioH/Machine-Learning/tree/master/image%20identification/Histogram%20retrieval

    // 优化为对图片求直方图时分块,或者加权,越靠近中心权重越高 

    在指定的图片数据库内,完成图片检索。图像数据按照文件名的次序大概100幅为1类,以颜色直方图为依据,

    用最邻近方法或其他方法,随机抽取一张图片,利用模板匹配方法在图片库中找出100幅最相似的图片,计算查全率和查准率。

    报告最后部分展示10幅来自不同类别的图片,计算查全率和查准率,展示最接近的5幅图片,并分析结果。

    数据集为

    http://www.vision.caltech.edu/Image_Datasets/Caltech101/Caltech101.html

    参考文献  Histogram-Based Color Image Retrieval

     

    检索方法:

    采用图像的RGB三通道直方图与hsv直方图,利用欧几里得距离(Euclid),卡方比较(Chi-Square,Bhattacharyya distance(巴氏距离)相关性比较(Correlation)计算与模板的距离,找到最相近的图片。

    影响性能的参数:

    rgb的直方图bins,hsv直方图的h,s的bins,以及采用的检索模式。

    利用API:

    cv2. calcHist() 

    cv2.compareHist()

    # -*- coding: utf-8 -*-
    """
    Created on Thu Oct 17 16:01:42 2019
    
    @author: erio
    """
    '''
    从下面10组中随机各选取一幅图片,
    直接根据其颜色直方图在9908(0-9907)幅图片中按照最邻近方法找出最接近的图片(若超出100幅取最接近的100幅。若不足100幅则不足)
    计算查全率查准率
    并展示最接近的五福图片
    0-99 butterfly 100  mark 1,第一组图片,选取19.bmp为模板
    100-199 mountain 100 mark 2 125.bmp
    300-399 mark3   376.bmp
    700-799 luori 100  mark 4  747.bmp
    800-899 花  mark5  850.bmp
    899-998 tree  100 mark 6  940.bmp
    1106-1205 mark 7 1177.bmp
    1593-1692  mark 8 1596.bmp
    8641 8740 mark 9  8655.bmp
    9029 9128 mark 10  9037.bmp
    '''
    
    import cv2
    import numpy as np
    
    
    #转bmp
    def jpg2bmp():
        for i in range(0,9908):
            nam='D:/image/'+str(i)+'.jpg'
            nam1='D:/image/'+str(i)+'.bmp'
            img = cv2.imread(nam, 1)
            cv2.imwrite(nam1, img)
    
    #计算图片的hsv histogram h,s为Hue, Saturation的bins
    def calchsv(start,end,h,s):
        histoh=[]       
        for i in range(start,end+1):
            img = cv2.imread('D:/image/'+str(i)+'.bmp')
            hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
            hist1 = cv2.calcHist([hsv], [0, 1], None, [h, s], [0, 180, 0, 256])
            #cv2.normalize(hist1, hist1, 0, 1, cv2.NORM_MINMAX, -1);    #归一化,后面数据处理的方便,其次是保证程序运行时收敛加快
            histoh.append(hist1)
        return histoh
    
    #计算图片的rgb histogram 。分三个通道RGB计算,每个通道bins为bins,而后拼接为一个histogram.
    def calcRGBhisto(start,end,bins):
        histor=[]                                          #histo storage all histogram nparrays
        for i in range(start,end+1):    
            img = cv2.imread('D:/image/'+str(i)+'.bmp') 
            #histc = cv2.calcHist([img],[0,1,2],None,[bins,bins,bins],[0,255,0,255,0,255])
            hist2 = cv2.calcHist([img],[2],None,[bins],[0,255])  #np.array   RGB三通道 
            hist0 = cv2.calcHist([img],[0],None,[bins],[0,255])  #np.array
            hist1 = cv2.calcHist([img],[1],None,[bins],[0,255])  #np.array
            histf=np.vstack((hist0,hist1,hist2))            #histf,当前图片的直方图的nparray
            #cv2.normalize(histf, histf, 0, 1, cv2.NORM_MINMAX, -1);
            histor.append(histf)
        return histor
    
    
    #imggroup为记录搜索数据的array。形如[[19,0,99],[125,100,199]] 意味第一组图片范围为0-99,选取19号图片为标准搜索
    #hisstart,hisend为要做检索的图片范围,如0,9907
    #method为采用的检索方式。如Euclid为根据图片的直方图的欧几里得距离,越短认为越接近
    def search(imggroup,gsize,hisstart,hisend,method): #method记录判定方式,如Euclid;
        rgbeqpre=0   #平均查全率查准率
        hsveqrecall=0
        rgbeqrecall=0
        hsveqpre=0
        if (method=="Euclid"):
            calmethod="Euclid"
        elif (method=="Correlation"):
            calmethod=cv2.HISTCMP_CORREL
        elif (method=="ChiSquare"):
            calmethod=cv2.HISTCMP_CHISQR
        else:
            calmethod=cv2.HISTCMP_BHATTACHARYYA
        rgbdis=[]                #rgbdis记录认为属于某组的图片的距离该组标准的距离;如dis[1]记录所有认为属于第二组的图片的距离该组标准150.bmp的距离
        hsvdis=[]
        rgbresult=[]    #rgbresult记录结果,为gsize维数组。从0开始index越小越接近标准。如rgbresult[0]数组记录判定为属于1组的图片index。如rgbresult[0][0]=19,即为19.bmp
        hsvresult=[]
        rgbindex=[]     #rgbindex[0]数组记录判定为属于1组的图片index。
        hsvindex=[]
        for i in range(0,gsize+1):
            rgbdis.append([])
            hsvdis.append([])
            rgbindex.append([])
            hsvindex.append([])
        ghisrgb=[] #选取为标准的图片的histogram数组。1维数组。如ghisrgb[0]为19.bmp的histogram
        ghishsv=[]
        gstart=[] #记录每组开始图片index
        gend=[]
        for i in range(0,gsize):         #ghisrgb,ghishsv 记录各个选取图片的histogram gstart记录图片所属组的开始index,
            ghisrgb.append(historgb[imggroup[i][0]]) #如第一组0-99,查找19.bmp,gstart[0]=0,gend[0]=99,ghisrgb[0]=histo[19]
            ghishsv.append(histohsv[imggroup[i][0]])
            gstart.append(imggroup[i][1])
            gend.append(imggroup[i][2])
        for i in range(hisstart,hisend+1):  #在hisstart-hisend的范围内,计算图片距离所选取的每幅图片距离,选择最近的认为属于该组;cnt记录距离各组距离
            tprgbdis=[]
            tphsvdis=[]  #记录当前图片采用rgb和hsvhistogram,距离选取出的图片的距离
            for j in range(0,gsize):       
                if (calmethod=="Euclid"):
                    tempr=historgb[i]-ghisrgb[j]
                    tempr=np.power(tempr,2)
                    tempdis=np.sum(tempr)
                    tprgbdis.append(tempdis)
                    temph=histohsv[i]-ghishsv[j]
                    temph=np.power(temph,2)
                    tempdis=np.sum(temph)
                    tphsvdis.append(tempdis)
                else:
                    match = cv2.compareHist(historgb[i],ghisrgb[j], calmethod)
                    tprgbdis.append(match)
                    match = cv2.compareHist(histohsv[i],ghishsv[j], calmethod)
                    tphsvdis.append(match)
            #np.argsort()用于给数组排序,返回值为从小到大元素index的值.
            #假设一个数组a为[0,1,2,20,67,3],使用numpy.argsort(a),返回值应为[0,1,2,5,3,4]
            if(method=="Correlation"):  #Correlation -1-1,越大越接近
                tpp=np.argsort(tprgbdis)
                final=tpp[gsize-1]                 #img i 与final组correlation最接近1,认为属于final组
                rgbdis[final].append(tprgbdis[final]) #将i.img距离final组标准的距离记录到rgbdis[final]数组,同时其index i记录到rgbindex[final]数组。
                rgbindex[final].append(i)
                
                tpp=np.argsort(tphsvdis)
                final=tpp[0]                 #img i 与final组euclid距离最短,认为属于final组
                hsvdis[final].append(tphsvdis[final]) 
                hsvindex[final].append(i)
            else:   #其余的三种方法越小越接近
                tpp=np.argsort(tprgbdis)
                final=tpp[0]                 #img i 与final组距离最短,认为属于final组
                rgbdis[final].append(tprgbdis[final]) 
                rgbindex[final].append(i)
                
                tpp=np.argsort(tphsvdis)
                final=tpp[0]              
                hsvdis[final].append(tphsvdis[final]) 
                hsvindex[final].append(i)
            
            #gstart[i],第i组起始index。如第0组0-99,gstart[0]=0,gend[0]=99;
            #index[i][result[i][j]] index[i]为认为属于[i]组的图片的index数组.result[i]为认为属于i组的图片的dis升序排序后的索引序列
            #例如 index[0]={0,24,5} 那么result[0][2]=5
        for i in range(0,gsize): 
            rgbcorr=0 #corr 认为属于i组并且确实属于i组
            hsvcorr=0
            if(method=="Correlation"): #越大越好
                #print(type(rgbdis))
                nprd=np.array(rgbdis[i])
                nphd=np.array(hsvdis[i])
                rgbresult.append(np.argsort(-nprd))                 #argsort 得到的result是dis降序排序后的索引序列,数组
                hsvresult.append(np.argsort(-nphd))   #result数组中增加一个数组,如[]-->[[0,1,2]],判定属于第0组的图片index为0,1,2
            else: #越小越好
                rgbresult.append(np.argsort(rgbdis[i]))    
                hsvresult.append(np.argsort(hsvdis[i]))
            
            #print(rgbresult[i].size,hsvresult[i].size)
            if rgbresult[i].size<=100:   #若判定为i组的图片不足100幅
                rgbsize=rgbresult[i].size
            else:                       #若判定为i组的图片超过100幅,取最近的100幅
                rgbsize=100
            if hsvresult[i].size<=100:   #若判定为i组的图片不足100幅
                hsvsize=hsvresult[i].size
            else:                       #若判定为i组的图片超过100幅,取最近的100幅
                hsvsize=100
            for j in range(0,rgbsize):                 #result[i][0]理论上是被search的图片自身,imgnum
                if (gstart[i]<=rgbindex[i][rgbresult[i][j]])&(rgbindex[i][rgbresult[i][j]]<=gend[i]):
                    rgbcorr=rgbcorr+1
            for j in range(0,hsvsize):                 #result[i][0]理论上是被search的图片自身,imgnum
                if (gstart[i]<=hsvindex[i][hsvresult[i][j]])&(hsvindex[i][hsvresult[i][j]]<=gend[i]):
                    hsvcorr=hsvcorr+1
            rgbclose=[]
            hsvclose=[]   #取最接近的5幅图片展示
            for k in range(0,6):
                rgbclose.append(rgbindex[i][rgbresult[i][k]])
                hsvclose.append(hsvindex[i][hsvresult[i][k]])
            rgbpre=rgbcorr/(rgbsize)
            rgbeqpre=rgbeqpre+rgbpre
            rgbrecall=rgbcorr/100
            rgbeqrecall=rgbeqrecall+rgbrecall
            hsvpre=hsvcorr/(hsvsize)
            hsveqpre=hsveqpre+hsvpre
            hsvrecall=hsvcorr/100
            hsveqrecall=hsveqrecall+hsvrecall
            print("imgnumber %d
    "%(imggroup[i][0]))
            print("using rgb histogram %s method 's precision:%.5f ,recall:%.5f
    "%(method,rgbpre,rgbrecall))
            print("using hsv histogram %s method 's precision:%.5f ,recall:%.5f
    "%(method,hsvpre,hsvrecall))
            print("rgb close 5
    ")
            print(rgbclose)
            print("hsv close 5
    ")
            print(hsvclose)
        print("rgbeqpre: %.5f,rgbeqrecall: %.5f,hsveqpre: %.5f,hsveqrecall: %.5f
    "%(rgbeqpre/gsize,rgbeqrecall/gsize,hsveqpre/gsize,hsveqrecall/gsize))
            
    
    if __name__ == '__main__': 
        #jpg2bmp()
        histostart = 0
        histoend = 9907
        histobins=32
        h= 90#180
        s= 256  #256
        historgb = calcRGBhisto(histostart,histoend,histobins)
        histohsv = calchsv(histostart,histoend,h,s)
        print(type(histohsv))
        #每组中选取一幅图片,查找最近的100张,计算查全率查准率。如第一组0-99,查19.bmp
        group=[[19,0,99],[125,100,199],[376,300,399],[747,700,799],[850,800,899],[940,899,998],
                   [1177,1106,1205],[1596,1593,1692],[8655,8641,8740],[9037,9029,9128]]
        #group=[[50,0,99],[137,100,199],[350,300,399]]
        groupsize = 10
        #search(group,groupsize,histostart,histoend,"Euclid")
        #search(group,groupsize,histostart,histoend,"Correlation")
        #search(group,groupsize,histostart,histoend,"ChiSquare")
        search(group,groupsize,histostart,histoend,"Bhattach")
  • 相关阅读:
    01-文件系统
    适配器模式,新老系统兼容
    01-Entity FrameWork如何控制数据的变化
    .Net实战之反射操作篇
    .Net实战之反射相关类之间的人体经络关系
    .Net实战之反射外卖计费
    [转]UINavigationController 返回的方法汇总
    [转]AFNetWorking使用笔记
    vue----子组件引用vux popup mask遮罩在最上层解决办法 z-index问题
    vue系列---vue项目(已安装vuex)中引入jquery
  • 原文地址:https://www.cnblogs.com/lqerio/p/11858763.html
Copyright © 2011-2022 走看看