英文:
how to plot line with angle 60 degree
问题
以下是翻译好的部分,不包括代码部分:
"我有一些RGB颜色数据,我想要将其绘制到2D的CIEab颜色通道中,使用a和b的数据。然后,我需要用一个60度的线将我的数据分开。
我已经使用以下代码绘制了a和b:
图像_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]],
...
lab_image = toLAB(image_RGB)
但我不知道如何制作60度的线?
我想要的结果如下图所示。有一条绿色的线,倾斜60度。我想要制作类似于那样的线。"
图片来源:https://www.researchgate.net/publication/325286809_Brief_overview_of_PANTONE_SkinTone_Guide_chart_in_CIELab_color
英文:
i have some data of colors in RGB, i want to plot it to CIEab color channel in 2d which is use the data of a & b. then i need to separate my data with a line which is 60 degree
i have done plot a&b with this code below :
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)
the result what i get is like this
but i don't know how to make line of 60 degree?
the result i want is like the image below. there is a green line with 60 degrees slope. i want to make the line like that
image from : https://www.researchgate.net/publication/325286809_Brief_overview_of_PANTONE_SkinTone_Guide_chart_in_CIELab_color
答案1
得分: 1
x = [1,2,3,4,5]
y = [1,2,3,4,5]
plt.scatter(x, y)
# 蓝色虚线,起点(1,1),终点(5,4)
plt.plot((1,5), (1,4), '--')
# 橙色实线,起点(1,1),终点(5,6)
plt.plot((1,5), (1,6), '-')
plt.plot((x1, x2), (y1, y2), '-') # 使用三角函数来找 x1、x2、y1、y2
或者使用
# 在这种情况下,斜率 = √3 或 1.732
斜率 = (y2 - y1) / (x2 - x1)
plt.axline((0, 0), 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
...
[slope equation](https://www.cuemath.com/slope-formula)
如果你已经有 x1, y1 和 x2, y2,请使用 (y2 - y1) / (x2 - x1)
如果你得到角度 theta,请使用 tan(theta)(不要忘记将度数转换为弧度),或者使用 Google 查找 [tan 60 度](https://www.google.com/search?q=tan+60+degrees&sxsrf=APwXEdf5hDmV4m6jhIag5GpVRY33habmtg%3A1680593008241&ei=cNArZIOJDtKOseMP2dGtkAo&oq=tan+60&gs_lcp=Cgxnd3Mtd2l6LXNlcnAQAxgAMgcIIxCwAxAnMgoIABBHENYEELADMgoIABBHENYEELADMgoIABBHENYEELADMgoIABBHENYEELADMgoIABBHENYEELADMgoIABBHENYEELADMgoIABBHENYEELADMgoIABBHENYEELADMgoIABBHENYEELADMgoIABCKBRCwAxBDSgQIQRgAUABYAGCCCmgBcAF4AIABAIgBAJIBAJgBAMgBCsABAQ&sclient=gws-wiz-serp)
[参考 `pyplot.axline`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.axline.html)
可能重复的问题: https://stackoverflow.com/questions/7941226/how-to-add-line-based-on-slope-and-intercept-in-matplotlib
英文:
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), '-')
and use some trigonometry to find x1 x2 and y1 y2
or use
# in this case slope = √3 or 1.732
slope = y2-y1 / x2-x1
plt.axline((0, 0), slope=slope)
you can add my code after this line
...
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
...
if you got x1,y1 and x2,y2, use y2-y1 / x2-x1
if you get theta, use tan theta (don't forget to convert degree to radian) or use google to find tan 60 degree
Possibly duplicate of: https://stackoverflow.com/questions/7941226/how-to-add-line-based-on-slope-and-intercept-in-matplotlib
答案2
得分: 1
这段代码绘制了两条线:
-
一条60度线(绿色),用于分离数据以最小化错误分类。在这种情况下,有一个红点被错误分类。
-
一条最佳角度线(品红色),完美地分离数据,没有任何错误分类。请注意:尽管该线似乎穿过一个黄点和一个红点,但实际上它只在黄点上方和红点下方经过。找到的最佳角度是52.12度。
此代码还包括一些关于LAB颜色空间的转换和图形绘制的功能。
在代码的最后,lab_image 变量包含了通过 toLAB 函数转换的 LAB 颜色空间图像。
英文:
This code plots two lines:
-
a 60-degree line (green color) that separates data with minimal misclassification. In this case, one red point is misclassified.
-
a best-angle-line (magenta color) that separates data perfectly without any misclassification. Note: Even though the line may seem passing through one yellow point and one red point, actually it is passing just above the yellow point and just below the red point. Maximum best angle is found to be 52.12 degrees.
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论