1. OpenCV шаг за шагом. Введение
2. Установка
3. Hello World
4. Загрузка картинки.
5. Вывод видео
6. Ползунок
7. Захват видео с камеры
8. Запись видео
9. События от мышки
10. Обработка изображения — сглаживание
11. Обработка изображения — изменение размеров
12. ROI — интересующая область изображения
13. Типы данных OpenCV
14. Матрица
15. Сохранение данных в XML
16. Генерация случайных чисел
17. Обработка изображения — морфологические преобразования
18. Обработка изображения — морфологические преобразования 2
19. Обработка изображения — заливка части изображения
20. Обработка изображения — альфа-смешивание
21. Обработка изображения — пороговое преобразование
22. Поиск объекта по цвету — RGB
23. Поиск объекта по цвету. Цветовое пространство HSV.
Успели соскучиться? Всё суета-суета 🙂 А ещё и Новый Год приближается 🙂
Как понятно из названия, продолжим рассмотрение выделения объектов по цвету. И в конце, в качестве бонуса, рассмотрим пример детектирования кожи 🙂
На прошлом шаге было рассмотрено выделение объекта по его RGB-цвету, но использовать модель HSV намного удобнее, т.к. координаты этой цветовой модели выбраны с учетом человеческого восприятия.
HSV (англ. Hue, Saturation, Value — тон, насыщенность, значение) — цветовая модель, в которой координатами цвета являются:
* Hue — цветовой тон, (например, красный, зелёный или сине-голубой). Варьируется в пределах 0—360°, однако иногда приводится к диапазону 0—100 или 0—1.
* Saturation — насыщенность. Варьируется в пределах 0—100 или 0—1. Чем больше этот параметр, тем «чище» цвет, поэтому этот параметр иногда называют чистотой цвета. А чем ближе этот параметр к нулю, тем ближе цвет к нейтральному серому.
* Value (значение цвета) или Brightness — яркость. Также задаётся в пределах 0—100 и 0—1.
Модель HSV была создана Элви Реем Смитом, одним из основателей Pixar, в 1978 году. Она является нелинейным преобразованием модели RGB.
Эта модель очень удобна для поиска на изображении объектов по цвету (и яркости). Например, пятно от лазерной указки, цветовые маркеры или просто объекты с выделяющимся цветом.
Преобразовать изображение из RGB в HSV очень просто:
// создаём изображения IplImage* hsv = cvCreateImage( cvGetSize(src), 8, 3 ); IplImage* h_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* s_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* v_plane = cvCreateImage( cvGetSize(src), 8, 1 ); // конвертируем в HSV cvCvtColor( src, hsv, CV_BGR2HSV ); // разбиваем на каналы cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );
Т.е. сначала просто создаются 4 изображения: одно для хранения изображения в формате HSV и три для последующего разделения изображения на отдельные каналы H, S и V.
Ниже приводится код полезной утилиты, которая может быть полезна для определения минимальных и максимальных значений каналов HSV для выделения объекта на изображении.
Программа преобразует изображение в формат HSV и затем используя ползунки и функцию cvInRangeS() формирует в дополнительных оконах «H range» бинарное изображение, которое получается из тех пикселей канала, значение которых больше Hmin и меньше Hmax.
Далее для всех трёх получившихся пороговых изображений выполняется операция логического И (т.е. в результирующем окне «hsv and» белыми будут только те пиксели, которые есть у всех трёх пороговых изображений).
// // конвертирует изображение в HSV // и позволяет подобрать параметры // Hmin, Hmax, Smin, Smax, Vmin, Vmax // для выделения нужного объекта // // robocraft.ru // #include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h> IplImage* image = 0; IplImage* dst = 0; // для хранения каналов HSV IplImage* hsv = 0; IplImage* h_plane = 0; IplImage* s_plane = 0; IplImage* v_plane = 0; // для хранения каналов HSV после преобразования IplImage* h_range = 0; IplImage* s_range = 0; IplImage* v_range = 0; // для хранения суммарной картинки IplImage* hsv_and = 0; int Hmin = 0; int Hmax = 256; int Smin = 0; int Smax = 256; int Vmin = 0; int Vmax = 256; int HSVmax = 256; // // функции-обработчики ползунков // void myTrackbarHmin(int pos) { Hmin = pos; cvInRangeS(h_plane, cvScalar(Hmin), cvScalar(Hmax), h_range); } void myTrackbarHmax(int pos) { Hmax = pos; cvInRangeS(h_plane, cvScalar(Hmin), cvScalar(Hmax), h_range); } void myTrackbarSmin(int pos) { Smin = pos; cvInRangeS(s_plane, cvScalar(Smin), cvScalar(Smax), s_range); } void myTrackbarSmax(int pos) { Smax = pos; cvInRangeS(s_plane, cvScalar(Smin), cvScalar(Smax), s_range); } void myTrackbarVmin(int pos) { Vmin = pos; cvInRangeS(v_plane, cvScalar(Vmin), cvScalar(Vmax), v_range); } void myTrackbarVmax(int pos) { Vmax = pos; cvInRangeS(v_plane, cvScalar(Vmin), cvScalar(Vmax), v_range); } int main(int argc, char* argv[]) { // имя картинки задаётся первым параметром char* filename = argc == 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename,1); printf("[i] image: %s\n", filename); assert( image != 0 ); // создаём картинки hsv = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 3 ); h_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); s_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); v_plane = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); h_range = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); s_range = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); v_range = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); hsv_and = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 ); // конвертируем в HSV cvCvtColor( image, hsv, CV_BGR2HSV ); // разбиваем на отельные каналы cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 ); // // определяем минимальное и максимальное значение // у каналов HSV double framemin=0; double framemax=0; cvMinMaxLoc(h_plane, &framemin, &framemax); printf("[H] %f x %f\n", framemin, framemax ); Hmin = framemin; Hmax = framemax; cvMinMaxLoc(s_plane, &framemin, &framemax); printf("[S] %f x %f\n", framemin, framemax ); Smin = framemin; Smax = framemax; cvMinMaxLoc(v_plane, &framemin, &framemax); printf("[V] %f x %f\n", framemin, framemax ); Vmin = framemin; Vmax = framemax; // окна для отображения картинки cvNamedWindow("original",CV_WINDOW_AUTOSIZE); cvNamedWindow("H",CV_WINDOW_AUTOSIZE); cvNamedWindow("S",CV_WINDOW_AUTOSIZE); cvNamedWindow("V",CV_WINDOW_AUTOSIZE); cvNamedWindow("H range",CV_WINDOW_AUTOSIZE); cvNamedWindow("S range",CV_WINDOW_AUTOSIZE); cvNamedWindow("V range",CV_WINDOW_AUTOSIZE); cvNamedWindow("hsv and",CV_WINDOW_AUTOSIZE); cvCreateTrackbar("Hmin", "H range", &Hmin, HSVmax, myTrackbarHmin); cvCreateTrackbar("Hmax", "H range", &Hmax, HSVmax, myTrackbarHmax); cvCreateTrackbar("Smin", "S range", &Smin, HSVmax, myTrackbarSmin); cvCreateTrackbar("Smax", "S range", &Smax, HSVmax, myTrackbarSmax); cvCreateTrackbar("Vmin", "V range", &Vmin, HSVmax, myTrackbarVmin); cvCreateTrackbar("Vmax", "V range", &Vmax, HSVmax, myTrackbarVmax); // // разместим окна по рабочему столу // if(image->width <1920/4 && image->height<1080/2){ cvMoveWindow("original", 0, 0); cvMoveWindow("H", image->width+10, 0); cvMoveWindow("S", (image->width+10)*2, 0); cvMoveWindow("V", (image->width+10)*3, 0); cvMoveWindow("hsv and", 0, image->height+30); cvMoveWindow("H range", image->width+10, image->height+30); cvMoveWindow("S range", (image->width+10)*2, image->height+30); cvMoveWindow("V range", (image->width+10)*3, image->height+30); } while(true){ // показываем картинку cvShowImage("original",image); cvShowImage( "H", h_plane ); cvShowImage( "S", s_plane ); cvShowImage( "V", v_plane ); cvShowImage( "H range", h_range ); cvShowImage( "S range", s_range ); cvShowImage( "V range", v_range ); // складываем cvAnd(h_range, s_range, hsv_and); cvAnd(hsv_and, v_range, hsv_and); cvShowImage( "hsv and", hsv_and ); char c = cvWaitKey(33); if (c == 27) { // если нажата ESC - выходим break; } } printf("\n[i] Results:\n" ); printf("[H] %d x %d\n", Hmin, Hmax ); printf("[S] %d x %d\n", Smin, Smax ); printf("[V] %d x %d\n", Vmin, Vmax ); // освобождаем ресурсы cvReleaseImage(&image); cvReleaseImage(&hsv); cvReleaseImage(&h_plane); cvReleaseImage(&s_plane); cvReleaseImage(&v_plane); cvReleaseImage(&h_range); cvReleaseImage(&s_range); cvReleaseImage(&v_range); cvReleaseImage(&hsv_and); // удаляем окна cvDestroyAllWindows(); return 0; }
примеры работы:
,а вот пример поиска знаменитой улыбки Чеширского кота:
и, наконец, пример выделения пятна от лазерной указки:
Большинство функций знакомы по предыдущему шагу — осталось рассмотреть только функцию:
CVAPI(void) cvCvtColor( const CvArr* src, CvArr* dst, int code );
— конвертирует изображение из одного цветового пространства в другое.
src — исходное изображение
dst — получаемое изображение
code — параметр, указывающий тип конвертации:
#define CV_BGR2BGRA 0 #define CV_RGB2RGBA CV_BGR2BGRA #define CV_BGRA2BGR 1 #define CV_RGBA2RGB CV_BGRA2BGR #define CV_BGR2RGBA 2 #define CV_RGB2BGRA CV_BGR2RGBA #define CV_RGBA2BGR 3 #define CV_BGRA2RGB CV_RGBA2BGR #define CV_BGR2RGB 4 #define CV_RGB2BGR CV_BGR2RGB #define CV_BGRA2RGBA 5 #define CV_RGBA2BGRA CV_BGRA2RGBA #define CV_BGR2GRAY 6 #define CV_RGB2GRAY 7 #define CV_GRAY2BGR 8 #define CV_GRAY2RGB CV_GRAY2BGR #define CV_GRAY2BGRA 9 #define CV_GRAY2RGBA CV_GRAY2BGRA #define CV_BGRA2GRAY 10 #define CV_RGBA2GRAY 11 #define CV_BGR2BGR565 12 #define CV_RGB2BGR565 13 #define CV_BGR5652BGR 14 #define CV_BGR5652RGB 15 #define CV_BGRA2BGR565 16 #define CV_RGBA2BGR565 17 #define CV_BGR5652BGRA 18 #define CV_BGR5652RGBA 19 #define CV_GRAY2BGR565 20 #define CV_BGR5652GRAY 21 #define CV_BGR2BGR555 22 #define CV_RGB2BGR555 23 #define CV_BGR5552BGR 24 #define CV_BGR5552RGB 25 #define CV_BGRA2BGR555 26 #define CV_RGBA2BGR555 27 #define CV_BGR5552BGRA 28 #define CV_BGR5552RGBA 29 #define CV_GRAY2BGR555 30 #define CV_BGR5552GRAY 31 #define CV_BGR2XYZ 32 #define CV_RGB2XYZ 33 #define CV_XYZ2BGR 34 #define CV_XYZ2RGB 35 #define CV_BGR2YCrCb 36 #define CV_RGB2YCrCb 37 #define CV_YCrCb2BGR 38 #define CV_YCrCb2RGB 39 #define CV_BGR2HSV 40 #define CV_RGB2HSV 41 #define CV_BGR2Lab 44 #define CV_RGB2Lab 45 #define CV_BayerBG2BGR 46 #define CV_BayerGB2BGR 47 #define CV_BayerRG2BGR 48 #define CV_BayerGR2BGR 49 #define CV_BayerBG2RGB CV_BayerRG2BGR #define CV_BayerGB2RGB CV_BayerGR2BGR #define CV_BayerRG2RGB CV_BayerBG2BGR #define CV_BayerGR2RGB CV_BayerGB2BGR #define CV_BGR2Luv 50 #define CV_RGB2Luv 51 #define CV_BGR2HLS 52 #define CV_RGB2HLS 53 #define CV_HSV2BGR 54 #define CV_HSV2RGB 55 #define CV_Lab2BGR 56 #define CV_Lab2RGB 57 #define CV_Luv2BGR 58 #define CV_Luv2RGB 59 #define CV_HLS2BGR 60 #define CV_HLS2RGB 61 #define CV_COLORCVT_MAX 100
Замечательно! Теперь используя более привычные параметры можно выделять различные объекты на изображении.
Наглядный пример — это детектирование кожи человека на фотографиях 🙂
Например, для детектированя наготы 😉
См. статью: Популярное изложение алгоритма распознавания наготы на цифровых фотографиях
в OpenCV уже есть класс,
CvAdaptiveSkinDetector
в 2.0 и 2.1 он объявлен в cvaux.hpp,
а а 2.2 в modules\contrib\include\opencv2\contrib\contrib.hpp
см. пример
samples\c\adaptiveskindetector.cpp
реализация класса находится в:
OpenCV-2.2.0\modules\contrib\src\adaptiveskindetector.cpp
Если вы его откроете, то обнаружите, что детектирование кожи проводится в HSV-пространстве с параметрами:
H 3-33
V 15-250
// // пример использования CvAdaptiveSkinDetector // // robocraft.ru // #include <cv.h> #include <highgui.h> #include <cvaux.h> // для CvAdaptiveSkinDetector #include <stdlib.h> #include <stdio.h> int main(int argc, char* argv[]) { IplImage* image=0, *dst=0, *mask=0; // имя картинки задаётся первым параметром char* filename = argc >= 2 ? argv[1] : "Image0.jpg"; // получаем картинку image = cvLoadImage(filename, 1); printf("[i] image: %s\n", filename); assert( image != 0 ); // покажем изображение cvNamedWindow( "original"); cvShowImage( "original", image ); // картинка для хранения изображения dst = cvCloneImage(image); // детектор кожи CvAdaptiveSkinDetector filter(1, CvAdaptiveSkinDetector::MORPHING_METHOD_ERODE); // MORPHING_METHOD_ERODE_DILATE // картинка для хранения результата (маски) mask = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1); // обработка filter.process(image, mask); // покажем маску cvNamedWindow( "mask"); cvShowImage( "mask", mask); // пробегаемся по всем пикселям изображения // и увеличиваем у пикселей картинки, где установлена маска // зелёную компоненту до максимума for( int y=0; yheight; y++ ) { uchar* ptr = (uchar*) (dst->imageData + y * dst->widthStep); // изображение uchar* ptrM = (uchar*) (mask->imageData + y * mask->widthStep); // маска for( int x=0; x width; x++ ) { if(ptrM[x]){ // маска установлена // 3 канала //ptr[3*x] = ; // B ptr[3*x+1] = 255; // G //ptr[3*x+2] = ; // R } } } // покажем картинку cvNamedWindow( "dst"); cvShowImage( "dst", dst ); // ждём нажатия клавиши cvWaitKey(0); // освобождаем ресурсы cvReleaseImage(& image); cvReleaseImage(&dst); cvReleaseImage(&mask); // удаляем окна cvDestroyAllWindows(); return 0; }
скачать иcходник (23-CvAdaptiveSkinDetector.cpp)
результат:
UPD 2012-11-17
Для получения координат полученного объекта, нужно, всего-лишь, найти центр масс фигуры. Для этого, обходим все пиксели картинки и для ненулевых пикселей складываем координаты и подсчитываем их количество.
Пример:
// // находим центр масс // int Xc = 0; int Yc = 0; int counter = 0; // счётчик числа белых пикселей // пробегаемся по пикселям изображения for(y=0; yheight; y++) { uchar* ptr = (uchar*) (result->imageData + y * result->widthStep); for(x=0; x width; x++) { if( ptr[x]>0 ) { Xc += x; Yc += y; counter++; } } } if(counter!=0) { center.x = float(Xc)/counter; center.y = float(Yc)/counter; }
далее: 24. Работа с камерой через библиотеку videoInput.
Ссылки
http://ru.wikipedia.org/wiki/Цветовая_модель
http://ru.wikipedia.org/wiki/HSV_(цветовая_модель)
Популярное изложение алгоритма распознавания наготы на цифровых фотографиях
С Наступающим!
24 комментария на «“23. OpenCV шаг за шагом. Поиск объекта по цвету. Цветовое пространство HSV”»
Доброго времени суток!pastebin.com/gxV6sPab
Попробовал приспособить данный код под захват изображения с веб-камеры и столкнулся со следующей проблемой: в окнах X_range и hsv_and при запуске из под VS 2010 серо-черные вертикальные полоски, при запуске.ехе просто черный экран и белая полоска, смахивающая на шум. Хотелось бы узнать, это настолько сильное влияние оказывают шумы на видео или это все же технические проблемы?
Код прилагаю, спасибо заранее )
С Наступившим!
23-hsv-camera.cpp
1. у вас должно показывать целых 8 картинок 🙂 оригинальную то картинку показывает?
2. мой код писался для обработки одной картинки — поэтому освобождение ресурсов делается в самом конце программы — в вашем случае у Вас идут просто нереальные утечки памяти — в конце цикла нужно удалять все картинки, которые в нём же создаются.
Но если внести удаление картинок в цикл, то ползунки работать не будут — поэтому лучше вынести из цикла создание картинок — это и по производительности получше — размер кадра ведь остаётся постоянным — поэтому можно создать все картинки всего один раз, а далее просто копировать в них новые данные 🙂
Ну и чтобы заставить работать ползунки — пороговое преобразование нужно из функций ползунков внести в код цикла.
ну и собственно код:
Благодарю за обстоятельный и скорый ответ)Оригинал и плейны показывало адекватно, а вот память ело да, как от нечего делать. Буду дальше изучать и допиливать код)
Я не совсем понимаю, как именно работает выделение красного пятна на детекторе луча, например.
Вы не могли бы пояснить более развернуто?
И можно ли где-то прочитать про фильтры: какие они есть, как применяются?
Спасибо 🙂
т.е. как выделяется улыбка Чеширского кота вам ясно, а лазерный луч — нет? 🙂
Поиск ведётся в цветовом пространстве HSV: для каждой плоскости мы задаём свой диапазон значений, в котором и выбираем подходящие пиксели плоскостей, а потом складываем плоскости через логическое И. Т.е. на получившейся бинарной картинке белым цветом будет выделен наш искомый объект.
Можно реализовать такой поиск самостоятельно — обходя пиксели слоёв и проверяя, что они лежат в нужных пределах:
Диапазон значений можно подобрать, используя вышеприведённую утилиту, и затем использовать для нахождения данного объекта на видео или других схожих картинках.
Добрый день
При компиляции в убунту 11:
user@Admin:~/testCV$ make
g++ -I/usr/local/include/opencv -L/usr/local/lib -o test.o test.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui
test.cpp: In function ‘int main(int, char**)’:
/tmp/ccSPBM74.o: In function `main’:
test.cpp:(.text+0xcb): undefined reference to `CvAdaptiveSkinDetector::CvAdaptiveSkinDetector(int, int)’
test.cpp:(.text+0x107): undefined reference to `CvAdaptiveSkinDetector::process(_IplImage*, _IplImage*)’
test.cpp:(.text+0x237): undefined reference to `CvAdaptiveSkinDetector::~CvAdaptiveSkinDetector()’
test.cpp:(.text+0x255): undefined reference to `CvAdaptiveSkinDetector::~CvAdaptiveSkinDetector()’
collect2: ld returned 1 exit status
make: *** [test] Ошибка 1
что делать? спасибо.
Добрый!
давайте посмотрим ошибку — её возвращает линкер и он говорит,
что не может найти реализацию методов. Значит, вы просто забыли указать необходимый
lib-файл библиотеки.
В статье я специально указал, что:
Попробуйте добавить к параметрам сборки:
Успехов!
Доброго времени суток!
Есть ли какой-либо метод конвертации цвета, как параметра рисования фигур, в другое цветовое пространство?
Хотелось бы что-нибудь вида
convert_HSV_TO_RGB(cvScalar(15,255,255)).
Просто встает вопрос с выделением объектов рамочками разных цветов, а вбивать руками 20 цветов в RGB не хочется. Да и добавлять потом руками двадцать первый — тоже.
Спасибо огромное за пример!
Скажите пожалуйста, как можно получить координаты распознанной точки (от лазерной указки)?
т.к. объект на картинке один, то можно поступить просто — найти его центр масс.
пример добавил в конец статьи.
спасибо большое )
я попробовал сделать немного другим способом — с использованием функций cvInRangeS и cvHoughCircles. но, увы, у меня не вышло вывести координаты 🙁
посмотрите, пожалуйста, мой код и, если сможете, подскажите как:
#include «stdafx.h»
#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>
IplImage* frame=0; // картинка, которую я получаю с видеокамеры
IplImage* new_frame = 0;
int main(int argc, char* argv[])
{
CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY);
assert( capture );
double width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
double height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
printf("[i] %.0f x %.0f\n", width, height );
CvScalar min = cvScalar(150, 84, 130, 0);
CvScalar max = cvScalar(358, 256, 255, 0);
CvMemStorage* storage = cvCreateMemStorage(0);
cvNamedWindow(«capture», CV_WINDOW_AUTOSIZE);
cvNamedWindow(«MyPoint»,CV_WINDOW_AUTOSIZE);
while(true)
{
frame = cvQueryFrame( capture );
new_frame = cvCreateImage( cvSize(frame->width, frame->height), IPL_DEPTH_8U, 1);
cvInRangeS(frame, min, max, new_frame);
cvLine(frame, cvPoint(width/2,height), cvPoint(width/2,1), cvScalar(20, 100, 100),5);
cvShowImage(«capture», frame);
cvShowImage(«MyPoint», new_frame);
CvSeq* results = cvHoughCircles(new_frame, storage, CV_HOUGH_GRADIENT, 2, new_frame->width/10);
for( int i = 0; i < results->total; i++ )
{
float* p = (float*) cvGetSeqElem( results, i );
CvPoint pt = cvPoint( cvRound( p[0] ), cvRound( p[1] )); // по идее это центр круга
cvCircle(new_frame,pt,cvRound( p[2] ),CV_RGB(0xff,0xff,0xff));
printf(«X position = %d Y position = %d», pt.x, pt.y); // ничего не выводится (
}
char c = cvWaitKey(33);
if (c == 27)
{
break;
}
}
cvReleaseCapture( &capture );
cvDestroyWindow(«capture»);
return 0;
}
хотя бы подскажите в какую сторону копать )
Доброго времени суток!
У меня возникла такая проблема. Использовал ваш алгоритм для нахождение центра масс. По Y координаты находятся нормально, а вот с Х проблемы: программа выдает какие то странные значения.
#include «stdafx.h»
#include «highgui.h»
#include «cv.h»
#include «highgui.h»
#include «math.h»
int _tmain(int argc, _TCHAR* argv[])
{
IplImage* img = cvLoadImage(«E://result.jpg»);
cvNamedWindow(«Screenshot», CV_WINDOW_AUTOSIZE);
cvShowImage(«Screenshot», img);
cvMoveWindow(«Screenshot», 0, 0);
printf(«height = %d width = %d », img->height,img->width);
int Xc = 0;
int Yc = 0;
int centerx = 0;
int centery = 0;
int counter = 0;
for(int y=0; y<img->height; y++)
{
int* ptr = (int*) (img->imageData + y * img->widthStep);
for(int x=0; x<img->width; x++)
{
if( ptr[x]>0 )
{
Xc += x;
Yc += y;
counter++;
//printf(«xc = %d yc = %d », Xc,Yc);
}
}
}
if(counter!=0)
{
centerx = (Xc)/counter;
centery = (Yc)/counter;
}
printf(«X position = %d Y position = %d », centerx,centery);
cvWaitKey(0);
cvDestroyAllWindows();
return 0;
}
Добрый день,
А у меня такой вопрос, с помошью данного алгоритма я нашел выделил все интересующие меня облости на изображении, как мне подсчитать количество выделенных областей? Буду очень признателен за помощь
Например, черезнахождение контуров .
Пробовал пользоваться тем методом, получается не совсем корректное кличество из за разомкнутости некоторых контуров, сложной формы исходного контура а так же из за нахождения внутреннего внутреннего и внешнего контуров некоторые области считаются по 2 раза.
А какая функция, кстати, возвращает количество найденных контуров? а то я реализовал через простой счетчик внутри цикла обхода всех контуров?
Сижу гадаю, почему у меня не получается найти так же улыбку и коды значений часто не совпадают… И тут заметил, что оригинальная картинка в этом примере гораздо насыщеннее, чем я скачал из статьиrobocraft.ru/blog/computervision/268.html !!!
Чем отличаются CvtPixToPlane от Split?
При использовании Split результат больше подходит на тот, что приведён в статье. При использовании CtvPixToPlane H и S изображения получились одинаковыми у меня.
А нет, в Cvt не преобразованное RGB изображение оригинала подставлял просто…
Если сделать всё идентично, что CvtPixToPlane и Split сработали у меня идентично. В чём же разница?
А, примерно понятно. Вот декомпилированный участок OpenCVSharp для функции CvtPixToPlane:
public void CvtPixToPlane(CvArr dst0, CvArr dst1, CvArr dst2, CvArr dst3)
{
Cv.Split(this, dst0, dst1, dst2, dst3);
}
🙂
в общем после долгих мучений добился чтобы показывал координаты, единственное не понятно откуда он начинает считать толи справа на лево сверху вниз, толи как, мож кто разберется, было бы замечательно,
Здравствуйте. Понимаю что тема старая, но…
В общем в последней версии OpenCV я не нашел метода: cvCvtPixToPlane
Подскажите если не трудно, чем его можно заменить, нужна реализация вашего:
Ага, пока ждал ответа сам разобрался, а выглядеть будет примерно так:
(код под OpenCVSharp — C# реализацию…)
Теперь встал вопрос в другом…
При попытке сохранения, или вывода окна с h_plane, s_plane, v_plane программа вываливается с ошибкой:
Source image must have 1, 3 or 4 channels
То-есть, изображение должно иметь 1, 3, или 4 канала.
Проверяю свойство h_plane.Channels(), получаю кол-во каналов = 2
Как то я запутался, а что делать что-бы получить 1 канал, почему Split возвращает изображение с 2 каналами?