teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

2

問題点の追記

2021/02/17 13:45

投稿

dotter
dotter

スコア1

title CHANGED
File without changes
body CHANGED
@@ -150,6 +150,7 @@
150
150
  ユークリッド距離での判定がイマイチだったので、2つ目のソースコードでは以下のURLの「CIE94」を試しています。
151
151
  https://ja.m.wikipedia.org/wiki/色差
152
152
 
153
+ ユークリッド距離はそもそもの色が若干違う点、CIE94は大まかには合っているものの黒い斑点が多く入ってしまうこと、が問題点です。
153
154
 
154
155
 
155
156
  左(base.jpg)→右(output.jpg)です。それぞれ2つ試しています。

1

2つめのソースコード追加(CIE94)、参考画像追加

2021/02/17 13:45

投稿

dotter
dotter

スコア1

title CHANGED
File without changes
body CHANGED
@@ -50,7 +50,7 @@
50
50
  #↑用意した色のテンプレート(rgb)
51
51
 
52
52
 
53
- for x in range(im.size[1]):
53
+ for x in range(im.size[0]):
54
54
  for z in range(im.size[1]):
55
55
  rgb=im.getpixel((x,z))[0:3]
56
56
  m=[dis(rgb,p) for p in palette]
@@ -60,15 +60,97 @@
60
60
 
61
61
  new_im.save("output.jpg",quarity=90)
62
62
 
63
+ ```
63
64
 
65
+ ### 2つ目のソースコード
64
66
 
67
+ ```Python
68
+ from PIL import Image
69
+ import numpy as np
65
70
 
71
+
72
+ im=Image.open("base.jpg") #元画像base.jpg
73
+ new_im=Image.new('RGB',(im.size[0],im.size[1]), (255,255,255))
74
+ #元画像と同じ大きさ、背景白の新たな画像
75
+
76
+
77
+ def rgb_to_xyz(rgb): #rgb(255まで)→xyzの割合(0<=return<=1)を出す
78
+ a=[0.4124,0.3575,0.1805]
79
+ b=[0.2127,0.7152,0.0722]
80
+ c=[0.0193,0.1192,0.9504]
81
+ k=np.array([a,b,c]) #変換用倍率の行列
82
+
83
+ t=k.dot(np.array([x/255 for x in rgb]))
84
+ return (t[0]/0.9504,t[1]/1.0001,t[2]/1.0889)
85
+ #↑白(255,255,255)で(0.9504,1.0001,1.0889)なので割合として返す
86
+
87
+ def F(t): #L*a*b*用の関数
88
+ if t>216/24389:
89
+ return 116*pow(t,1/3)-16
90
+ else:
91
+ return 24389/27*t
92
+
93
+ def Lab(x,y,z): #xyz方式をL*a*b*に変換
94
+ L=F(y)
95
+ a=125/29*(F(x)-F(y))
96
+ b=50/29*(F(y)-F(z))
97
+ return (L,a,b)
98
+
99
+ def cos(a,b):
100
+ return sum([change(*a)[x]*change(*b)[x] for x in range(2)])
101
+
102
+ def C94(L1,a1,b1,L2,a2,b2):
103
+ k1=0.045
104
+ k2=0.015
105
+ kL=1
106
+ C1=(a1**2+b1**2)**(0.5)
107
+ C2=(a2**2+b2**2)**(0.5)
108
+ dC=C1-C2
109
+ dH=((a1-a2)**2+(b1-b2)**2-dC**2)**(0.5)
110
+ Sc=1+k1*C1
111
+ Sh=1+k2*C2
112
+ return (((L1-L2)/kL)**2+(dC/Sc)**2+(dH/Sh)**2)**(0.5)
113
+
114
+
115
+ def dis(a,b):
116
+ return sum([C94(*Lab(*rgb_to_xyz(a)),*Lab(*rgb_to_xyz(b))) for x in range(2)])
117
+
118
+
119
+ palette=[(60, 60, 60), (120, 120, 120), (130, 130, 130), (90, 90, 90), (255, 255, 255), (130, 135, 145), (70, 175, 170), (190, 100, 130), (140, 60, 170), (100, 50, 40), (130, 130, 200), (40, 60, 40), (60, 100, 120), (80, 120, 170), (120, 40, 40), (90, 0, 0), (200, 0, 0), (170, 100, 40), (200, 185, 130), (120, 85, 60), (100, 70, 40), (80, 60, 40), (100, 140, 45), (115, 150, 70), (0, 170, 45), (100, 160, 20), (180, 180, 40), (200, 190, 60), (80, 100, 40), (0, 100, 0), (50, 70, 30), (40, 65, 40)]
120
+ #↑用意した色のテンプレート(rgb)
121
+
122
+
123
+
124
+ f![イメージ説明](9792dc25b0893bd07159f748839d1633.png)n range(im.size[0]):
125
+ for z in range(im.size[1]):
126
+ rgb=im.getpixel((x,z))[0:3]
127
+ m=[dis(rgb,p) for p in palette]
128
+ #↑現在指定しているピクセルの色(rgb)とパレットそれぞれを比較したリスト作成
129
+ new_im.putpixel((x,z),palette[m.index(min(m))]) #作成したリストの最小値に値するタプルで色付け
130
+
131
+
132
+ new_im.save("output.jpg",quarity=90)
133
+
134
+
135
+
66
136
  ```
67
137
 
138
+
68
139
  ### 試したこと
69
140
  近い色を判定するために、まずrgbのタプル同士でのユークリッド距離として近い色を検出させました。
70
141
  次に、rgb配色のままだとあまり同系色を検出できないことを理解して、rgbをhsv形式に変換して同様にユークリッド距離で判定しました。
71
142
  ユークリッド距離での計算が思うようにいかなかったため、コサイン類似度(空間ベクトル内での2ベクトルの内積の最小値)によって判定しました。
72
143
  あまりいい結果が得られないため、次にrgbをxyz方式にして同様にユークリッド距離、コサイン類似度で計算しました。
73
144
  最後に、現在のソースコードのようにrgb→xyz→L*a*b*方式に変換してユークリッド距離での判定をしました。
74
- これらのことを行なったのですが似たような色へと変換することが困難でした。
145
+ これらのことを行なったのですが似たような色へと変換することが困難でした。
146
+
147
+
148
+
149
+ ### 《追記分》
150
+ ユークリッド距離での判定がイマイチだったので、2つ目のソースコードでは以下のURLの「CIE94」を試しています。
151
+ https://ja.m.wikipedia.org/wiki/色差
152
+
153
+
154
+
155
+ 左(base.jpg)→右(output.jpg)です。それぞれ2つ試しています。
156
+ ![イメージ説明](33721052ec07fee94bce216931a18e07.png)