前言
因为这是我第一次参加建模比赛,当时手忙脚乱做的并不好,所以重新花了一天的时间做了一遍,如有错误欢迎指正。
第一问
第一问讲解
首先读取数据,使用了pandas库,pd.read_table()读取txt文件。
import pandas as pd
import numpy as np
f1 = open("F:/train/建模比赛/华中杯2021/附件2:图像1颜色列表.txt",encoding="utf-8")
data1 = pd.read_table(f1)
f2 = open("F:/train/建模比赛/华中杯2021/附件3:图像2颜色列表.txt",encoding="utf-8")
data2 = pd.read_table(f2)
f1.close()
f2.close()
第二步就来提取f1,f2里的RGB的值。很简单的分割字符串,用split()。写成函数方便后面使用。
#提取RGB的值
def Rgb_list(x):
RGB1_list = []
for i in x:
for j in x[i]:
RGB1_list.append(j)
RGB1_list1 = []
for i in RGB1_list:
p = i.split(",(")[1]
p = p.split(")")[0]
RGB1_list1.append([int(i) for i in p.split(",")])
return RGB1_list1
现在已经有了f1,f2里的RGB数据,简单的计算他们的色差,姑且叫做色差吧,因为是瓷砖,使用起来必然是要给人,即肉眼看的,所以简单的算出他们的在空间直角坐标系下的欧氏距离是不行的。
Lab简介:Lab模式既不依赖光线,也不依赖于颜料,它是CIE组织确定的一个理论上包括了人眼可以看见的所有色彩的色彩模式。Lab模式弥补了RGB和CMYK两种色彩模式的不足。同RGB颜色空间相比,Lab是一种不常用的色彩空间。它是在1931年国际照明委员会(CIE)制定的颜色度量国际标准的基础上建立起来的。1976年,经修改后被正式命名为CIELab。它是一种设备无关的颜色系统,也是一种基于生理特征的颜色系统。这也就意味着,它是用数字化的方法来描述人的视觉感应。Lab颜色空间中的L分量用于表示像素的亮度,取值范围是[0,100],表示从纯黑到纯白;a表示从红色到绿色的范围,取值范围是[127,-128];b表示从黄色到蓝色的范围,取值范围是[127,-128]。如图所示为Lab颜色空间的图示 来源:百度百科 RGB不能直接转变为Lab,这里不细说需要的去看看这篇文章 但是Python有库可以实现直接转换,如果不是图片要转换的话建议用colormath。有需要的可以去看看。 好,接下来就是要写RGB转换成Lab的函数了。
from colormath.color_conversions import convert_color#这个是转换的
from colormath.color_objects import LabColor,sRGBColor
from colormath.color_diff import delta_e_cie1976#这个是计算“色差”的
#RGB转换Lab
def RGB_Lab(x):
p = []
for i in x:
r = sRGBColor(float(i[0]),float(i[1]),float(i[2]),is_upscaled=True)
s = convert_color(r,LabColor)
p.append(s)
return p
然后是计算“色差”的,算出每个要编号的RGB值到现有的22种瓷砖“色差”,“色差”最小的就是属于那一类的。
#计算颜色色差并返回最小索引值+1,这里返回的值就是它们的瓷砖编号了
def Color_difference(c2):
color_index = []
for i in c2:
delt = [delta_e_cie1976(i,j) for j in LabColor_initial]
color_index.append(np.argmin(delt)+1)
return color_index
这时候已经有了编号了,按照题目的要求写入到给定的两个txt文件里。
第一问代码
import pandas as pd
import numpy as np
#图像一添加到result1.txt
f1 = open("F:/train/建模比赛/华中杯2021/附件2:图像1颜色列表.txt",encoding="utf-8")
data1 = pd.read_table(f1)
#图像二添加到result2.txt
f2 = open("F:/train/建模比赛/华中杯2021/附件3:图像2颜色列表.txt",encoding="utf-8")
data2 = pd.read_table(f2)
f1.close()
f2.close()
#提取RGB的值
def Rgb_list(x):
RGB1_list = []
for i in x:
for j in x[i]:
RGB1_list.append(j)
RGB1_list1 = []
for i in RGB1_list:
p = i.split(",(")[1]
p = p.split(")")[0]
RGB1_list1.append([int(i) for i in p.split(",")])
return RGB1_list1
from colormath.color_conversions import convert_color
from colormath.color_objects import LabColor,XYZColor,sRGBColor
from colormath.color_diff import delta_e_cie1976
#RGB转换Lab
def RGB_Lab(x):
p = []
for i in x:
r = sRGBColor(float(i[0]),float(i[1]),float(i[2]),is_upscaled=True)
s = convert_color(r,LabColor)
p.append(s)
return p
#现有颜色瓷砖RGB
color_list=[[0,0,0],[255,255,255],[255,0,0],[246,232,9],[72,176,64],[27,115,186],
[53,118,84],[244,181,208],[255,145,0],[177,125,85],[92,59,144],
[11,222,222],[228,0,130],[255,218,32],[118,238,0],[17,168,226],
[255,110,0],[201,202,202],[255,249,177],[179,226,242],[249,225,214],
[186,149,195]]
LabColor_initial = RGB_Lab(color_list)#现有瓷砖颜色LAb
LabColor1 = RGB_Lab(Rgb_list(data1))#图像一颜色Lab
LabColor2 = RGB_Lab(Rgb_list(data2))#图像二颜色Lab
#计算颜色色差并分类
def Color_difference(c2):
color_index = []
for i in c2:
delt = [delta_e_cie1976(i,j) for j in LabColor_initial]
color_index.append(np.argmin(delt)+1)
return color_index
#图像一的颜色编号
color_category1 = Color_difference(LabColor1)
#图像二的颜色编号
color_category2 = Color_difference(LabColor2)
r1 = open("F:/train/建模比赛/华中杯2021/result1.txt",encoding="utf-8")
r1 = pd.read_csv(r1)
r2 = open("F:/train/建模比赛/华中杯2021/result2.txt",encoding="utf-8")
r2 = pd.read_csv(r2)
r1["瓷砖颜色编号"] = color_category1
r2["瓷砖颜色编号"] = color_category2
r1.to_csv("F:/train/建模比赛/华中杯2021/result1.txt",index=False)
r2.to_csv("F:/train/建模比赛/华中杯2021/result2.txt",index=False)
第二问
第二问讲解
对于题目提到的表现力,颜色越近似就说明表现力越好。既然要新加颜色,就可视化出来看看。可视化出来的数据远比数据本身更容易看出来一些东西。 既然是RGB就画成3D的看一看。
R1 = [i[0] for i in Rgb_list(data1)]
G1 = [i[1] for i in Rgb_list(data1)]
B1 = [i[2] for i in Rgb_list(data1)]
#RGB归一化
def RGB_1(x):
q = []
for i in x:
r = [i[0]/255,i[1]/255,i[2]/255]
q.append(r)
return q
t1 = RGB_1(Rgb_list(data1))
import matplotlib.pyplot as plt #绘图用的模块
from mpl_toolkits.mplot3d import Axes3D #绘制3D坐标的函数
fig = plt.figure(figsize=(10,6))
ax1 = Axes3D(fig)
ax1.scatter(R1,G1,B1,s=300,c=t1,alpha=0.5,marker='o')
fig1 = plt.figure(figsize=(10,6))
ax2 = Axes3D(fig1)
ax2.scatter([i[0] for i in Rgb_list(data2)],[i[1] for i in Rgb_list(data2)],[i[2] for i in Rgb_list(data2)],
c = RGB_1(Rgb_list(data2)),s=300,alpha=0.5,marker='o'
)
fig2 = plt.figure(figsize=(10,6))
ax3 = Axes3D(fig2)
ax3.scatter([i[0] for i in color_list],[i[1] for i in color_list],[i[2] for i in color_list],
c = RGB_1(color_list),s=300,alpha=0.5,marker='o'
)
因为是要在(255255255-22)个RGB值里找出新颜色,所以train应该是255255255个RGB的值,但是我算不动,电脑卡死了,毕竟太大了,从第一个散点图可以看出来,他们是均匀分布的,所以就拿这216个点聚类了。把他们转置,从shape(216,3) 变成(3,216) 用FCM(模糊C-均值算法),详情看这里 写出当你输入要增加几种新颜色时候的函数。
def Fcm_RGB(x):
print("增加"+str(x)+"个的新颜色是")
c1 = x
k = 22
center, u, u0, d, jm, p, fpc = cmeans(train, m=2, c=k+c1, error=0.0005, maxiter=10000)
color_list1 = center.tolist()
color_list1_int = []
for n in color_list1:
color_list2_int = [int(f) for f in n]
color_list1_int.append(color_list2_int)
Rgb_lab = RGB_Lab(color_list1)
color_delt = []
for i in Rgb_lab:
delt1 = np.array([delta_e_cie1976(i,j) for j in LabColor_initial]).sum()
color_delt.append(delt1)
center_list = []
for m in range(1,x+1):
max_index_x = np.argsort(color_delt)[int(m)]
center_list.append(color_list1_int[max_index_x])
return center_list
center是簇中心点,c是簇的个数,其它的不过多介绍,详情看这里
第二问代码
import numpy as np
import matplotlib.pyplot as plt
from skfuzzy.cluster import cmeans
train = np.array(Rgb_list(data1))
train = train.T
def Fcm_RGB(x):
print("增加"+str(x)+"个的新颜色是")
c1 = x
k = 22
center, u, u0, d, jm, p, fpc = cmeans(train, m=2, c=k+c1, error=0.0005, maxiter=10000)
color_list1 = center.tolist()
color_list1_int = []
for n in color_list1:
color_list2_int = [int(f) for f in n]
color_list1_int.append(color_list2_int)
Rgb_lab = RGB_Lab(color_list1)
color_delt = []
for i in Rgb_lab:
delt1 = np.array([delta_e_cie1976(i,j) for j in LabColor_initial]).sum()
color_delt.append(delt1)
center_list = []
for m in range(1,x+1):
max_index_x = np.argsort(color_delt)[int(m)]
center_list.append(color_list1_int[max_index_x])
return center_list
for i in range(1,10.1):
Fcm_RGB(i)
第三问
第三问讲解
和第二问的差不多,只不过是加了一个对表现力的评价分数。对颜色来说,新增的颜色越多,表现力越强,只是既然是在技术革新,一共有22个颜色,那就取个整,最多新增20个颜色,计算看看结果
第三问代码
def Fcm_RGB_result(x):
result = []
for i in range(1,x+1):
p = Fcm_RGB(i)
p1 = RGB_Lab(p)
result1 = []
for k in p1:
delt11 = (np.array([delta_e_cie1976(k,j) for j in LabColor_initial]).sum())/(i+22)
result1.append(delt11)
result.append(np.array(result1).sum()/len(result1))
print("平均色差",str(np.array(result1).sum()/len(result1)))
return np.argmin(result)+1
Fcm_RGB_result(20)
可以看出新增20个颜色时最好,所以再调用第二问的函数计算出新增20个颜色的RGB值。
|