123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- # import
- # ------------------------------------------------------------------------------------------
- import os
- import matplotlib.pyplot as plt
- import numpy as np
- import multiprocessing as mp
- import easygui
- import imageio
- # miam import
- import miam.image.Image as MIMG
- import miam.image.imageType as MTYPE
- import miam.image.channel as MCH
- import miam.image.ColorSpace as MICS
- import miam.processing.ColorSpaceTransform as MCST
- import miam.processing.TMO_Lightness as TMO_L
- import miam.processing.ContrastControl as PCC
- import miam.histogram.Histogram as MHIST
- import miam.aesthetics.LightnessAesthetics as MLAC
- import miam.aesthetics.Palette as MPAL
- import miam.imageDB.ImageDB
- import miam.imageDB.POGChecker
- import miam.imageDB.HwHDRBuilder
- import miam.html.generator
- import miam.utils
- import miam.pointcloud.PointCloud2D as MPC2D
- import miam.classification.kmeans
- import miam.math.Distance
- import miam.math.Normalize
- import miam.classification.colorPaletteKmeanDisplay
- # ------------------------------------------------------------------------------------------
- # MIAM project 2020
- # ------------------------------------------------------------------------------------------
- # author: remi.cozot@univ-littoral.fr
- # ------------------------------------------------------------------------------------------
- # --------------------------------------------> Cluster
- # --------------------------------------------> Lightness
- def clusterPalette():
- # ------------------------------------------------------------------------------------------
- #
- # ------------------------------------------------------------------------------------------
- # config: configfile
- jsonfile = "../DB/config_POG_DB.json"
- # palettes files
- allPalettes_2colorsNoBlack = "../DB/POG_DB_Lab_kmeans_Palette_2colorsNoBlack.npy"
- allPalettes_3colorsNoBlack = "../DB/POG_DB_Lab_kmeans_Palette_3colorsNoBlack.npy"
- allPalettes_4colorsNoBlack = "../DB/POG_DB_Lab_kmeans_Palette_4colorsNoBlack.npy"
- allPalettes_5colorsNoBlack = "../DB/POG_DB_Lab_kmeans_Palette_5colorsNoBlack.npy"
- optimalNumberOfClusters = 4 #5
- distanceToCentroids_5colorsNoBlack = "../DB/POG_DB_dist_to_centroids_Palette_5colorsNoBlack.npy"
- # ------------------------------------------------------------------------------------------
- print("MIAM[POG Cluster Palette]")
- # ------------------------------------------------------------------------------------------
- # boolean to select what to do
- # ------------------------------------------------------------------------------------------
- displayPalette2 = False
- displayPalette3 = False
- displayPalette5 = False
- clusterPalettes = False
-
- clusterPalettes_ncentroids = False
- displayPaletteClasses = True
- searchOptimalNumberOfClusters = False
- displayBestPaletteClass = True
- distanceToCentroids = False
- distanceToCentroidsAnalysis = False
- bestImagePerClass = True
-
- # ------------------------------------------------------------------------------------------
- # first analysis of palettes
- # ------------------------------------------------------------------------------------------
- if displayPalette2:
- # try to see something with palettes
- print("MIAM[------------------------------------------]")
- print("MIAM[display Palette 2 colors in (L)ab]")
- # load all palette 2 colors no black
- pal2CNB = np.load(allPalettes_2colorsNoBlack)
- print("MIAM[load Palette 2 colors: palette object shape",pal2CNB.shape,"]")
- plt.figure("Palette 2 color in ab")
- for i,p in enumerate(pal2CNB[0:-1]):
- print(i,'/',pal2CNB.shape[0],' ',end='\r')
- # plot palette
- x = p[:,1] # a -> x
- y = p[:,2] # b -> y
- plt.plot(x,y)
-
- plt.show(block=True)
- # ------------------------------------------------------------------------------------------
- if displayPalette3:
- # try to see something with palettes
- print("MIAM[------------------------------------------]")
- print("MIAM[display Palette 3 colors in (L)ab]")
- # load all palette 3 colors no black
- pal3CNB = np.load(allPalettes_3colorsNoBlack)
- print("MIAM[load Palette 3 colors: palette object shape",pal3CNB.shape,"]")
- plt.figure("Palette 3 color in ab")
- for i,p in enumerate(pal3CNB[0:250]):
- print(i,'/',pal3CNB.shape[0],' ',end='\r')
- # plot palette
- x = p[:,1] # a -> x
- x = np.append(x,x[0])
- y = p[:,2] # b -> y
- y = np.append(y,y[0])
- plt.plot(x,y,'o--', linewidth=1, markersize=3)
- plt.plot([-100,100],[0,0],'k-')
- plt.plot([0,0],[-100,100],'k-')
- plt.show(block=True)
- # ------------------------------------------------------------------------------------------
- if displayPalette5:
- # try to see something with palettes
- print("MIAM[------------------------------------------]")
- print("MIAM[display Palette 5 colors in (L)ab]")
- # load all palette 5 colors no black
- pal5CNB = np.load(allPalettes_5colorsNoBlack)
- print("MIAM[load Palette 5 colors: palette object shape",pal5CNB.shape,"]")
- plt.figure("Palette 5 color in ab")
- for i,p in enumerate(pal5CNB[0:-1]):
- print(i,'/',pal5CNB.shape[0],' ',end='\r')
- # plot palette
- x = p[:,1] # a -> x
- y = p[:,2] # b -> y
- pc = MPC2D.PointCloud2D(x,y)
- xx,yy = MPC2D.PointCloud2D.toXYarray(pc.convexHull())
- plt.plot(xx,yy,'o--', linewidth=1, markersize=3)
- plt.plot([-100,100],[0,0],'k-')
- plt.plot([0,0],[-100,100],'k-')
- plt.show(block=True)
- # ------------------------------------------------------------------------------------------
- # second analysis of palettes: k-means of palettes
- # ------------------------------------------------------------------------------------------
- if clusterPalettes:
- # load all palette 5 colors no black
- pal5CNB = np.load(allPalettes_5colorsNoBlack)
- print("MIAM[load Palette (5 colors): palette object shape",pal5CNB.shape,"]")
- print("MIAM[clustering Palette (5 colors) launch !]")
- # __init__(self, distance, normalize):
- km = miam.classification.kmeans.kmeans(miam.math.Distance.Distance(miam.math.Distance.cL2distance),
- miam.math.Normalize.Normalize(miam.math.Normalize.sortNorm))
- # kmeans(self,samples, nbClusters, nbIter, display = None, initRange= ...):
- centroids,assigments,assigmentsIdx = km.kmeans(pal5CNB[0:1000],
- 4, #4
- 100, #100
- display = miam.classification.colorPaletteKmeanDisplay.colorPaletteKmeanDisplay(),
- initRange=[(0,100),(-100,100),(-100,100)],
- multiPro=True)
- print("MIAM[clustering done !]")
- # plot centroids
- plt.figure("Palette (5 color) in ab")
- for p in centroids:
- # plot palette
- x = p[:,1] # a -> x
- y = p[:,2] # b -> y
- pc = MPC2D.PointCloud2D(x,y)
- xx,yy = MPC2D.PointCloud2D.toXYarray(pc.convexHull())
- plt.plot(xx,yy,'o--', linewidth=1, markersize=3)
- plt.plot([-100,100],[0,0],'k-')
- plt.plot([0,0],[-100,100],'k-')
- plt.show(block=True)
- # np.save("../DB/"+"POG_DB"+'_centroids_palette_5colors_4centroids',centroids)
- # np.save("../DB/"+"POG_DB"+'_assigments_palette_5colors_4centroids',assigments)
- # np.save("../DB/"+"POG_DB"+'_assigmentsIdx_palette_5colors_4centroids',assigmentsIdx)
- # print("MIAM[","POG_DB"," clustering save saved !]")
- # test the number of centroids
- # ------------------------------------------------------------------------------------------
- if clusterPalettes_ncentroids:
- # load all palette 5 colors no black
- pal5CNB = np.load(allPalettes_5colorsNoBlack)
- print("MIAM[load Palette 5 colors: palette object shape",pal5CNB.shape,"]")
- print("MIAM[clustering Palette 5 colors launch !]")
- # __init__(self, distance, normalize):
- km = miam.classification.kmeans.kmeans(miam.math.Distance.Distance(miam.math.Distance.cL2distance),
- miam.math.Normalize.Normalize(miam.math.Normalize.sortNorm))
- for nbc in [2,3,4,5,6,7,8,9,10]: #,11,12,13,14,15]:
- print("MIAM[clustering Palette 5 colors:",str(nbc)," centroids launch !]")
- # kmeans
- centroids,assigments,assigmentsIdx = km.kmeans(pal5CNB,
- nbc,
- 500,
- display=miam.classification.colorPaletteKmeanDisplay.colorPaletteKmeanDisplay(),
- initRange=[(0,100),(-100,100),(-100,100)],
- multiPro=True)
- print("MIAM[clustering done !]")
- np.save("../DB/"+"POG_DB"+'_centroids_palette_5colors_'+str(nbc)+'centroids',centroids)
- np.save("../DB/"+"POG_DB"+'_assigments_palette_5colors_'+str(nbc)+'centroids',assigments)
- np.save("../DB/"+"POG_DB"+'_assigmentsIdx_palette_5colors_'+str(nbc)+'centroids',assigmentsIdx)
- print("MIAM[","POG_DB"," clustering save saved !]")
- # ------------------------------------------------------------------------------------------
- # analysis of palettes classes
- # ------------------------------------------------------------------------------------------
- if displayPaletteClasses:
- numberOfClusters = [2,3,4,5,6,7,8,9,10,11,12,13,14,15]
- for numberOfCluster in numberOfClusters:
- print("----------------------------------------------")
- print("numberOfCluster:",numberOfCluster)
- print("----------------------------------------------")
- # load centroids , etc.
- centroids = np.load("../DB/"+"POG_DB"+'_centroids_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigments = np.load("../DB/"+"POG_DB"+'_assigments_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigmentsIdx = np.load("../DB/"+"POG_DB"+'_assigmentsIdx_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- # plot images of palette
- fig, ax = plt.subplots(numberOfCluster,1)
- fig.suptitle("CentroidsImage:"+str(numberOfCluster)+"/ palette 5 colors")
- for i,p in enumerate(centroids):
- # debug
- print("| palette (",i,"): number of image assigned >>", len(assigmentsIdx[i]))
- # create palette object
- pal = MPAL.Palette('Palette_'+str(i),p, MICS.ColorSpace.buildLab())
- # create image of palette
- imgPal = pal.createImageOfPalette()
- imgPal.plot(ax[i],title=False)
-
- plt.show(block=False)
- # plot centroids
- figC = plt.figure()
- figC.suptitle("Centroids:"+str(numberOfCluster)+"/ palette 5 colors")
- for i,p in enumerate(centroids):
- # plot palette
- x = p[:,1] # a -> x
- y = p[:,2] # b -> y
- pc = MPC2D.PointCloud2D(x,y)
- xx,yy = MPC2D.PointCloud2D.toXYarray(pc.convexHull())
- plt.plot(xx,yy,'o--', linewidth=1, markersize=3)
-
- if numberOfCluster != numberOfClusters[-1]:
- plt.show(block=False)
- else:
- plt.show(block=True)
- # ------------------------------------------------------------------------------------------
- if searchOptimalNumberOfClusters:
- # find the optimal number of clusters
- res = []
- numberOfClusters = [2,3,4,5,6,7,8,9,10]
- #distance
- distance = miam.math.Distance.Distance(miam.math.Distance.cL2distance)
- for numberOfCluster in numberOfClusters:
- # DEBUG
- print("--------------------------------------------------------------")
- print(" number of clusters:",numberOfCluster)
- print("--------------------------------------------------------------")
- # load centroids , etc.
- centroids = np.load("../DB/"+"POG_DB"+'_centroids_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigments = np.load("../DB/"+"POG_DB"+'_assigments_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigmentsIdx = np.load("../DB/"+"POG_DB"+'_assigmentsIdx_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- allSumD2 = 0
- for i,centroid in enumerate(centroids):
- # DEBUG
- print("| centroids(",i,"): number of assigments >>", len(assigments[i]))
- print("+-------------------------------------------------------------")
- PaletteCentroid = MPAL.Palette('Palette_'+str(i),centroid, MICS.ColorSpace.buildLab())
- sumD2 = 0
- for j,ass in enumerate(assigments[i]):
- # DEBUUG
- print("| > assigment(",j,")/", len(assigments[i])," ",end='\r')
- PaletteAss = MPAL.Palette('Palette_'+str(i),ass, MICS.ColorSpace.buildLab())
- # compute distance
- D2 = distance.eval(PaletteCentroid.colors,PaletteAss.colors)**2
- sumD2 +=D2 # sum of distance between a centroids and its assigments
- allSumD2 += sumD2 # sum of distance between all centroids and their respectives assigments
- res.append(allSumD2)
- ypps = []
- for i,y in enumerate(res[1:-1]):
- ypp = res[i+1]+res[i-1]-2*res[i]
- print("d2 (sum of squared distance)/d (nb clusters) (",i,"):",ypp)
- ypps.append(ypp)
- plt.figure("sum of squared distance / number of centroids")
- plt.plot(numberOfClusters,res,'b-')
- plt.plot(numberOfClusters[1:-1],ypps,'r')
- plt.show(block=True)
- # ------------------------------------------------------------------------------------------
- if displayBestPaletteClass:
- numberOfCluster = 5
- print("----------------------------------------------")
- print("numberOfCluster:",numberOfCluster)
- print("----------------------------------------------")
- # load centroids , etc.
- centroids = np.load("../DB/"+"POG_DB"+'_centroids_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigments = np.load("../DB/"+"POG_DB"+'_assigments_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigmentsIdx = np.load("../DB/"+"POG_DB"+'_assigmentsIdx_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- colors = ['b', 'g','r','c','m']
- # plot number of assigments per cluster
- figNBA = plt.figure("number of assigments per cluster ['b', 'g','r','c','m']")
- nbAss = []
- for i,p in enumerate(centroids): nbAss.append(len(assigmentsIdx[i]))
- plt.bar(colors,nbAss,color=colors)
- plt.show(block=False)
- # plot images of palette
- fig, ax = plt.subplots(numberOfCluster,2)
- fig.suptitle("Centroids:"+str(numberOfCluster)+"/ palette 5 colors ['b', 'g','r','c','m']")
- for i,p in enumerate(centroids):
- # debug
- print("| palette (",i,"): number of image assigned >>", len(assigmentsIdx[i]))
- # create palette object
- pal = MPAL.Palette('Palette_'+str(i),p, MICS.ColorSpace.buildLab())
- # create image of palette
- imgPal = pal.createImageOfPalette()
- imgPal.plot(ax[i,1],title=False)
- ax[i,0].plot(0,0,'o'+colors[i],markersize=10)
- ax[i,0].axis("off")
-
- plt.show(block=False)
- # plot centroids
- figC = plt.figure()
- figC.suptitle("Centroids:"+str(numberOfCluster)+"/ palette 5 colors")
- for i,p in enumerate(centroids):
- # plot palette
- x = p[:,1] # a -> x
- y = p[:,2] # b -> y
- pc = MPC2D.PointCloud2D(x,y)
- xx,yy = MPC2D.PointCloud2D.toXYarray(pc.convexHull())
- plt.plot(xx,yy,colors[i]+'o--', linewidth=1, markersize=3)
-
- plt.show(block=True)
- # ------------------------------------------------------------------------------------------
- # POG: cluster analysis PART 1: distance to each centroids
- # -----------------------------------------------------------------------------------------
- if distanceToCentroids:
- numberOfCluster = 5
- print("----------------------------------------------")
- print("numberOfCluster:",numberOfCluster)
- print("----------------------------------------------")
- # load centroids , etc.
- centroids = np.load("../DB/"+"POG_DB"+'_centroids_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigments = np.load("../DB/"+"POG_DB"+'_assigments_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigmentsIdx = np.load("../DB/"+"POG_DB"+'_assigmentsIdx_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- # load all palette
- allPalettes = np.load("../DB/POG_DB_Lab_kmeans_Palette_5colorsNoBlack.npy", allow_pickle=True)
- #distance
- distance = miam.math.Distance.Distance(miam.math.Distance.cL2distance)
- # buid palette objects
- pCentroids = []
- for i,cent in enumerate(centroids):
- c = MPAL.Palette('Palette_'+str(i),cent, MICS.ColorSpace.buildLab())
- pCentroids.append(c)
- # distToCentroids
- distToCentroids = []
- # distance to centroids
- for i, palette in enumerate(allPalettes):
- # DEBUG
- print("> palette(",i,")/", allPalettes.shape[0]," ",end='\r')
- # get raw image histogram and build Histogram Object
- p = MPAL.Palette('Palette_'+str(i),palette, MICS.ColorSpace.buildLab())
- distToCent = []
- for j,hc in enumerate(pCentroids):
- d = distance.eval(hc.colors,p.colors)
- distToCent.append(d)
-
- distToCentroids.append(distToCent)
- np.save(distanceToCentroids_5colorsNoBlack,distToCentroids)
- rows = len(distToCentroids)
- cols = len(list(zip(*distToCentroids))) #cols = len(distToCentroids[0])
- print("")
- print("MIAM[distToCentroids.shape(", rows,"x",cols,")]")
- print("MIAM[distToCentroids[0]:", distToCentroids[0],")]")
- print("MIAM[","POG_DB"," distance for each image to each centroids saved !]")
- # ------------------------------------------------------------------------------------------
- if distanceToCentroidsAnalysis:
- numberOfCluster = 5
- print("----------------------------------------------")
- print(" distance to centroids ")
- print("----------------------------------------------")
- print("numberOfCluster:",numberOfCluster)
- print("----------------------------------------------")
- distToCentroids = np.load(distanceToCentroids_5colorsNoBlack, allow_pickle=True)
- # get data
- fig, ax = plt.subplots(1,numberOfCluster)
- fig.suptitle('distance to centroids')
- colors = ['b', 'g','r','c','m','y','k']
- # sort
- for i in range(numberOfCluster):
- idxSorted = np.argsort(distToCentroids[:,i])#[::-1]
- for j in range(numberOfCluster):
- ax[i].plot((distToCentroids[idxSorted[0:1000],j]),colors[j%len(colors)]+'o', markersize=1)
- plt.show(block=True)
- # ------------------------------------------------------------------------------------------
- if bestImagePerClass:
- # config: configfile
- jsonfile = "../DB/config_POG_DB.json"
- # loading POG
- pogDB = miam.imageDB.ImageDB.ImageDB(jsonConfigFile =jsonfile)
- pogDB.check(miam.imageDB.POGChecker.POGChecker(local=True))
- print("MIAM[",pogDB.name,":(csvFileName:: ",pogDB.csvFileName,", imagePATH::",pogDB.imagePATH,")]")
- # number of class
- numberOfCluster = 5
- print("MIAM[ number of Palette Class:",numberOfCluster,"]")
- # load centroids , etc.
- centroids = np.load("../DB/"+"POG_DB"+'_centroids_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigments = np.load("../DB/"+"POG_DB"+'_assigments_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- assigmentsIdx = np.load("../DB/"+"POG_DB"+'_assigmentsIdx_palette_5colors_'+str(numberOfCluster)+'centroids'+'.npy', allow_pickle=True)
- # for each palette/image distance to each cluster
- distToCentroids = np.load(distanceToCentroids_5colorsNoBlack, allow_pickle = True)
- # load all palette
- allPalettes = np.load("../DB/POG_DB_Lab_kmeans_Palette_5colorsNoBlack.npy", allow_pickle=True)
- # for each class
- for i,p in enumerate(centroids):
- # palette of class
- pCentroid = MPAL.Palette('Palette_'+str(i),p, MICS.ColorSpace.buildLab())
- pcCentroid = MPC2D.PointCloud2D(pCentroid.colors[:,1],pCentroid.colors[:,2])
- xxCentroid,yyCentroid = MPC2D.PointCloud2D.toXYarray(pcCentroid.convexHull())
- imgPaletteCentroid = pCentroid.createImageOfPalette()
- # sort image according to class distance
- idxSorted = np.argsort(distToCentroids[:,i])#[::-1]
- # for ten best image of the current class
- for j in range(3):
- # best j-th image
- imagefilename = pogDB.db[idxSorted[j]]
- print("class(",i,"): best", j,">>",imagefilename)
- img = MIMG.Image.read(imagefilename)
- jj = idxSorted[j]
- p = allPalettes[jj]
- pImg = MPAL.Palette('Palette_'+str(i),p, MICS.ColorSpace.buildLab())
- imgPImg = pImg.createImageOfPalette()
- # palette contour
- pcImage = MPC2D.PointCloud2D(pImg.colors[:,1],pImg.colors[:,2])
- xxImage, yyImage = MPC2D.PointCloud2D.toXYarray(pcImage.convexHull())
- # figure and axes
- fig, ax = plt.subplots(2,2) # 1 row x 2 columns
- fig.suptitle('best image('+str(j)+')/class('+str(i)+')')
- ax[0,0].set_title('image')
- img.plot(ax[0,0],title=False)
- imgPImg.plot(ax[1,0],title=False)
- ax[1,0].set_title('palette of image')
- ax[0,1].set_title('palettes (red class/blue image)')
- _range = max([np.amax(np.abs(centroids[:,:,1])),np.amax(np.abs(centroids[:,:,2]))])
- for k, c in enumerate(centroids):
- # plot palette
- x = c[:,1] # a -> x
- y = c[:,2] # b -> y
- pc = MPC2D.PointCloud2D(x,y)
- xx,yy = MPC2D.PointCloud2D.toXYarray(pc.convexHull())
- if k != i: ax[0,1].plot(xx,yy,'m--')
- ax[0,1].plot(xxCentroid,yyCentroid,'ro--')
- ax[0,1].plot(xxImage,yyImage,'bo-')
- ax[0,1].plot([- _range, _range],[0,0],'k')
- ax[0,1].plot([0,0],[-_range,_range],'k')
-
- imgPaletteCentroid.plot(ax[1,1],title=False)
- ax[1,1].set_title("palette of class")
- plt.show(block=True)
|