У меня есть некоторые данные о цветах в RGB, я хочу отобразить их в цветовом канале CIEab в 2d, который использует данные a и b. тогда мне нужно разделить мои данные линией, которая составляет 60 градусов
я сделал график a & b с этим кодом ниже:
import cv2
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
image_RGB = np.uint8([[[236,195,187],[224,175,167] ,[211,160,147] ,[199,141,130] ,[182,126,113] ,[164,106,95] ,[144, 92, 79] ,[122, 74, 67] ,[101, 61, 53] ,[78, 47, 44]],
[[234, 196, 186],[222, 178, 161],[209, 162, 146],[193, 143, 123],[178, 128, 105],[161, 110, 93] ,[142, 93, 77] ,[121, 77, 61] ,[99, 63, 49] ,[77, 49, 39]],
[[232, 198, 179],[220, 179, 160],[206, 163, 139],[191, 145, 121],[176, 129, 103],[157, 111, 87] ,[139, 96, 71] ,[117, 80, 58] ,[97, 64, 45] ,[77, 49, 37]],
[[229, 200, 177],[218, 182, 155],[204, 163, 136],[188, 147, 119],[170, 129, 99] ,[154, 113, 85] ,[134, 95, 66] ,[117, 81, 55] ,[93, 65, 43] ,[73, 52, 35]],
[[225, 199, 176],[213, 182, 152],[200, 165, 133],[185, 149, 117],[167, 131, 99] ,[149, 114, 82] ,[131, 98, 65] ,[112, 81, 52] ,[92, 66, 41] ,[71, 52, 37]],
[[224,201,176] ,[210,184,151] ,[196,166,130] ,[181,152,112] ,[166,132,94] ,[146,117,77] ,[126, 100, 63] ,[109, 85, 50] ,[89, 68, 41] ,[70, 53, 37]],
[[163,107,72] ,[0,0,0] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255]]
])
def toLAB(image, input_type = 'RGB'):
conversion = cv2.COLOR_BGR2Lab if input_type == 'BGR' else cv2.COLOR_RGB2Lab
image_LAB = cv2.cvtColor(image, conversion)
print("LAB : ", image_LAB)
y,x,z = image_LAB.shape
LAB_flat = np.reshape(image_LAB, [y*x,z])
print("LAB FLAT : ", LAB_flat)
colors = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) if input_type == 'BGR' else image
colors = np.uint8([[[255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0]],
[[255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0]],
[[0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0]],
[[0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0]],
[[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0]],
[[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0]],
[[0,0,255], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0]]
])
print("colors : ", colors)
colors = np.reshape(colors, [y*x,z])/255.
fig = plt.figure()
ax = fig.add_subplot(111, projection='rectilinear')
ax.scatter(x=LAB_flat[:,2], y=LAB_flat[:,1], s=10, c=colors, lw=0)
ax.set_xlabel('A')
ax.set_ylabel('B')
# ax = fig.add_subplot(111, projection='3d')
# ax.scatter(xs=LAB_flat[:,2], ys=LAB_flat[:,1], zs=LAB_flat[:,0], s=10, c=colors, lw=0)
# ax.set_xlabel('A')
# ax.set_ylabel('B')
# ax.set_zlabel('L')
print(colors)
plt.show()
return image_LAB
lab_image = toLAB(image_RGB)
результат, который я получаю, такой
но я не знаю, как сделать линию 60 градусов?
результат, который я хочу, подобен изображению ниже. есть зеленая линия с наклоном 60 градусов. я хочу сделать такую строчку изображение из: https://www.researchgate.net/publication/325286809_Brief_overview_of_PANTONE_SkinTone_Guide_chart_in_CIELab_color
@rajkumar_data я отредактировал его, я хочу сделать линию под углом 60 градусов, и я ожидаю, что она будет разделена на красный и желтый цвета.
хорошо. Красный и желтый хорошо разделены на сюжете. Это означает, что на графике может быть любое количество линий с наклоном 60 градусов. Везде нормально? Или посреди разделяющей области?
И еще одно уточнение: вам нужно нарисовать линию только для этих данных или вам нужен общий подход, чтобы построить линию и для некоторых других данных?
@rajkumar_data на самом деле из исследования, на которое я ссылаюсь по изображению, оно говорит, что данные о цвете кожи, которые отображаются красным и синим, разделены на 60 градусов. и теперь у меня есть другие данные о цвете кожи, которые отличаются от тех данных, которые они используют. затем я хочу проверить, правильно ли разделены мои данные на 60 градусов
мои данные между красным и желтым разделены на графике, но я хочу знать, разделены ли они линией 60 градусов?
Давайте продолжим обсуждение в чате.
x = [1,2,3,4,5]
y = [1,2,3,4,5]
plt.scatter(x,y)
# blue line start at 1,1 end 5,4
plt.plot((1,5), (1,4), '--')
# orange line start at 1,1 end 5,6
plt.plot((1,5), (1,6), '-')
plt.plot((x1,x2), (y1,y2), '-')
и используйте некоторую тригонометрию, чтобы найти x1 x2 и y1 y2
или использовать
# in this case slope = √3 or 1.732
slope = y2-y1 / x2-x1
plt.axline((0, 0), slope=slope)
вы можете добавить мой код после этой строки
...
code before
...
ax.scatter(x=LAB_flat[:,2], y=LAB_flat[:,1], s=10, c=colors, lw=0)
ax.axline((0, 0), slope=1.732)
ax.set_xlabel('A')
...
code after
...
если у вас есть x1,y1 и x2,y2, используйте y2-y1 / x2-x1 если вы получаете тета, используйте тангенс тета (не забудьте преобразовать градусы в радианы) или используйте Google, чтобы найти тангенс 60 градусов
Возможно, дубликат: Как добавить линию на основе наклона и точки пересечения в Matplotlib?
Этот код отображает две строки:
линия под углом 60 градусов (зеленый цвет), которая разделяет данные с минимальной ошибкой классификации. В этом случае неправильно классифицируется одна красная точка.
линия наилучшего угла (пурпурный цвет), которая идеально разделяет данные без какой-либо неправильной классификации. Примечание. Хотя может показаться, что линия проходит через одну желтую и одну красную точки, на самом деле она проходит чуть выше желтой точки и чуть ниже красной точки. Установлено, что максимальный наилучший угол составляет 52,12 градуса.
image_RGB = np.uint8([[[236,195,187],[224,175,167] ,[211,160,147] ,[199,141,130] ,[182,126,113] ,[164,106,95] ,[144, 92, 79] ,[122, 74, 67] ,[101, 61, 53] ,[78, 47, 44]],
[[234, 196, 186],[222, 178, 161],[209, 162, 146],[193, 143, 123],[178, 128, 105],[161, 110, 93] ,[142, 93, 77] ,[121, 77, 61] ,[99, 63, 49] ,[77, 49, 39]],
[[232, 198, 179],[220, 179, 160],[206, 163, 139],[191, 145, 121],[176, 129, 103],[157, 111, 87] ,[139, 96, 71] ,[117, 80, 58] ,[97, 64, 45] ,[77, 49, 37]],
[[229, 200, 177],[218, 182, 155],[204, 163, 136],[188, 147, 119],[170, 129, 99] ,[154, 113, 85] ,[134, 95, 66] ,[117, 81, 55] ,[93, 65, 43] ,[73, 52, 35]],
[[225, 199, 176],[213, 182, 152],[200, 165, 133],[185, 149, 117],[167, 131, 99] ,[149, 114, 82] ,[131, 98, 65] ,[112, 81, 52] ,[92, 66, 41] ,[71, 52, 37]],
[[224,201,176] ,[210,184,151] ,[196,166,130] ,[181,152,112] ,[166,132,94] ,[146,117,77] ,[126, 100, 63] ,[109, 85, 50] ,[89, 68, 41] ,[70, 53, 37]],
[[163,107,72] ,[0,0,0] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255] ,[255,255,255]]
])
def toLAB(image, input_type = 'RGB'):
conversion = cv2.COLOR_BGR2Lab if input_type == 'BGR' else cv2.COLOR_RGB2Lab
image_LAB = cv2.cvtColor(image, conversion)
#print("LAB : ", image_LAB)
y,x,z = image_LAB.shape
LAB_flat = np.reshape(image_LAB, [y*x,z])
# print("LAB FLAT : ", LAB_flat)
colors = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) if input_type == 'BGR' else image
colors = np.uint8([[[255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0]],
[[255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0], [255,0,0]],
[[0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0]],
[[0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0], [0,255,0]],
[[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0]],
[[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0],[255,255,0]],
[[0,0,255], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0]]
])
colors = np.reshape(colors, [y*x,z])/255.
# get indices of red and yellow colors
red_index = np.all(colors==[1.,0.,0.],axis=1)
yellow_index = np.all(colors==[1.,1.,0.],axis=1)
# slice interesting data points, red and yellow
LAB_red = LAB_flat[red_index]
LAB_yellow = LAB_flat[yellow_index]
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='rectilinear')
# plot red points
ax.scatter(x=LAB_red[:,2], y=LAB_red[:,1], s=10, c='red', lw=0)
# plot yellow points
ax.scatter(x=LAB_yellow[:,2], y=LAB_yellow[:,1], s=10, c='yellow', lw=0)
# a formula to get y2 given other params
def get_y(X1,X2,Y1,angle):
return Y1 + (X2-X1) * np.tan(np.radians(angle))
# (141,135) is one the extreme yellow points that stays close to separator line
# (141,135) is obtained from LAB_flat data corresponding to yellow color
# use that as hinge point (x_ref,y_ref) to change angle
# x0 = 100 is randomly selected for plotting purpose and y0 will be calculated for given angle
# x2 = 200 is randomly selected for plotting purpose and y2 will be calculated for given angle
# epsilon, a small value, to keep the line just above the reference yellow hinge point
epsilon = 1e-4
x_ref = 141.
y_ref = 135.+ epsilon
x0 = 100.
x2 = 200.
y0 = get_y(x_ref,x0,y_ref,60)
y2 = get_y(x_ref,x2,y_ref,60)
# plot the 60-degree green line
plt.plot((x0,x2),(y0,y2),c='g',label='60-degree-line')
# find the best separating angle
LAB_red_X = LAB_red[:,2]
LAB_red_Y = LAB_red[:,1]
# reduce angle value starting fron 60
for new_angle in np.arange(60.,40.,-0.01):
# get Y values for all red X values for given angle
y_pred = get_y(x_ref, LAB_red_X, y_ref, new_angle)
# all actual red points should fall above the line
if (LAB_red_Y > y_pred).all():
# we found the best angle
print(new_angle)
# stop iteration
break
# plot a line with the best separating angle
y0 = get_y(x_ref,x0,y_ref,new_angle)
y2 = get_y(x_ref,x2,y_ref,new_angle)
# plot the best-degree line (magenta color)
plt.plot((x0,x2),(y0,y2),'--',c='magenta',label=f'{new_angle:0.2f}-degree-line')
# show image to the interesting region only
plt.xlim([125,160])
plt.ylim([125,160])
ax.set_xlabel('A')
ax.set_ylabel('B')
plt.legend()
plt.show()
return image_LAB
lab_image = toLAB(image_RGB)
я проверил
colors
, у него 5 уникальных значений[[0. 0. 0.] [0. 0. 1.] [0. 1. 0.] [1. 0. 0.] [1. 1. 0.]]
. Какие из них вы хотите отделить? Или где вы хотите провести линию?