from os import listdir
from os.path import isfile, join
import argparse
#import cv2
import numpy as np
import sys
import os
import shutil
import random
import math
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import matplotlib.colors
import seaborn as sns
current_palette = list(sns.xkcd_rgb.values())
width_in_cfg_file = 608.
height_in_cfg_file = 608.
#############################
def overlap(x1, len1, x2, len2):
len1_half = len1 / 2
len2_half = len2 / 2
left = max(x1 - len1_half, x2 - len2_half)
right = min(x1 + len1_half, x2 + len2_half)
return right - left
# 计算box a和box b的交集面积
# a和b都是Box类型实例
# 返回值area是box a 和box b的交集面积
def box_intersection(a, b):
w = overlap(a.x, a.w, b.x, b.w)
h = overlap(a.y, a.h, b.y, b.h)
if w < 0 or h < 0:
return 0
area = w * h
return area
# 计算box a 和box b的并集面积
# a和b都是box类型实例
# 返回值u是box a 和box b的并集
def box_union(a, b):
i = box_intersection(a, b)
u = a.w * a.h + b.w * b.h - i
return u
# 计算box a和box b的iou
# a和b都是box类型的实例
# 返回值是boxa 和boxb的iou
def box_iou(a, b):
return box_intersection(a, b) / box_union(a, b)
class Box():
def __init__(self,x,y,w,h):
self.x=x
self.y=y
self.w=w
self.h=h
####################################
# K-means++最重要的创新点:初始质心的选择
####################################
def init_centroids1(annotation_dims, n_anchors):
centroids = [[]]
boxes_num = len(annotation_dims)
centroid_index1 = int(np.random.choice(boxes_num, 1))
centroids[0].append(annotation_dims[centroid_index1])
# print('asd',centroids)
# print(centroids[0][0], centroids[0][1])
for centroid_index in range(0, n_anchors - 1):
sum_distance = 0
distance_thresh = 0
distance_list = [] ###
cur_sum = 0
for box in annotation_dims:
min_distance = 1
# print('???',centroids)
for centroid_i, centroid in enumerate(centroids):
# print('hhgjgh',centroid_i,centroid)
# if len(centroid)==1:
# centroid=[centroid]
# print('ggggg',centroid)
distance = (1 - IOU(box, centroid))
# print('gfasd',distance)
if distance < min_distance:
min_distance = distance
sum_distance += min_distance
distance_list.append(min_distance)
distance_thresh = sum_distance * np.random.random()
for i in range(0, boxes_num):
# print('bbbb',distance_list)
cur_sum += distance_list[i]
if cur_sum > distance_thresh:
centroids.append([annotation_dims[i]])
break
print('初始化', centroids)
return centroids
################################
# 计算IOU,参数centroids为9*2矩阵,x为单位化以后的w和h
def IOU(x,centroids):
similarities = []
k = len(centroids)
# print('xx',x)
# print('gg',centroids)
for centroid in centroids:
c_w,c_h = centroid # 得到当前的单位化后的w h
w,h = x
if c_w>=w and c_h>=h:
similarity = w*h/(c_w*c_h)
elif c_w>=w and c_h<=h:
similarity = w*c_h/(w*h + (c_w-w)*c_h)
elif c_w<=w and c_h>=h:
similarity = c_w*h/(w*h + c_w*(c_h-h))
else: #means both w,h are bigger than c_w and c_h respectively
similarity = (c_w*c_h)/(w*h)
similarities.append(similarity) # will become (k,) shape
return np.array(similarities)
def avg_IOU(X,centroids):
n,d = X.shape
# print('xx', X)
sum = 0.
for i in range(X.shape[0]):
sum+= max(IOU(X[i],centroids))
return sum/n
def write_anchors_to_file(centroids,X,anchor_file):
f = open(anchor_file,'w')
anchors = centroids.copy()
print(anchors.shape)
for i in range(anchors.shape[0]):
anchors[i][0]*=width_in_cfg_file/32.
anchors[i][1]*=height_in_cfg_file/32.
widths = anchors[:,0]
sorted_indices = np.argsort(widths)
print('Anchors = ', anchors[sorted_indices])
for i in sorted_indices[:-1]:
f.write('%0.2f,%0.2f, '%(anchors[i,0],anchors[i,1]))
f.write('%0.2f,%0.2f\n'%(anchors[sorted_indices[-1:],0],anchors[sorted_indices[-1:],1]))
f.write('%f\n'%(avg_IOU(X,centroids)))
print('Avf IoU:%f'%(avg_IOU(X,centroids)))
# 确定初始质心后开始迭代聚类
def kmeans(X,centroids,eps,anchor_file):
N = X.shape[0]
iterations = 0
centroids= np.array(centroids).reshape(9,2)
print(centroids)
k, dim = centroids.shape
prev_assignments = np.ones(N)*(-1)
iter = 0
old_D = np.zeros((N,k))
while True:
D = []
iter+=1
for i in range(N):
d = 1 - IOU(X[i],centroids)
D.append(d)
D = np.array(D) # D.shape = (N,k)
print("iter {}: dists = {}".format(iter,np.sum(np.abs(old_D-D))))
assignments = np.argmin(D,axis=1)
if (assignments == prev_assignments).all() :
print("Centroids = ",centroids)
write_anchors_to_file(centroids,X,anchor_file)
return assignments,centroids
#计算新的簇质心
centroid_sums=np.zeros((k,dim),np.float)
for i in range(N):
centroid_sums[assignments[i]]+=X[i]
for j in range(k):
centroids[j] = centroid_sums[j]/(np.sum(assignments==j))
prev_assignments = assignments.copy()
old_D = D.copy()
def visualization(all_boxes_wh, centers, current_nearest):
# plt.style.use('grayscale')
# 可视化数据
figure, ax = plt.subplots(figsize=(19, 10))
multiple = 2.5
fontsize = 15 * multiple
x_size = 50 * (multiple+1)
font = {'family': 'Times New Roman',
'weight': 'normal',
'size': fontsize,}
# plt.grid(linestyle="--")
# 设置坐标刻度值的大小以及刻度值的字体
plt.tick_params(labelsize=fontsize)
labels = ax.get_xticklabels() + ax.get_yticklabels()
[label.set_fontname('Times New Roman') for label in labels]
# plt.scatter(all_boxes_wh[:, 0], all_boxes_wh[:, 1], c=current_nearest, marker='o', cmap='plasma')
# c=['c1','c2','c3','c4','c5','c6','c7','c8','c9']
# for loc,lab in enumerate(c):
# plt.text(centers[:, 0][loc], centers[:, 1][loc], lab,fontsize=25,bbox=dict(boxstyle='round,pad=0.1', fc='white', ec='k',lw=1 ,alpha=0.7))
for icluster in np.unique(current_nearest):
pick = current_nearest == icluster
c = current_palette[icluster]
# c=icluster
plt.rc('font', size=8)
plt.plot(all_boxes_wh[pick, 0], all_boxes_wh[pick, 1],'p',
color=c,
alpha=0.5, label="cluster = {}, N = {:6.0f}".format(icluster, np.sum(pick)))
plt.text(centers[icluster,0],
centers[icluster,1],
"c{}".format(icluster),
bbox=dict(boxstyle='round,pad=0.1', fc='white', ec='k', lw=1, alpha=0.3),
fontsize=25,color="red")
# print('current_nearest',current_nearest)
# # 制作图例
# dc = {x:current_nearest.count(loc) for loc,x in enumerate(c)}
plt.legend(fontsize=18)
plt.title('Anchor for K-means++, Avg IoU: 69.86%',font)
plt.xlabel('width', font)
plt.ylabel('height', font)
plt.savefig("Anchors-by-Kmeans7.png") # 保存
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('-filelist', default = r'F:\新冠背景下基于YOLOv4的口罩佩戴和社交距离检测和部署\1.口