how to plot line with angle 60 degree
Question:
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
Answers:
I Hope it help
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: How to add line based on slope and intercept in Matplotlib?
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)
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
I Hope it help
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: How to add line based on slope and intercept in Matplotlib?
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)