質問編集履歴

2

問題点の追記

2021/02/17 13:45

投稿

dotter
dotter

score1

test CHANGED
File without changes
test CHANGED
@@ -302,6 +302,8 @@
302
302
 
303
303
 
304
304
 
305
+ ユークリッド距離はそもそもの色が若干違う点、CIE94は大まかには合っているものの黒い斑点が多く入ってしまうこと、が問題点です。
306
+
305
307
 
306
308
 
307
309
 

1

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

2021/02/17 13:45

投稿

dotter
dotter

score1

test CHANGED
File without changes
test CHANGED
@@ -102,7 +102,7 @@
102
102
 
103
103
 
104
104
 
105
- for x in range(im.size[1]):
105
+ for x in range(im.size[0]):
106
106
 
107
107
  for z in range(im.size[1]):
108
108
 
@@ -122,16 +122,158 @@
122
122
 
123
123
 
124
124
 
125
-
126
-
127
-
128
-
129
-
130
-
131
125
  ```
132
126
 
133
127
 
134
128
 
129
+ ### 2つ目のソースコード
130
+
131
+
132
+
133
+ ```Python
134
+
135
+ from PIL import Image
136
+
137
+ import numpy as np
138
+
139
+
140
+
141
+
142
+
143
+ im=Image.open("base.jpg") #元画像base.jpg
144
+
145
+ new_im=Image.new('RGB',(im.size[0],im.size[1]), (255,255,255))
146
+
147
+ #元画像と同じ大きさ、背景白の新たな画像
148
+
149
+
150
+
151
+
152
+
153
+ def rgb_to_xyz(rgb): #rgb(255まで)→xyzの割合(0<=return<=1)を出す
154
+
155
+ a=[0.4124,0.3575,0.1805]
156
+
157
+ b=[0.2127,0.7152,0.0722]
158
+
159
+ c=[0.0193,0.1192,0.9504]
160
+
161
+ k=np.array([a,b,c]) #変換用倍率の行列
162
+
163
+
164
+
165
+ t=k.dot(np.array([x/255 for x in rgb]))
166
+
167
+ return (t[0]/0.9504,t[1]/1.0001,t[2]/1.0889)
168
+
169
+ #↑白(255,255,255)で(0.9504,1.0001,1.0889)なので割合として返す
170
+
171
+
172
+
173
+ def F(t): #L*a*b*用の関数
174
+
175
+ if t>216/24389:
176
+
177
+ return 116*pow(t,1/3)-16
178
+
179
+ else:
180
+
181
+ return 24389/27*t
182
+
183
+
184
+
185
+ def Lab(x,y,z): #xyz方式をL*a*b*に変換
186
+
187
+ L=F(y)
188
+
189
+ a=125/29*(F(x)-F(y))
190
+
191
+ b=50/29*(F(y)-F(z))
192
+
193
+ return (L,a,b)
194
+
195
+
196
+
197
+ def cos(a,b):
198
+
199
+ return sum([change(*a)[x]*change(*b)[x] for x in range(2)])
200
+
201
+
202
+
203
+ def C94(L1,a1,b1,L2,a2,b2):
204
+
205
+ k1=0.045
206
+
207
+ k2=0.015
208
+
209
+ kL=1
210
+
211
+ C1=(a1**2+b1**2)**(0.5)
212
+
213
+ C2=(a2**2+b2**2)**(0.5)
214
+
215
+ dC=C1-C2
216
+
217
+ dH=((a1-a2)**2+(b1-b2)**2-dC**2)**(0.5)
218
+
219
+ Sc=1+k1*C1
220
+
221
+ Sh=1+k2*C2
222
+
223
+ return (((L1-L2)/kL)**2+(dC/Sc)**2+(dH/Sh)**2)**(0.5)
224
+
225
+
226
+
227
+
228
+
229
+ def dis(a,b):
230
+
231
+ return sum([C94(*Lab(*rgb_to_xyz(a)),*Lab(*rgb_to_xyz(b))) for x in range(2)])
232
+
233
+
234
+
235
+
236
+
237
+ 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)]
238
+
239
+ #↑用意した色のテンプレート(rgb)
240
+
241
+
242
+
243
+
244
+
245
+
246
+
247
+ f![イメージ説明](9792dc25b0893bd07159f748839d1633.png)n range(im.size[0]):
248
+
249
+ for z in range(im.size[1]):
250
+
251
+ rgb=im.getpixel((x,z))[0:3]
252
+
253
+ m=[dis(rgb,p) for p in palette]
254
+
255
+ #↑現在指定しているピクセルの色(rgb)とパレットそれぞれを比較したリスト作成
256
+
257
+ new_im.putpixel((x,z),palette[m.index(min(m))]) #作成したリストの最小値に値するタプルで色付け
258
+
259
+
260
+
261
+
262
+
263
+ new_im.save("output.jpg",quarity=90)
264
+
265
+
266
+
267
+
268
+
269
+
270
+
271
+ ```
272
+
273
+
274
+
275
+
276
+
135
277
  ### 試したこと
136
278
 
137
279
  近い色を判定するために、まずrgbのタプル同士でのユークリッド距離として近い色を検出させました。
@@ -145,3 +287,25 @@
145
287
  最後に、現在のソースコードのようにrgb→xyz→L*a*b*方式に変換してユークリッド距離での判定をしました。
146
288
 
147
289
  これらのことを行なったのですが似たような色へと変換することが困難でした。
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+ ### 《追記分》
298
+
299
+ ユークリッド距離での判定がイマイチだったので、2つ目のソースコードでは以下のURLの「CIE94」を試しています。
300
+
301
+ https://ja.m.wikipedia.org/wiki/色差
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+ 左(base.jpg)→右(output.jpg)です。それぞれ2つ試しています。
310
+
311
+ ![イメージ説明](33721052ec07fee94bce216931a18e07.png)