Получение и изменение цвета пикселя в изображении. Библиотека PIL Python
8 августа 2013 г.
Archy
Просмотров: 59269
RSS
Обсудить
Работа с изображениями » Python для начинающих
изменить пиксель python, сменить формат изображения python, сохранения изображения python

В прошлой статье мы узнали как установить библиотеку PIL в Python и начать уже с ней работать. В этой статье мы продолжаем изучение библиотеки PIL. Начиная с версией 1.1.6 метод load() возвращает объект, с помощью которого можно получить доступ к отдельным пикселям изображения. Указав два значения внутри квадратных скобок, можно получить или задать цвет пикселя.
>>> img = Image.open("foto.jpg") >>> obj = img.load() >>> obj[25, 45] # Получаем цвет пикселя (122, 86, 62) >>> obj[25, 45] = (255, 0, 0) # Задаем цвет пикселя (красный)
Для доступа к отдельному пикселю вместо метода load() можно использовать методы getpixel() и putpixel(). Метод getpixel() позволяет получить цвет указанного пикселя, а метод putpixel(, ) изменяет цвет пикселя. Координаты пикселя указываются в виде кортежа из двух элементов. Необходимо заметить, что эти методы работают медленнее метода load(). Пример использования метода getpixel() и putpixel() приведен ниже.
Использование метода getpixel() и putpixel()
>>> img = Image.open("foto.jpg") >>> img.getpixel((25, 45)) # Получаем цвет пикселя (122, 86, 62) >>> img.putpixel((25, 45), (255, 0, 0)) # Изменяем цвет пикселя >>> img.getpixel((25, 45)) # Получаем цвет пикселя (255, 0, 0) >>> img.show() # Просматриваем изображение
В этом примере для просмотра изображения мы воспользовались методом show(). Метод show() создает временный файл в формате BMP и запускает программу для просмотра изображения, используемую в операционной системе по умолчанию. Например, на моем компьютере запускается программа ACDSee. Для сохранения изображения в файл предназначен метод save().
В первом параметре указывается абсолютный или относительный путь. Вместо пути можно передать файловый объект, открытый в бинарном режиме. Сохраним изображение в форматах JPEG и BMP разными способами.
Сохраняем изображение в Python
>>> img.save("tmp.jpg") # В формате JPEG >>> img.save("tmp.bmp", "BMP") # В формате BMP >>> f = open("tmp2.bmp", "wb") >>> img.save(f, "BMP") # Передаем файловый объект >>> f.close()
Обратите внимание на то, что мы открыли файл в формате JPEG, а сохранили его в формате BMP. Таким образом, можно открывать изображения в одном формате и конвертировать его в другой формат. Если сохранить изображение не удалось, возбуждается исключение IOError. Если параметр не указан, то формат изображения определяется по расширению файла.
В параметре можно указать дополнительный характеристики изображения. Поддерживаемый опции зависят от формата изображения. Например, по умолчанию изображения в формате JPEG сохраняются с качеством 75. С помощью опции quality можно указать другое значение в диапазоне от 1 до 100.
>>> img.save("tmp3.jpg", "JPEG", quality=100) # Указание качества
За дополнительной информации по опциям обращайтесь к документации. Так же для более подробной инструкции игры в покер можете прочитать poker правила и повысить свои навыки в этой игре. Удивите своих знакомых во время игры в покер, продемонстрировав им свой профессионализм игры.
Еще записи по теме
- Курсы Python для новичков
- Как защитить Python-код от модификации?
- Создание и открытие базы данных SQLite в Python
- Алгоритм расшифровки названии автомобилей в игре «Что за тачка?» на Python
- Распаковка последовательности в отдельные переменные
- Вложение декораторов в Python
- Стандартные библиотеки и сторонние библиотеки Python
OpenCV: HSV и поиск объектов по цвету
Рассмотрим еще один способ поиска объектов на изображениях с помощью OpenCV. Воспользуемся одним из самых простых, однако достаточно полезных на практике методов — распознавание по цвету.
Вот что у нас получится:

Коротко о цветовой схеме HSV
Очень часто с изображениями работают как с массивом пикселей в формате RGB. Хотя такое представление оказывается относительно интуитивным, его нельзя назвать оптимальным для задачи, которую нам предстоит решить. В RGB цвет пикселя определяется насыщенностью красным, зеленым и голубым. Таким образом, выбор диапазона оттенков одного и того же цвета становится не самой простой задачей.
С форматом HSV дела обстоят иначе. Эта цветовая схема определяется тремя компонентами:

В схеме HSV базовый цвет можно выбрать с помощью компоненты Hue (например, красный, оранжевый и т.д.). Две остальных компоненты позволяют регулировать насыщенность и яркость базового цвета, делая его более насыщенным или тусклым, более светлым или темным.
Такие свойства HSV позволяют легко задавать диапазоны, которые смогут захватывать области нужного цвета и его оттенков.
Реализация поиска объектов на изображении по цвету с помощью OpenCV
В интерфейс приложения включим область для просмотра изображений, кнопку загрузки другого изображения, переключатель режимов для удобства отладки и несколько ползунков для выбора фильтров по компонентам HSV:
![]()
Итак, мы хотим найти на изображении объекты некоторого цвета. Сделать это можно в несколько этапов:
- Отфильтровать все лишнее по диапазону HSV-цветов. Здесь мы получим битовую маску, где нужные нам участки изображения (в идеале — искомые объекты) окажутся помечены белым цветом, а все остальное станет черным;
- Немного «подчистить» шумы и сгладить битовую маску;
- Найти контуры получившихся белых областей;
- Определить прямоугольники, в которые вписываются найденные контуры.
Заголовочный файл mainwidget.h :
#ifndef MAINWIDGET_H #define MAINWIDGET_H #include #include #include namespace Ui < class MainWidget; >class MainWidget : public QWidget < Q_OBJECT public: explicit MainWidget( QWidget* parent = 0 ); ~MainWidget(); private slots: void onLoad(); void refreshHSV(); private: Ui::MainWidget* ui; cv::Mat m_mat; QString m_lastLoadPath; QSettings m_settings; >; #endif // MAINWIDGET_H
Файл реализации mainwidget.cpp :
#include "mainwidget.h" #include "ui_mainwidget.h" #include #include #include #include #include static const char* CONFIG_FILE_NAME = "config.ini"; MainWidget::MainWidget( QWidget* parent ) : QWidget( parent ), ui( new Ui::MainWidget ), m_lastLoadPath( "." ), m_settings( CONFIG_FILE_NAME, QSettings::IniFormat ) < ui->setupUi( this ); foreach( QSlider* slider, findChildren< QSlider* >() ) < connect( slider, SIGNAL( sliderMoved( int ) ), SLOT( refreshHSV() ) ); QString sliderName = slider->objectName(); slider->setValue( m_settings.value( sliderName, slider->value() ).toInt() ); if( QSpinBox* sp = findChild< QSpinBox* >( "sp" + sliderName.mid( 2 ) ) ) < sp->setMinimum( slider->minimum() ); sp->setMaximum( slider->maximum() ); sp->setValue( slider->value() ); connect( sp, SIGNAL( valueChanged( int ) ), SLOT( refreshHSV() ) ); > > foreach( const QRadioButton* rb, findChildren< QRadioButton* >() ) < connect( rb, SIGNAL( clicked( bool ) ), SLOT( refreshHSV() ) ); >connect( ui->bnLoad, SIGNAL( clicked( bool ) ), SLOT( onLoad() ) ); > MainWidget::~MainWidget() < foreach( const QSlider* slider, findChildren< QSlider* >() ) < QString sliderName = slider->objectName(); m_settings.setValue( sliderName, slider->value() ); > delete ui; > void MainWidget::onLoad() < QString imgName = QFileDialog::getOpenFileName( this, "Load image", m_lastLoadPath, "Images (*.jpg *.jpeg *.png *.bmp)" ); if( imgName.isEmpty() ) < return; >m_lastLoadPath = QFileInfo( imgName ).absolutePath(); m_mat = cv::imread( imgName.toStdString() ); if( !m_mat.empty() ) < cv::cvtColor( m_mat, m_mat, cv::COLOR_BGR2RGB ); >refreshHSV(); > void MainWidget::refreshHSV() < if( m_mat.empty() ) < return; >QImage resultImg; if( ui->rbOriginal->isChecked() ) < resultImg = QImage( m_mat.data, m_mat.cols, m_mat.rows, m_mat.step, QImage::Format_RGB888 ).copy(); >else < int hueFrom = ui->slHueFrom->value(); int hueTo = std::max( hueFrom, ui->slHueTo->value() ); int saturationFrom = ui->slSaturationFrom->value(); int saturationTo = std::max( saturationFrom, ui->slSaturationTo->value() ); int valueFrom = ui->slValueFrom->value(); int valueTo = std::max( valueFrom, ui->slValueTo->value() ); cv::Mat thresholdedMat; cv::cvtColor( m_mat, thresholdedMat, cv::COLOR_RGB2HSV ); // Отфильтровываем только то, что нужно, по диапазону цветов cv::inRange( thresholdedMat, cv::Scalar( hueFrom, saturationFrom, valueFrom ), cv::Scalar( hueTo, saturationTo, valueTo ), thresholdedMat ); // Убираем шум cv::erode( thresholdedMat, thresholdedMat, cv::getStructuringElement( cv::MORPH_ELLIPSE, cv::Size( 5, 5 ) ) ); cv::dilate( thresholdedMat, thresholdedMat, cv::getStructuringElement( cv::MORPH_ELLIPSE, cv::Size( 5, 5 ) ) ); // Замыкаем оставшиеся крупные объекты cv::dilate( thresholdedMat, thresholdedMat, cv::getStructuringElement( cv::MORPH_ELLIPSE, cv::Size( 5, 5 ) ) ); cv::erode( thresholdedMat, thresholdedMat, cv::getStructuringElement( cv::MORPH_ELLIPSE, cv::Size( 5, 5 ) ) ); if( ui->rbCanny->isChecked() ) < // Визуально выделяем границы cv::Canny( thresholdedMat, thresholdedMat, 100, 50, 5 ); >if( ui->rbResult->isChecked() ) < // Находим контуры std::vector< std::vector< cv::Point >> countours; std::vector < cv::Vec4i >hierarchy; cv::findContours( thresholdedMat, countours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point( 0, 0 ) ); std::vector < cv::Rect >rects; for( uint i = 0; i < countours.size(); ++i ) < // Пропускаем внутренние контуры if( 0 rects.push_back( cv::boundingRect( countours[ i ] ) ); > resultImg = QImage( m_mat.data, m_mat.cols, m_mat.rows, m_mat.step, QImage::Format_RGB888 ).copy(); QPainter p; p.begin( &resultImg ); p.setPen( QPen( Qt::green, 2 ) ); foreach( const cv::Rect& r, rects ) < p.drawRect( r.x, r.y, r.width, r.height ); >p.end(); > else < resultImg = QImage( thresholdedMat.data, thresholdedMat.cols, thresholdedMat.rows, thresholdedMat.step, QImage::Format_Indexed8 ).copy(); >> ui->lbView->setPixmap( QPixmap::fromImage( resultImg ).scaled( ui->lbView->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ) ); >
В целом код соответствует нашей задумке и снабжен комментариями, поэтому должен быть понятен. Однако требуется одно замечание. Мы задействовали функцию Canny() , но не используем ее для фактического нахождения контуров. Это связано с тем, что окончательный результат мало чем визуально отличается от того, что будет получен без применения этой функции. При этом сама функция достаточно интересна для того, чтобы ее можно было оставить в нашем тестовом приложении.
OpenCV — определение доминирующих цветов на изображении
Определение доминирующих цветов на изображении — очень полезная техника, например для выбора палитры веб-сайта, элементов UI и т.п.
Существуют и online-сервисы, решающие подобную задачу самыми разными методами.
Однако, попробуем решить данную задачку самостоятельно при помощи OpenCV.
Рассмотрим два способа:
— определение отношения пикселя к заданному набору цветов (в пространстве HSV)
— использовании кластеризации методом k-средних (k-means).
Первый способ довольно прост — мы просто конвертируем картинку в цветовое пространство HSV, а затем перебираем все пиксели изображения и по его значениям H, S и V при помощи функции getPixelColorType() определяем к какому цвету из заданого перечисления:
enum ;
относится цвет.
При этом, число таких пикселей подсчитывается. Сохраняются и RGB-составляющие, для последующего усреднения.
// // определение преобладающих цветов на изображении // через пространство HSV // + накопление данных по соответствующим цветам из RGB #include #include #include #include #include #include #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 ; char* sCTypes[NUM_COLOR_TYPES] = ; uchar cCTHue[NUM_COLOR_TYPES] = ; uchar cCTSat[NUM_COLOR_TYPES] = ; uchar cCTVal[NUM_COLOR_TYPES] = ; typedef unsigned int uint; // число пикселей данного цвета на изображении uint colorCount[NUM_COLOR_TYPES] = ; // 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 for (y=0; yheight; y++) < for (x=0; xwidth; 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 // теперь загоним массив в вектор и отсортируем :) std::vector < std::pair< int, uint >> colors; colors.reserve(NUM_COLOR_TYPES); for(i=0; i color; color.first = i; color.second = colorCount[i]; colors.push_back( color ); > // сортируем std::sort( colors.begin(), colors.end(), colors_sort ); // для отладки - выводим коды, названия цветов и их количество for(i=0; i // выдаём код первых цветов printf("[i] color code: \n"); for(i=0; iheight / RECT_COLORS_SIZE; int w = dst2->width; for(i=0; i cvShowImage("colors", dst2); //cvSaveImage("dominate_colors_table.png", dst2); // покажем картинку в найденных цветах dst3 = cvCloneImage(image); for (y=0; yheight; y++) < for (x=0; xwidth; 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; >

Пример работы:
Использовать метод k-средних для определения доминирующих цветов очень просто.
Фактически, решение задачи заключается в определении кластеров цветов на изображении.
Как мы помним, идея метода k-средних состоит в минимизации суммарного квадратичного отклонения точек выборки от центров кластеров.
Сначала, начальные центры кластеров выбираются случайно, затем вычисляется принадлежность каждого элемента к тому или иному центру, а потом на каждой итерации алгоритма выполняется пересчёт центров масс кластеров — и так до тех пор, пока центры не перестают смещаться.
При решении задачи определения доминирующих цветов, каждый пиксель изображения рассматривается как точка в трёхмерном пространстве RGB, в котором вычисляется расстояние до центров масс кластеров.
Для оптимизации работы алгоритма k-means, картинку желательно предварительно уменьшить.
// // определение преобладающих цветов на изображении // при помощи k-Means // #include #include #include #include #include #include // получение пикселя изображения (по типу картинки и координатам) #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 for (y=0; yheight; y++) < for (x=0; xwidth; 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> // устанавливаем индекс кластера 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 min_rgb_euclidean) min_rgb_euclidean = ecli; > //printf("%f\n", min_rgb_euclidean); if( fabs(min_rgb_euclidean - old_rgb_euclidean) //----------------------------------------------------- // теперь загоним массив в вектор и отсортируем :) std::vector < std::pair< int, uint >> colors; colors.reserve(CLUSTER_COUNT); int colors_count = 0; for(i=0; i 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 cvNamedWindow("colors"); cvShowImage("colors", dst2); //cvResize(dst2, image, CV_INTER_LINEAR); //cvSaveImage("dominate_colors_table.png", image); //----------------------------------------------------- // покажем картинку в найденных цветах dst = cvCloneImage(src); for (y=0; yheight; y++) < for (x=0; xwidth; 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; >

Пример работы:
— стоит обратить внимание, что здесь заметны слабые стороны алгоритма 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 цветов)


Получение RGB цвета определённого пикселя на экране
Поиск определенного пикселя на экране
Здравствуйте. Я хочу найти определённый пиксель на экране. Я опробовал способ через opencv.
Поиск определенного пикселя на экране
Всем привет. Пишу игрового бота. Дано: Есть часть экрана размером в 1080х871 Нужно: Найти в этой.
получение координат пикселя определённого цвета
Не так давно начал изучать c++, перебрал множество вариантов. не как не могу быстро найти.
Получение значений RGB из пикселя
Имеется SDL_Surface в который я загрузил картинку, нужно получить значения RGB для каждого.
![]()
4615 / 2036 / 359
Регистрация: 17.03.2012
Сообщений: 10,103
Записей в блоге: 6
Если на винде — то через winapi. Чистый питон ничего не знает про экран.
![]()
1354 / 651 / 207
Регистрация: 23.03.2014
Сообщений: 3,057
Макс Орлов, Направение дать могу
1 2 3 4 5
from PIL import Image im = Image.open('1.jpg', 'r') width, height = im.size pixel_values = list(im.getdata()) print(pixel_values)
![]()
4615 / 2036 / 359
Регистрация: 17.03.2012
Сообщений: 10,103
Записей в блоге: 6
Вот кстати да, хорошо бы указать, где пиксель. Я подумал, на экране, но может и про файл речь идёт.
Просто Лис
![]()
5321 / 3335 / 1021
Регистрация: 17.05.2012
Сообщений: 9,768
Записей в блоге: 9
1 2 3 4
from matplotlib.image import imread img = imread('abc.tiff') print(type(img))
1 2 3
import cv2 im = cv2.imread("abc.tiff",mode='RGB') print type(im)
Регистрация: 29.12.2018
Сообщений: 14
никто не ответил про самый простой способ. Держите кому надо
1 2 3 4 5 6 7 8
>>> import pyautogui >>> pix = pyautogui.pixel(100, 200) >>> pix RGB(red=130, green=135, blue=144) >>> pix[0] 130 >>> pix.red 130
Искусственный интеллект
112 / 82 / 34
Регистрация: 26.08.2020
Сообщений: 590
Записей в блоге: 1
Макс Орлов, Этот способ не самый быстрый. Быстрее будет так как то
1 2 3 4 5 6 7 8 9 10
import win32gui def pixel_color_at(x, y): hdc = win32gui.GetWindowDC(win32gui.GetDesktopWindow()) c = int(win32gui.GetPixel(hdc, x, y)) # (r, g, b) return (c & 0xff), ((c >> 8) & 0xff), ((c >> 16) & 0xff) print(pixel_color_at(10, 10)) print(pixel_color_at(*win32gui.GetCursorPos()))
Ну а на C++ так ваще 1млн раз в секнду)
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Определение цвета пикселя под курсором и контроль RGB ленты на Arduino
Доброго времени суток уважаемые форумчане! Как получить цвет пикселя под курсором на экране при.
Цвет определенного пикселя на экране
Как сделать процедуру с помощью которой в текстовом редакторе отображался цвет(в формате.

Определение цвета пикселя на экране
Добрый вечер, нужна помощь! Пишу программу, которая при определенном цвете пикселя выполняет клик.
Определение цвета пикселя на экране
Ребят, сразу прошу не счесть за тупость. Я гуглил! Представим, у меня есть на экране область, цвет.
Узнать цвет определенного пикселя на экране
Привет всем:) столкнулся с проблемой, а проблема состоит в том, что я хочу узнать цвет.
Поиск координат пикселя определенного цвета
Здравствуйте, уважаемые участники форума! Я только начинаю программировать на С++ Builder. У меня.

Быстрый поиск цвета пикселя на экране монитора
Подскажите как можно реализовать быстрый поиск определеного пикселя на экране. Накидал.