Pull to refresh

Простое обнаружение объектов по цвету

Reading time 3 min
Views 37K
Доброго времени суток.
В этом коротком посте хотел показать простой способ поиска объектов по цвету с OpenCV.

Для экспериментов использовал камеру Logitech WebCam C270


Итак начнем

Подключаем всё нужное
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdlib> // Для функции exit()

using namespace cv;
using std::cout;
using std::endl;


Объявляем переменные
char mainWindow[] = "Main";
	char trackbarWindow[] = "Trackbar";
	char thresholdWindow[] = "Threshold";
	int min = 0, max = 1000;
	int hmin = 0, smin = 0, vmin = 0,
		hmax = 255, smax = 255, vmax = 255;
	Mat frame, HSV, threshold, blurred;
	VideoCapture capture;


Создаем трэкбар для регулирования цвета
createTrackbar("H min:", trackbarWindow, &hmin, hmax);
createTrackbar("H max:", trackbarWindow, &hmax, hmax);
createTrackbar("S min:", trackbarWindow, &smin, smax);
createTrackbar("S max:", trackbarWindow, &smax, smax);
createTrackbar("V min:", trackbarWindow, &vmin, vmax);
createTrackbar("V max:", trackbarWindow, &vmax, vmax);
createTrackbar("Size min:", trackbarWindow, &min, max);
createTrackbar("Size max:", trackbarWindow, &max, max);


Открываем камеру
capture.open(1);
if(!capture.isOpened()){
	cout << "Камера не может быть открыта." << endl;
	exit(1);
}


Запускаем цикл обработки камеры
for(;;){
	capture >> frame;
	cvtColor(frame, HSV, COLOR_BGR2HSV);
	medianBlur(HSV, blurred, 21);
	inRange(blurred, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), threshold);
	for(int y = 0; y < threshold.rows; y++){
		for(int x = 0; x < threshold.cols; x++){
			int value = threshold.at<uchar>(y, x);
			if(value == 255){
				Rect rect;
				int count = floodFill(threshold, Point(x, y), Scalar(200), &rect);
				if(rect.width >= min && rect.width <= max
					&& rect.height >= min && rect.height <= max){
					rectangle(frame, rect, Scalar(255, 0, 255, 4));
			
				}
			}
		}
	}
		imshow(mainWindow, frame);
		imshow(thresholdWindow, threshold);
		if(waitKey(33) == 27) break;
}


В этом цикле сначала преобразуем кадр из RGB в HSV. После чего делаем размытие и вызываем функцию поиска цвета. Функция inRange() делает поиск по принципу «от и до», т.е. от какого до какого цвета ей выделять пиксели. Дальше обрабатываю каждый пиксель кадра, если пиксель белого цвета, заливаем его серым. Ну и функцией rectangle() выделяем объект, просто рисуя прямоугольник вокруг выделенной области.

Вот пример поиска лимона:


Полный исходный код
#include <opencv2/opencv.hpp>
#include <iostream>
#include <cstdlib>

using namespace cv;
using std::cout;
using std::endl;

int main(int argc, char **argv){
	char mainWindow[] = "Main";
	char trackbarWindow[] = "Trackbar";
	char thresholdWindow[] = "Threshold";
	int min = 0, max = 1000;
	int hmin = 0, smin = 0, vmin = 0,
		hmax = 255, smax = 255, vmax = 255;
	Mat frame, HSV, threshold, blurred;
	VideoCapture capture;
	
	//Создаем окна
	namedWindow(mainWindow, 0);
	namedWindow(trackbarWindow, 0);
	namedWindow(thresholdWindow, 0);
	
	//Создаем трэкбар
	createTrackbar("H min:", trackbarWindow, &hmin, hmax);
	createTrackbar("H max:", trackbarWindow, &hmax, hmax);
	createTrackbar("S min:", trackbarWindow, &smin, smax);
	createTrackbar("S max:", trackbarWindow, &smax, smax);
	createTrackbar("V min:", trackbarWindow, &vmin, vmax);
	createTrackbar("V max:", trackbarWindow, &vmax, vmax);
	createTrackbar("Size min:", trackbarWindow, &min, max);
	createTrackbar("Size max:", trackbarWindow, &max, max);
	
	//Открываем камеру
	capture.open(1);
	if(!capture.isOpened()){
		cout << "Камера не может быть открыта." << endl;
		exit(1);
	}
	
	//Запускаем цикл чтения с камеры
	for(;;){
		capture >> frame;
		cvtColor(frame, HSV, COLOR_BGR2HSV);
		medianBlur(HSV, blurred, 21);
		inRange(blurred, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), threshold);
		for(int y = 0; y < threshold.rows; y++){
			for(int x = 0; x < threshold.cols; x++){
				int value = threshold.at<uchar>(y, x);
				if(value == 255){
					Rect rect;
					int count = floodFill(threshold, Point(x, y), Scalar(200), &rect);
					if(rect.width >= min && rect.width <= max
						&& rect.height >= min && rect.height <= max){
						rectangle(frame, rect, Scalar(255, 0, 255, 4));
					
					}
				}
			}
		}
		imshow(mainWindow, frame);
		imshow(thresholdWindow, threshold);
		if(waitKey(33) == 27) break;
	}
	return 0;
}

Tags:
Hubs:
+32
Comments 33
Comments Comments 33

Articles