User Tools

Site Tools


color_detecting

Color Detecting using OpenCV

Author: Myong Geon Kim Email: [email protected]
Date: Last modified on <06/20/19>
Keywords: Tutorial, how to, step-by-step, opencv


This tutorial is for whom will continue DASL Intern Gantry project. Visual studio and OpenCV library are required for this tutorial.

Motivation and Audience



Readers of this tutorial assumes the reader has the following background and interests:


* Basic background of CPP * Basic background of using OpenCV library : How to Use OpenCV library.

The rest of this tutorial is presented as follows:



Code



#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	int range_count = 0;

	Scalar red(0, 0, 255);
	Scalar blue(255, 0, 0);
	Scalar yellow(0, 255, 255);

	Scalar magenta(255, 0, 255);


	Mat rgb_color = Mat(1, 1, CV_8UC3, red);
	Mat hsv_color;

	cvtColor(rgb_color, hsv_color, COLOR_BGR2HSV);


	int hue = (int)hsv_color.at<Vec3b>(0, 0)[0];
	int saturation = (int)hsv_color.at<Vec3b>(0, 0)[1];
	int value = (int)hsv_color.at<Vec3b>(0, 0)[2];


	cout << "hue = " << hue << endl;
	cout << "saturation = " << saturation << endl;
	cout << "value = " << value << endl;


	int low_hue = hue - 10;
	int high_hue = hue + 10;

	int low_hue1 = 0, low_hue2 = 0;
	int high_hue1 = 0, high_hue2 = 0;

	if (low_hue < 10) {
		range_count = 2;

		high_hue1 = 180;
		low_hue1 = low_hue + 180;
		high_hue2 = high_hue;
		low_hue2 = 0;
	}
	else if (high_hue > 170) {
		range_count = 2;

		high_hue1 = low_hue;
		low_hue1 = 180;
		high_hue2 = high_hue - 180;
		low_hue2 = 0;
	}
	else {
		range_count = 1;

		low_hue1 = low_hue;
		high_hue1 = high_hue;
	}


	cout << low_hue1 << "  " << high_hue1 << endl;
	cout << low_hue2 << "  " << high_hue2 << endl;


	VideoCapture cap(1);
	Mat img_frame, img_hsv;


	if (!cap.isOpened()) {
		cerr << "ERROR! Unable to open camera\n";
		return -1;
	}


	for (;;)
	{
		// wait for a new frame from camera and store it into 'frame'
		cap.read(img_frame);

		// check if we succeeded
		if (img_frame.empty()) {
			cerr << "ERROR! blank frame grabbed\n";
			break;
		}


		//HSV로 변환
		cvtColor(img_frame, img_hsv, COLOR_BGR2HSV);


		//지정한 HSV 범위를 이용하여 영상을 이진화
		Mat img_mask1, img_mask2;
		inRange(img_hsv, Scalar(low_hue1, 50, 50), Scalar(high_hue1, 255, 255), img_mask1);
		if (range_count == 2) {
			inRange(img_hsv, Scalar(low_hue2, 50, 50), Scalar(high_hue2, 255, 255), img_mask2);
			img_mask1 |= img_mask2;
		}


		//morphological opening 작은 점들을 제거 
		erode(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		dilate(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));


		//morphological closing 영역의 구멍 메우기 
		dilate(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));
		erode(img_mask1, img_mask1, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)));


		//라벨링 
		Mat img_labels, stats, centroids;
		int numOfLables = connectedComponentsWithStats(img_mask1, img_labels,
			stats, centroids, 8, CV_32S);


		//영역박스 그리기
		int max = -1, idx = 0;
		for (int j = 1; j < numOfLables; j++) {
			int area = stats.at<int>(j, CC_STAT_AREA);
			if (max < area)
			{
				max = area;
				idx = j;
			}
		}


		int left = stats.at<int>(idx, CC_STAT_LEFT);
		int top = stats.at<int>(idx, CC_STAT_TOP);
		int width = stats.at<int>(idx, CC_STAT_WIDTH);
		int height = stats.at<int>(idx, CC_STAT_HEIGHT);

		int x = left + width / 2;
		int y = top + height / 2;

		int original_x = centroids.at<double>(0, 0); //중심좌표
	    int original_y = centroids.at<double>(0, 1);


		circle(img_frame, Point(x, y), width / 2, Scalar(0, 0, 255), 1); //make a circle around object
	

		cout << "Ball position X = " << x   // x position of center point of circle
			<< ",\tY = " << y       // y position of center point of circle
			<< ",\tRadius = " << width/2 
			<<"center x =" << original_x
			<<"center y=" << original_y
			<< "\n";
	


		imshow("이진화 영상", img_mask1);
		imshow("원본 영상", img_frame);


		if (waitKey(5) >= 0)
			break;
	}

	





	return 0;
}



Explanation



Above project is made by three big parts.
First, detect color by setting up curtain hue value.
Second, clarify detected color by change the image to binary image.
Last, labeling that color.

Detecting and clarifying was hard for me to understand how it works.

In this tutorial, I will focus on drawing a circle around the color and finding its position.

In this part,

int left = stats.at<int>(idx, CC_STAT_LEFT);
		int top = stats.at<int>(idx, CC_STAT_TOP);
		int width = stats.at<int>(idx, CC_STAT_WIDTH);
		int height = stats.at<int>(idx, CC_STAT_HEIGHT);


“stats.at” function helps to find left,top,width,height of color
which means we can find radius and center of circle.

int original_x = centroids.at<double>(0, 0); 
int original_y = centroids.at<double>(0, 1);


This function let us know the origin point of images.

circle(img_frame, Point(x, y), width / 2, Scalar(0, 0, 255), 1); //make a circle around object


This function draw a circle around the color.

cout << "Ball position X = " << x   // x position of center point of circle
			<< ",\tY = " << y       // y position of center point of circle
			<< ",\tRadius = " << width/2 
			<<"center x =" << original_x
			<<"center y=" << original_y
			<< "\n";


This will show current position and radius of circle constantly in the cmd window.

Final Words

For questions, clarifications, etc, Email: [email protected]

color_detecting.txt · Last modified: 2019/06/21 05:58 by myeonggeonkim