Comments 9
Результаты сегментации запрещающих (красных) знаков будут лучше, если в HSV добавить дополнительно участок значений цветового тона от, скажем, 340 до 360.
Возможно это и будет работать, но есть вероятность появление шума и выделения не только знаков, но и не нужных объектов. Степень ошибок сегментации будет варьироваться в зависимости от яркости изображения и других факторов.
P.S.: В данном случае подбиралось значение HSV для представленных изображений, что позволило получить более менее нормальный результат.
А где-то можно подробнее почитать про IHSL, кроме вашей собственной статьи издательства рязанского госуниверситета, которая не гуглится?
Ссылка на статью:
Hanbury A., Serra J. Colour Image Analysis in 3D-Polar Coordinates // Lecture Notes in Computer Science. – 2003. – DOI: 10.1007/978-3-540-45243-0_17.
Электронный вариант:
https://www.researchgate.net/publication/221114392_Colour_Image_Analysis_in_3D-Polar_Coordinates
Прикреплю код на C, который использовался для преобразования RGB в IHSL.
uint32_t ZETTA;
uint32_t GAMMA;
typedef enum
{
cn_grayscale = 1,
cn_rgb = 3
} channel;
typedef struct image_mat_structure
{
unsigned char *data;
unsigned int width;
unsigned int height;
channel cn;
} *image_mat;
void rgb_to_ihsl_mask(const image_mat image_src, image_mat image_dst)
{
uint32_t size_mat = image_src->height * image_src->width;
// Объявление переменных
uint8_t H, S, L;
uint8_t R, G, B;
// Угол в цветовом пространстве HSL;
double theta;
double denominator;
double argument;
// Максимально и минимальное значение пикселей в каналах
uint8_t max, min;
for (uint32_t i = 0; i < size_mat; i++)
{
R = (image_src->data)[i * 3];
G = (image_src->data)[i * 3 + 1];
B = (image_src->data)[i * 3 + 2];
denominator = sqrt((double)R*R + (double)G*G + (double)B*B - (double)R*G - (double)R*B - (double)G*B);
argument = ((double)R - (double)G / 2.0 - (double)B / 2.0) / denominator;
if (argument < -1.0) argument = -1.0;
if (argument > 1.0) argument = 1.0;
// Нахождение угла
theta = acos(argument);
// Находждение Hue
if (B <= G)
{
H = (uint8_t) theta * (180.0 / M_PI_MY);
}
else
{
H = (uint8_t) (360 - theta * (180.0 / M_PI_MY));
}
if (argument < -1.0) argument = -1.0;
if (argument > 1.0) argument = 1.0;
// Нахождение максимального значения пикселя из 3-х каналов
max = (R > G ? (R > B ? R : B) : (G > B ? G : B));
min = (R < G ? (R < B ? R : B) : (G < B ? G : B));
// Нахождение Saturation
S = max - min;
// Нахождение Luminance
L = (uint8_t)(0.212 * R + 0.715 * G + 0.072 * B);
if (max == G || ((abs(R - G) < ZETTA) && (abs(B - G) < GAMMA)))
{
// (image_dst->data)[i * 3] = 0;
// (image_dst->data)[i * 3 + 1] = 0;
// (image_dst->data)[i * 3 + 2] = 0;
(image_dst->data)[i] = 0;
}
else
{
if ((61 <= H && H <= 150 && S >= 20 && L >= 0) || // Зеленые
(150 <= H && H <= 250 && S >= 20 && L >= 10) || // Синие
(30 <= H && H <= 60 && S >= 90 && S <= 255 && L >= 80)) // Желтые
{
//Сохраняем значения в HSL
// (image_dst->data)[i * 3] = H;
// (image_dst->data)[i * 3 + 1] = S;
// (image_dst->data)[i * 3 + 2] = L;
(image_dst->data)[i] = 255;
}
// Сохраняем значения в RGB
// (image_dst->data)[i] = 255;
}
}
}
"Дорожникам" давно пора держать актуальными открытые карты дорожной ситуации/обстановки/режимов.
Способы цветовой сегментации в задачах детектирования дорожных знаков