Как построить линию с углом 60 градусов

У меня есть некоторые данные о цветах в 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

я проверил colors, у него 5 уникальных значений [[0. 0. 0.] [0. 0. 1.] [0. 1. 0.] [1. 0. 0.] [1. 1. 0.]]. Какие из них вы хотите отделить? Или где вы хотите провести линию?

rajkumar_data 04.04.2023 08:16

@rajkumar_data я отредактировал его, я хочу сделать линию под углом 60 градусов, и я ожидаю, что она будет разделена на красный и желтый цвета.

KEZIA ANGELINE 04.04.2023 08:33

хорошо. Красный и желтый хорошо разделены на сюжете. Это означает, что на графике может быть любое количество линий с наклоном 60 градусов. Везде нормально? Или посреди разделяющей области?

rajkumar_data 04.04.2023 08:51

И еще одно уточнение: вам нужно нарисовать линию только для этих данных или вам нужен общий подход, чтобы построить линию и для некоторых других данных?

rajkumar_data 04.04.2023 08:56

@rajkumar_data на самом деле из исследования, на которое я ссылаюсь по изображению, оно говорит, что данные о цвете кожи, которые отображаются красным и синим, разделены на 60 градусов. и теперь у меня есть другие данные о цвете кожи, которые отличаются от тех данных, которые они используют. затем я хочу проверить, правильно ли разделены мои данные на 60 градусов

KEZIA ANGELINE 04.04.2023 09:04

мои данные между красным и желтым разделены на графике, но я хочу знать, разделены ли они линией 60 градусов?

KEZIA ANGELINE 04.04.2023 09:06

Давайте продолжим обсуждение в чате.

rajkumar_data 04.04.2023 09:22
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
7
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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), '-') 

1

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 градусов

Ссылка на pyplot.axline

Возможно, дубликат: Как добавить линию на основе наклона и точки пересечения в Matplotlib?

Ответ принят как подходящий

Этот код отображает две строки:

  1. линия под углом 60 градусов (зеленый цвет), которая разделяет данные с минимальной ошибкой классификации. В этом случае неправильно классифицируется одна красная точка.

  2. линия наилучшего угла (пурпурный цвет), которая идеально разделяет данные без какой-либо неправильной классификации. Примечание. Хотя может показаться, что линия проходит через одну желтую и одну красную точки, на самом деле она проходит чуть выше желтой точки и чуть ниже красной точки. Установлено, что максимальный наилучший угол составляет 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)

Другие вопросы по теме