CraftDuino v2.0
  • - это CraftDuino - наш вариант полностью Arduino-совместимой платы.
  • CraftDuino - настоящий конструктор, для очень быстрого прототипирования и реализации идей.
  • Любая возможность автоматизировать что-то с лёгкостью реализуется с CraftDuino!
Просто добавьте CraftDuino!

OpenCV - определение доминирующих цветов на изображении

Оглавление

Определение доминирующих цветов на изображении — очень полезная техника, например для выбора палитры веб-сайта, элементов UI и т.п.

Существуют и online-сервисы, решающие подобную задачу самыми разными методами.
Однако, попробуем решить данную задачку самостоятельно при помощи OpenCV.

Рассмотрим два способа:
— определение отношения пикселя к заданному набору цветов (в пространстве HSV)
— использовании кластеризации методом k-средних (k-means).

Первый способ довольно прост — мы просто конвертируем картинку в цветовое пространство HSV, а затем перебираем все пиксели изображения и по его значениям H, S и V при помощи функции getPixelColorType() определяем к какому цвету из заданого перечисления:
enum {cBLACK=0, cWHITE, cGREY, cRED, cORANGE, cYELLOW, cGREEN, cAQUA, cBLUE, cPURPLE, NUM_COLOR_TYPES};

относится цвет.
При этом, число таких пикселей подсчитывается. Сохраняются и RGB-составляющие, для последующего усреднения.

Исходный код:
//
// определение преобладающих цветов на изображении
// через пространство HSV
// + накопление данных по соответствующим цветам из RGB

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>

#include <vector>
#include <algorithm>

#define RECT_COLORS_SIZE 10

// получение пикселя изображения (по типу картинки и координатам)
#define CV_PIXEL(type,img,x,y) (((type*)((img)->imageData+(y)*(img)->widthStep))+(x)*(img)->nChannels)

// Various color types
//	    0			1	  2		 3		4		 5		  6		7		8		9			10
enum {cBLACK=0, cWHITE, cGREY, cRED, cORANGE, cYELLOW, cGREEN, cAQUA, cBLUE, cPURPLE, NUM_COLOR_TYPES};
char* sCTypes[NUM_COLOR_TYPES] = {"Black", "White","Grey","Red","Orange","Yellow","Green","Aqua","Blue","Purple"};
uchar cCTHue[NUM_COLOR_TYPES] =    {0,       0,      0,     0,     20,      30,      60,    85,   120,    138  };
uchar cCTSat[NUM_COLOR_TYPES] =    {0,       0,      0,    255,   255,     255,     255,   255,   255,    255  };
uchar cCTVal[NUM_COLOR_TYPES] =    {0,      255,    120,   255,   255,     255,     255,   255,   255,    255  };

typedef unsigned int uint;

// число пикселей данного цвета на изображении 
uint colorCount[NUM_COLOR_TYPES] = {0,		0,		0,		0,		0,		0,		0,		0,		0,		0 };

// Determine what type of color the HSV pixel is. Returns the colorType between 0 and NUM_COLOR_TYPES.
int getPixelColorType(int H, int S, int V)
{
	int color = cBLACK;

#if 1
	if (V < 75)
		color = cBLACK;
	else if (V > 190 && S < 27)
		color = cWHITE;
	else if (S < 53 && V < 185)
		color = cGREY;
	else 
#endif
	{	
		if (H < 7)
			color = cRED;
		else if (H < 25)
			color = cORANGE;
		else if (H < 34)
			color = cYELLOW;
		else if (H < 73)
			color = cGREEN;
		else if (H < 102)
			color = cAQUA;
		else if (H < 140)
			color = cBLUE;
		else if (H < 170)
			color = cPURPLE;
		else	// full circle 
			color = cRED;	// back to Red
	}
	return color;
}

// сортировка цветов по количеству
bool colors_sort(std::pair< int, uint > a, std::pair< int, uint > b)
{
	return (a.second > b.second);
}

int main(int argc, char* argv[])
{
	// для хранения изображения
	IplImage* image=0, *hsv=0, *dst=0, *dst2=0, *color_indexes=0, *dst3=0;

	//
	// загрузка изображения
	//

	char img_name[] =  "Image0.jpg";

	// имя картинки задаётся первым параметром
	char* image_filename = argc >= 2 ? argv[1] : img_name;

	// получаем картинку
	image = cvLoadImage(image_filename, 1);

	printf("[i] image: %s\n", image_filename);
	if(!image){
		printf("[!] Error: cant load test image: %s\n", image_filename);
		return -1;
	}

	// показываем картинку
	cvNamedWindow("image");
	cvShowImage("image", image);

	//
	// преобразуем изображение в HSV 
	//
	hsv = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 3 ); 
	cvCvtColor( image, hsv, CV_BGR2HSV );

	// картинки для хранения результатов
	dst = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 3 ); 
	dst2 = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 3 );
	color_indexes = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); //для хранения индексов цвета

	// для хранения RGB-х цветов
	CvScalar rgb_colors[NUM_COLOR_TYPES];

	int i=0, j=0, x=0, y=0;

	// обнуляем цвета
	for(i=0; i<NUM_COLOR_TYPES; i++) {
		rgb_colors[i] = cvScalarAll(0);
	}

	for (y=0; y<hsv->height; y++) {
		for (x=0; x<hsv->width; x++) {

			// получаем HSV-компоненты пикселя
			uchar H = CV_PIXEL(uchar, hsv, x, y)[0];	// Hue
			uchar S = CV_PIXEL(uchar, hsv, x, y)[1];	// Saturation
			uchar V = CV_PIXEL(uchar, hsv, x, y)[2];	// Value (Brightness)

			// определяем к какому цвету можно отнести данные значения
			int ctype = getPixelColorType(H, S, V);

			// устанавливаем этот цвет у отладочной картинки
			CV_PIXEL(uchar, dst, x, y)[0] = cCTHue[ctype];	// Hue
			CV_PIXEL(uchar, dst, x, y)[1] = cCTSat[ctype];	// Saturation
			CV_PIXEL(uchar, dst, x, y)[2] = cCTVal[ctype];	// Value

			// собираем RGB-составляющие
			rgb_colors[ctype].val[0] += CV_PIXEL(uchar, image, x, y)[0]; // B
			rgb_colors[ctype].val[1] += CV_PIXEL(uchar, image, x, y)[1]; // G
			rgb_colors[ctype].val[2] += CV_PIXEL(uchar, image, x, y)[2]; // R

			// сохраняем к какому типу относится цвет
			CV_PIXEL(uchar, color_indexes, x, y)[0] = ctype;

			// подсчитываем :)
			colorCount[ctype]++;
		}
	}

	// усреднение RGB-составляющих
	for(i=0; i<NUM_COLOR_TYPES; i++) {
		rgb_colors[i].val[0] /= colorCount[i];
		rgb_colors[i].val[1] /= colorCount[i];
		rgb_colors[i].val[2] /= colorCount[i];
	}

	// теперь загоним массив в вектор и отсортируем :)
	std::vector< std::pair< int, uint > > colors;
	colors.reserve(NUM_COLOR_TYPES);

	for(i=0; i<NUM_COLOR_TYPES; i++){
		std::pair< int, uint > color;
		color.first = i;
		color.second = colorCount[i];
		colors.push_back( color );
	}
	// сортируем
	std::sort( colors.begin(), colors.end(), colors_sort );

	// для отладки - выводим коды, названия цветов и их количество
	for(i=0; i<colors.size(); i++){
		printf("[i] color %d (%s) - %d\n", colors[i].first, sCTypes[colors[i].first], colors[i].second );
	}

	// выдаём код первых цветов
	printf("[i] color code: \n");
	for(i=0; i<NUM_COLOR_TYPES; i++)
		printf("%02d ", colors[i].first);
	printf("\n");
	printf("[i] color names: \n");
	for(i=0; i<NUM_COLOR_TYPES; i++)
		printf("%s ", sCTypes[colors[i].first]);
	printf("\n");

	// покажем цвета
	cvZero(dst2);
	int h = dst2->height / RECT_COLORS_SIZE;
	int w = dst2->width;
	for(i=0; i<RECT_COLORS_SIZE; i++ ){
		cvRectangle(dst2, cvPoint(0, i*h), cvPoint(w, i*h+h), rgb_colors[colors[i].first], -1);
	}
	cvShowImage("colors", dst2);
	//cvSaveImage("dominate_colors_table.png", dst2);

	// покажем картинку в найденных цветах
	dst3 = cvCloneImage(image);
	for (y=0; y<dst3->height; y++) {
		for (x=0; x<dst3->width; x++) {
			int color_index = CV_PIXEL(uchar, color_indexes, x, y)[0];

			CV_PIXEL(uchar, dst3, x, y)[0] = rgb_colors[color_index].val[0];
			CV_PIXEL(uchar, dst3, x, y)[1] = rgb_colors[color_index].val[1];
			CV_PIXEL(uchar, dst3, x, y)[2] = rgb_colors[color_index].val[2];
		}
	}

	cvNamedWindow("dst3");
	cvShowImage("dst3", dst3);
	//cvSaveImage("dominate_colors.png", dst3);

	// конвертируем отладочную картинку обратно в RGB
	cvCvtColor( dst, dst, CV_HSV2BGR );

	// показываем результат
	cvNamedWindow("color");
	cvShowImage("color", dst);

	// ждём нажатия клавиши
	cvWaitKey(0);

	// освобождаем ресурсы
	cvReleaseImage(&image);
	cvReleaseImage(&hsv);
	cvReleaseImage(&dst);
	cvReleaseImage(&dst2);
	cvReleaseImage(&color_indexes);
	cvReleaseImage(&dst3);

	// удаляем окна
	cvDestroyAllWindows();
	return 0;
}

dominate_colors_hsv.cpp

Пример работы:


Использовать метод k-средних для определения доминирующих цветов очень просто.
Фактически, решение задачи заключается в определении кластеров цветов на изображении.
Как мы помним, идея метода k-средних состоит в минимизации суммарного квадратичного отклонения точек выборки от центров кластеров.
Сначала, начальные центры кластеров выбираются случайно, затем вычисляется принадлежность каждого элемента к тому или иному центру, а потом на каждой итерации алгоритма выполняется пересчёт центров масс кластеров — и так до тех пор, пока центры не перестают смещаться.
При решении задачи определения доминирующих цветов, каждый пиксель изображения рассматривается как точка в трёхмерном пространстве RGB, в котором вычисляется расстояние до центров масс кластеров.
Для оптимизации работы алгоритма k-means, картинку желательно предварительно уменьшить.

Исходный код:
//
// определение преобладающих цветов на изображении
// при помощи k-Means
//

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>

#include <vector>
#include <algorithm>

// получение пикселя изображения (по типу картинки и координатам)
#define CV_PIXEL(type,img,x,y) (((type*)((img)->imageData+(y)*(img)->widthStep))+(x)*(img)->nChannels)

const CvScalar BLACK = CV_RGB(0, 0, 0);				// чёрный
const CvScalar WHITE = CV_RGB(255, 255, 255);		// белый

const CvScalar RED = CV_RGB(255, 0, 0);				// красный
const CvScalar ORANGE = CV_RGB(255, 100, 0);		// оранжевый 
const CvScalar YELLOW = CV_RGB(255, 255, 0);		// жёлтый 
const CvScalar GREEN = CV_RGB(0, 255, 0);			// зелёный  
const CvScalar LIGHTBLUE = CV_RGB(60, 170, 255);	// голубой 
const CvScalar BLUE = CV_RGB(0, 0, 255);			// синий 
const CvScalar VIOLET = CV_RGB(194, 0, 255);		// фиолетовый

const CvScalar GINGER = CV_RGB(215, 125, 49);		// рыжий
const CvScalar PINK = CV_RGB(255, 192, 203);		// розовый
const CvScalar LIGHTGREEN = CV_RGB(153, 255, 153);	// салатовый
const CvScalar BROWN = CV_RGB(150, 75, 0);			// коричневый 

typedef unsigned char uchar;
typedef unsigned int uint;

typedef struct ColorCluster {
	CvScalar color;
	CvScalar new_color;
	int count;

	ColorCluster():count(0) {
	}
} ColorCluster;

float rgb_euclidean(CvScalar p1, CvScalar p2)
{
	float val = sqrtf( (p1.val[0]-p2.val[0])*(p1.val[0]-p2.val[0]) + 
		(p1.val[1]-p2.val[1])*(p1.val[1]-p2.val[1]) +
		(p1.val[2]-p2.val[2])*(p1.val[2]-p2.val[2]) +
		(p1.val[3]-p2.val[3])*(p1.val[3]-p2.val[3]));

	return val;
}

// сортировка цветов по количеству
bool colors_sort(std::pair< int, uint > a, std::pair< int, uint > b)
{
	return (a.second > b.second);
}

int main(int argc, char* argv[])
{
	// для хранения изображения
	IplImage* image=0, *src=0, *dst=0, *dst2=0;

	//
	// загрузка изображения
	//
	char img_name[] =  "Image0.jpg";
	// имя картинки задаётся первым параметром
	char* image_filename = argc >= 2 ? argv[1] : img_name;

	// получаем картинку
	image = cvLoadImage(image_filename, 1);

	printf("[i] image: %s\n", image_filename);
	if(!image){
		printf("[!] Error: cant load test image: %s\n", image_filename);
		return -1;
	}

	// показываем картинку
	cvNamedWindow("image");
	cvShowImage("image", image);

	// ресайзим картинку (для скорости обработки)
	src = cvCreateImage(cvSize(image->width/2, image->height/2), IPL_DEPTH_8U, 3);
	cvResize(image, src, CV_INTER_LINEAR);

	cvNamedWindow("img");
	cvShowImage("img", src);

	// картинка для хранения индексов кластеров
	IplImage* cluster_indexes = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
	cvZero(cluster_indexes);

#define CLUSTER_COUNT 10
	int cluster_count = CLUSTER_COUNT;
	ColorCluster clusters[CLUSTER_COUNT];

	int i=0, j=0, k=0, x=0, y=0;

	// начальные цвета кластеров
#if 0
	clusters[0].new_color = RED;
	clusters[1].new_color = ORANGE;
	clusters[2].new_color = YELLOW;
	//	clusters[3].new_color = GREEN;
	//	clusters[4].new_color = LIGHTBLUE;
	//	clusters[5].new_color = BLUE;
	//	clusters[6].new_color = VIOLET;
#elif 0
	clusters[0].new_color = BLACK;
	clusters[1].new_color = GREEN;
	clusters[2].new_color = WHITE;
#else
	CvRNG rng = cvRNG(-1);
	for(k=0; k<cluster_count; k++)
		clusters[k].new_color = CV_RGB(cvRandInt(&rng)%255, cvRandInt(&rng)%255, cvRandInt(&rng)%255);
#endif

	// k-means
	float min_rgb_euclidean = 0, old_rgb_euclidean=0;

	while(1) {
		for(k=0; k<cluster_count; k++) {
			clusters[k].count = 0;
			clusters[k].color = clusters[k].new_color;
			clusters[k].new_color = cvScalarAll(0);
		}

		for (y=0; y<src->height; y++) {
			for (x=0; x<src->width; x++) {
				// получаем RGB-компоненты пикселя
				uchar B = CV_PIXEL(uchar, src, x, y)[0];	// B
				uchar G = CV_PIXEL(uchar, src, x, y)[1];	// G
				uchar R = CV_PIXEL(uchar, src, x, y)[2];	// R

				min_rgb_euclidean = 255*255*255;
				int cluster_index = -1;
				for(k=0; k<cluster_count; k++) {
					float euclid = rgb_euclidean(cvScalar(B, G, R, 0), clusters[k].color);
					if(  euclid < min_rgb_euclidean ) {
						min_rgb_euclidean = euclid;
						cluster_index = k;
					}
				}
				// устанавливаем индекс кластера
				CV_PIXEL(uchar, cluster_indexes, x, y)[0] = cluster_index;

				clusters[cluster_index].count++;
				clusters[cluster_index].new_color.val[0] += B;
				clusters[cluster_index].new_color.val[1] += G;
				clusters[cluster_index].new_color.val[2] += R;
			}
		}

		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;
		}

		//printf("%f\n", min_rgb_euclidean);
		if( fabs(min_rgb_euclidean - old_rgb_euclidean)<1 ) 
			break;

		old_rgb_euclidean = min_rgb_euclidean;
	}
	//-----------------------------------------------------

	// теперь загоним массив в вектор и отсортируем :)
	std::vector< std::pair< int, uint > > colors;
	colors.reserve(CLUSTER_COUNT);

	int colors_count = 0;
	for(i=0; i<CLUSTER_COUNT; i++){
		std::pair< int, uint > color;
		color.first = i;
		color.second = clusters[i].count;
		colors.push_back( color );
		if(clusters[i].count>0)
			colors_count++;
	}
	// сортируем
	std::sort( colors.begin(), colors.end(), colors_sort );

	// покажем цвета
	dst2 = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 3 );
	cvZero(dst2);
	int h = dst2->height / CLUSTER_COUNT;
	int w = dst2->width;
	for(i=0; i<CLUSTER_COUNT; i++ ){
		cvRectangle(dst2, cvPoint(0, i*h), cvPoint(w, i*h+h), clusters[colors[i].first].color, -1);
		printf("[i] Color: %d %d %d (%d)\n", (int)clusters[colors[i].first].color.val[2],
			(int)clusters[colors[i].first].color.val[1],
			(int)clusters[colors[i].first].color.val[0],
			clusters[colors[i].first].count);
	}
	cvNamedWindow("colors");
	cvShowImage("colors", dst2);
	//cvResize(dst2, image, CV_INTER_LINEAR);
	//cvSaveImage("dominate_colors_table.png", image);
	//-----------------------------------------------------

	// покажем картинку в найденных цветах
	dst = cvCloneImage(src);
	for (y=0; y<dst->height; y++) {
		for (x=0; x<dst->width; x++) {
			int cluster_index = CV_PIXEL(uchar, cluster_indexes, x, y)[0];

			CV_PIXEL(uchar, dst, x, y)[0] = clusters[cluster_index].color.val[0];
			CV_PIXEL(uchar, dst, x, y)[1] = clusters[cluster_index].color.val[1];
			CV_PIXEL(uchar, dst, x, y)[2] = clusters[cluster_index].color.val[2];
		}
	}

	cvNamedWindow("dst");
	cvShowImage("dst", dst);
	//cvResize(dst, image, CV_INTER_LINEAR);
	//cvSaveImage("dominate_colors.png", image);
	//-----------------------------------------------------

	// ждём нажатия клавиши
	cvWaitKey(0);

	// освобождаем ресурсы
	cvReleaseImage(&image);
	cvReleaseImage(&src);

	cvReleaseImage(&cluster_indexes);

	cvReleaseImage(&dst);
	cvReleaseImage(&dst2);

	// удаляем окна
	cvDestroyAllWindows();
	return 0;
}

dominate_colors_kmeans.cpp

Пример работы:


— стоит обратить внимание, что здесь заметны слабые стороны алгоритма k-means:
возможность разных результатов при разных начальных значениях

А теперь сравним результаты работы алгоритмов
исходная картинка:

алгоритм HSV (10 цветов)

алгоритм k-means (10 цветов)

алгоритм k-means (5 цветов)

алгоритм k-means (3 цвета)


Сравнивним результирующие картинки в найденных цветах:
исходная — HSV — k-means (10 цветов) — k-means (5 цветов)





Сравним таблицы доминирующих цветов:
HSV — k-means (10 цветов) — k-means (5 цветов)




Ссылки:
Определение доминирующих тонов на изображении
Определение доминирующих тонов на изображении [v 1.1]
Определение доминирующих цветов: Python и метод k-средних
  • +1
  • 6 ноября 2012, 19:51
  • noonv

Комментарии (17)

RSS свернуть / развернуть
+
+1
Здравствуйте!
Меня очень заинтересовала Ваша статья об OpenCV — определение доминирующих цветов на изображении/
Хотел уточнить возможно ли запустить указанный Вами код на С++ builder для использования компонента Timage
на данный момент не получается запустить Ваши примеры на С++ builder а нужно именно на С++ builder, буду очень благодарен если подскажете в этом плане что-то я студент начинающий очень нужна Ваша помощь также еще вопрос возможна реализация описанных Вами методов без использования OpenCV. Заранее благодарен за ответ.
avatar

Jon

  • 25 мая 2016, 06:45
+
0
Привет!
Т.к. здесь никаких специфичных функций не используется, то не вижу проблем перенести этот код под любую другую платформу (пример — tinycv).
avatar

noonv

  • 25 мая 2016, 10:20
+
0
Привет вот еще такая проблема при использовании Вашего кода тот что второй метод 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' не подскажете в чем может быть причина, также как можно сделать в данном методе чтобы белый фон игнорировался?
avatar

Jon

  • 26 мая 2016, 01:15
+
0
Очевидно, нужно проверять, что clusters[k].count не равен нулю.
Чтобы игнорировать белый — можно просто пропускать пиксели с RGB-параметрами около (255, 255, 255).
avatar

noonv

  • 26 мая 2016, 11:09
+
0
Здравствуйте, не подскажите пожалуйста, можно ли обрабатывать при помощи open cv более сложные изображения, типа мозаики, а именно выделение на изображении определенных объектов, и довести это до автомата? Сейчас я смог находить на изображении только точные геометрические предметы( круг, треугольник, прямоугольник и линии, но честно говоря получилось не очень)
Я думал может как-то различать по цвету от темного к светлому
Просто я студент 2 курса, и недавно занимаюсь программированием c#, а c++ для меня вообще не знаком) поэтому ваши примеры мне не понятны( заранее спасибо за ответ
avatar

Sirtau

  • 21 ноября 2016, 07:10
+
0
Разумеется, можно. OpenCV — это библиотека в которой уже реализованы многие важные функции. Но реализовывать свои собственные или же применять существующие — это полностью ваша задача.
avatar

noonv

  • 21 ноября 2016, 12:57
+
0
Здоавствуйте. Не подскажите, пожалуйста, как с помощью первого способа вывести в консоль количество пикселей определенного цвета не по всей картинке, а только в заданной области? Просто в коде цвета подсчитываются сразу colorCount[ctype]++; а если задать массив, что array[x][y]= ctype, то выдаются разные ошибки.
avatar

SMore

  • 15 декабря 2016, 19:14
+
0
Например, при помощи ROI.
avatar

admin

  • 16 декабря 2016, 14:11
+
+1
На самом деле надо было просто создать динамический массив через указатель :) Как-то глупо получилось. Но все равно спасибо за помощь!
avatar

SMore

  • 21 декабря 2016, 21:27
+
0
Да, это было бы хорошо. Но нельзя всё-таки получить именно массив/матрицу изображения, чтобы легко оперировать с ним, зная, что, например, пиксель [245][108]=0, т.е. имеет чёрный цвет, индекс которого в данной программе — 0? Просто тогда было бы легче рассматривать изображение с доминирующими цветами после его обработки, не прибегая к обращению пикселя в RGB(x,x,x) с тремя параметрами, т.к. во время работы того кода по выделению доминирующих цветов новый цвет пикселя напрямую присваивается в виде индекса, который варьируется от 0 до 7. И ни как нельзя это присвоение как-то перехватить и записать в массив? Дело в том, что для моего алгоритма, который я хочу написать, нужно рассматривать маленькие области, к примеру, 20x20 пикселей для последующей обработки, зная какие доминирующие цвета там есть. И так как новое присвоение цвета уже известно, то почему бы просто это не записать в массив? Просто тогда на картинке в 4к разрешением таких областей придется создавать ну очень много, т.к. изображение будет разбито на эти маленькие сегменты, и каждый в отдельности рассматривать неудобно с помощью ROI.
В любом случае, спасибо за ответ!
avatar

SMore

  • 16 декабря 2016, 20:04
+
0
Добрый день!
Возможно, не совсем в тему, но можете подсказать, пожалуйста, как создать кнопки в OpenСV и использовать их так, чтобы доминирующие цвета присваивались, например, к 20% процентам полученных цветов и так далее?
Заранее спасибо за помощь!
avatar

TheQuelby

  • 25 декабря 2016, 10:21
+
0
здраствуйте, спасибо за туториал, у меня такой вопрос, а возможно ли отобразить доминирующие цвета ввиде pie-чарта? Спасибо.
avatar

uldibai

  • 4 января 2017, 18:55
+
0
Используя примитивы рисования (см. Drawing Functions), думается вполне возможно.
avatar

admin

  • 9 января 2017, 11:36
+
0
Получилось, спасибо!
avatar

uldibai

  • 9 января 2017, 19:10
+
0
Не получается релизнуть программу. Вот ошибка: The program '[6932] opencv.exe' has exited with code -1 (0xffffffff).
В чем может быть дело?
avatar

TheQuelby

  • 18 января 2017, 22:58
+
0
Здравствуйте. я применила данный код для видео, но что то не так, я передаю fraim как изображение, для первого фрейма работает, но последующие идут с ошибкой и средние RGB значения все уменьшаются с каждым фреймом. В чем может быть ошибка? Спасибо!
avatar

uldibai

  • 20 января 2017, 19:19
+
0
Дело было в цикле, решилось, спасибо.
avatar

uldibai

  • 20 января 2017, 19:59

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.