Определение доминирующих цветов на изображении — очень полезная техника, например для выбора палитры веб-сайта, элементов UI и т.п.
Существуют и online-сервисы, решающие подобную задачу самыми разными методами.
Однако, попробуем решить данную задачку самостоятельно при помощи OpenCV.
Рассмотрим два способа:
— определение отношения пикселя к заданному набору цветов (в пространстве HSV)
— использовании кластеризации методом k-средних (k-means).
Первый способ довольно прост — мы просто конвертируем картинку в цветовое пространство HSV, а затем перебираем все пиксели изображения и по его значениям H, S и V при помощи функции getPixelColorType() определяем к какому цвету из заданого перечисления:
Использовать метод k-средних для определения доминирующих цветов очень просто.
Фактически, решение задачи заключается в определении кластеров цветов на изображении.
Как мы помним, идея метода k-средних состоит в минимизации суммарного квадратичного отклонения точек выборки от центров кластеров.
Сначала, начальные центры кластеров выбираются случайно, затем вычисляется принадлежность каждого элемента к тому или иному центру, а потом на каждой итерации алгоритма выполняется пересчёт центров масс кластеров — и так до тех пор, пока центры не перестают смещаться.
При решении задачи определения доминирующих цветов, каждый пиксель изображения рассматривается как точка в трёхмерном пространстве RGB, в котором вычисляется расстояние до центров масс кластеров.
Для оптимизации работы алгоритма k-means, картинку желательно предварительно уменьшить.
Здравствуйте!
Меня очень заинтересовала Ваша статья об OpenCV — определение доминирующих цветов на изображении/
Хотел уточнить возможно ли запустить указанный Вами код на С++ builder для использования компонента Timage
на данный момент не получается запустить Ваши примеры на С++ builder а нужно именно на С++ builder, буду очень благодарен если подскажете в этом плане что-то я студент начинающий очень нужна Ваша помощь также еще вопрос возможна реализация описанных Вами методов без использования OpenCV. Заранее благодарен за ответ.
Привет вот еще такая проблема при использовании Вашего кода тот что второй метод k средних появляется ошибка при первом заходе в данный цикл
min_rgb_euclidean = 0;
for(k=0; k<cluster_count; k++) {
// new color
clusters[k].new_color.val[0] /= clusters[k].count;
clusters[k].new_color.val[1] /= clusters[k].count;
clusters[k].new_color.val[2] /= clusters[k].count;
float ecli = rgb_euclidean(clusters[k].new_color, clusters[k].color);
if(ecli > min_rgb_euclidean)
min_rgb_euclidean = ecli;
}
ошибка следующая: Exception class $C0000090 with message 'floating point invalid operation at 0x00403cf1' не подскажете в чем может быть причина, также как можно сделать в данном методе чтобы белый фон игнорировался?
Очевидно, нужно проверять, что clusters[k].count не равен нулю.
Чтобы игнорировать белый — можно просто пропускать пиксели с RGB-параметрами около (255, 255, 255).
Здравствуйте, не подскажите пожалуйста, можно ли обрабатывать при помощи open cv более сложные изображения, типа мозаики, а именно выделение на изображении определенных объектов, и довести это до автомата? Сейчас я смог находить на изображении только точные геометрические предметы( круг, треугольник, прямоугольник и линии, но честно говоря получилось не очень)
Я думал может как-то различать по цвету от темного к светлому
Просто я студент 2 курса, и недавно занимаюсь программированием c#, а c++ для меня вообще не знаком) поэтому ваши примеры мне не понятны( заранее спасибо за ответ
Разумеется, можно. OpenCV — это библиотека в которой уже реализованы многие важные функции. Но реализовывать свои собственные или же применять существующие — это полностью ваша задача.
Здоавствуйте. Не подскажите, пожалуйста, как с помощью первого способа вывести в консоль количество пикселей определенного цвета не по всей картинке, а только в заданной области? Просто в коде цвета подсчитываются сразу colorCount[ctype]++; а если задать массив, что array[x][y]= ctype, то выдаются разные ошибки.
Да, это было бы хорошо. Но нельзя всё-таки получить именно массив/матрицу изображения, чтобы легко оперировать с ним, зная, что, например, пиксель [245][108]=0, т.е. имеет чёрный цвет, индекс которого в данной программе — 0? Просто тогда было бы легче рассматривать изображение с доминирующими цветами после его обработки, не прибегая к обращению пикселя в RGB(x,x,x) с тремя параметрами, т.к. во время работы того кода по выделению доминирующих цветов новый цвет пикселя напрямую присваивается в виде индекса, который варьируется от 0 до 7. И ни как нельзя это присвоение как-то перехватить и записать в массив? Дело в том, что для моего алгоритма, который я хочу написать, нужно рассматривать маленькие области, к примеру, 20x20 пикселей для последующей обработки, зная какие доминирующие цвета там есть. И так как новое присвоение цвета уже известно, то почему бы просто это не записать в массив? Просто тогда на картинке в 4к разрешением таких областей придется создавать ну очень много, т.к. изображение будет разбито на эти маленькие сегменты, и каждый в отдельности рассматривать неудобно с помощью ROI.
В любом случае, спасибо за ответ!
Добрый день!
Возможно, не совсем в тему, но можете подсказать, пожалуйста, как создать кнопки в OpenСV и использовать их так, чтобы доминирующие цвета присваивались, например, к 20% процентам полученных цветов и так далее?
Заранее спасибо за помощь!
Здравствуйте. я применила данный код для видео, но что то не так, я передаю fraim как изображение, для первого фрейма работает, но последующие идут с ошибкой и средние RGB значения все уменьшаются с каждым фреймом. В чем может быть ошибка? Спасибо!
Комментарии (17)
RSS свернуть / развернутьМеня очень заинтересовала Ваша статья об OpenCV — определение доминирующих цветов на изображении/
Хотел уточнить возможно ли запустить указанный Вами код на С++ builder для использования компонента Timage
на данный момент не получается запустить Ваши примеры на С++ builder а нужно именно на С++ builder, буду очень благодарен если подскажете в этом плане что-то я студент начинающий очень нужна Ваша помощь также еще вопрос возможна реализация описанных Вами методов без использования OpenCV. Заранее благодарен за ответ.
Jon
Т.к. здесь никаких специфичных функций не используется, то не вижу проблем перенести этот код под любую другую платформу (пример —
noonv
min_rgb_euclidean = 0;
for(k=0; k<cluster_count; k++) {
// new color
clusters[k].new_color.val[0] /= clusters[k].count;
clusters[k].new_color.val[1] /= clusters[k].count;
clusters[k].new_color.val[2] /= clusters[k].count;
float ecli = rgb_euclidean(clusters[k].new_color, clusters[k].color);
if(ecli > min_rgb_euclidean)
min_rgb_euclidean = ecli;
}
ошибка следующая: Exception class $C0000090 with message 'floating point invalid operation at 0x00403cf1' не подскажете в чем может быть причина, также как можно сделать в данном методе чтобы белый фон игнорировался?
Jon
Чтобы игнорировать белый — можно просто пропускать пиксели с RGB-параметрами около (255, 255, 255).
noonv
Я думал может как-то различать по цвету от темного к светлому
Просто я студент 2 курса, и недавно занимаюсь программированием c#, а c++ для меня вообще не знаком) поэтому ваши примеры мне не понятны( заранее спасибо за ответ
Sirtau
noonv
SMore
admin
SMore
В любом случае, спасибо за ответ!
SMore
Возможно, не совсем в тему, но можете подсказать, пожалуйста, как создать кнопки в OpenСV и использовать их так, чтобы доминирующие цвета присваивались, например, к 20% процентам полученных цветов и так далее?
Заранее спасибо за помощь!
TheQuelby
uldibai
admin
uldibai
В чем может быть дело?
TheQuelby
uldibai
uldibai
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.