Tôi không phải là chuyên gia về màu sắc, nhưng tôi đã tìm kiếm RGB/HEX/HSV để chuyển đổi tên màu đơn giản thành python. Sau khi thực hiện một số nghiên cứu, tôi tin rằng tôi đã thực hiện một giải pháp ghê gớm.Theo IfLoop trong this post:
Nếu bạn kết thúc bằng khoảng cách Descartes để so sánh màu, bạn thường phải dịch đầu vào thành không gian màu theo cảm nhận, chẳng hạn như Lab hoặc Yuv. Cả RGB và HSV đều không tuyến tính, và vì vậy khoảng cách Descartes không liên quan nhiều đến hai màu tương tự. - IfLoop ngày 27 tháng 7 '11 tại 21:15
Do đó, mã của Jochen Ritzel sẽ không luôn trả về màu sắc phù hợp, như Graf đã chỉ ra. Điều này là do cả RGB và HSV đều là các không gian màu tuyến tính. Chúng ta cần sử dụng một không gian màu cảm nhận tuyến tính như YUV.
Vì vậy, những gì tôi đã làm là tôi lấy mã của Jochen Ritzel và thay thế mã rgb thành mã hsv bằng mã rgb thành yuv dựa trên this post.
colors = dict((
((196, 2, 51), "RED"),
((255, 165, 0), "ORANGE"),
((255, 205, 0), "YELLOW"),
((0, 128, 0), "GREEN"),
((0, 0, 255), "BLUE"),
((127, 0, 255), "VIOLET"),
((0, 0, 0), "BLACK"),
((255, 255, 255), "WHITE"),))
def rgb_to_ycc(r, g, b): #http://bit.ly/1blFUsF
y = .299*r + .587*g + .114*b
cb = 128 -.168736*r -.331364*g + .5*b
cr = 128 +.5*r - .418688*g - .081312*b
return y, cb, cr
def to_ycc(color):
""" converts color tuples to floats and then to yuv """
return rgb_to_ycc(*[x/255.0 for x in color])
def color_dist(c1, c2):
""" returns the squared euklidian distance between two color vectors in yuv space """
return sum((a-b)**2 for a,b in zip(to_ycc(c1),to_ycc(c2)))
def min_color_diff(color_to_match, colors):
""" returns the `(distance, color_name)` with the minimal distance to `colors`"""
return min(# overal best is the best match to any color:
(color_dist(color_to_match, test), colors[test]) # (distance to `test` color, color name)
for test in colors)
if __name__ == "__main__":
r = input('r: ')
g = input('g: ')
b = input('b: ')
color_to_match = (r, g, b)
print min_color_diff(color_to_match, colors)
input('Press enter to exit.')
Bây giờ chúng ta dường như kết thúc với màu sắc phù hợp hầu hết thời gian:
>>> color_to_match = (2, 2, 0) #Graf's test
>>> print min_color_diff(color_to_match, colors)
>>>
(6.408043991348166e-05, 'BLACK')
Thêm ví dụ:
>>> color_to_match = (131, 26, 26)
>>> print min_color_diff(color_to_match, colors)
>>>
(0.027661314571288835, 'RED')
>>> color_to_match = (69, 203, 136)
>>> print min_color_diff(color_to_match, colors)
>>>
(0.11505647737959283, 'GREEN')
Cho đến nay có vẻ như phiên bản của tôi dường như được làm việc gần như hoàn toàn, nhưng xin lưu ý: Có khả năng nếu màu rgb quá sáng hoặc quá tối, có thể bạn sẽ được trả về 'TRẮNG' hoặc 'ĐEN'. Để giải quyết điều này, bạn sẽ cần phải thêm màu sáng hơn và tối hơn cho từ điển màu của bạn. Ngoài ra, thêm nhiều màu sắc như 'BROWN' và 'GRAY' (v.v.) vào từ điển màu cũng sẽ trả lại kết quả tốt hơn.
2,2,0 là không kỹ thuật đen, giống như không phải là 240.240.240 về mặt kỹ thuật màu xám. – Chris
Đó là một xấp xỉ. Đó là mục tiêu của kịch bản này rõ ràng. –