User Tools

Site Tools


color_detecting

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

color_detecting [2019/06/21 05:58] (current)
myeonggeonkim created
Line 1: Line 1:
 +====== 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
 +\\
 +
 +{{ mgkim:​opencv_7.jpg?​800 |}}
 +\\
 +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: ​
 +\\
 +\\
 +<fc blue>  ​
 +\\
 +  * Basic background of CPP
 +  * Basic background of using OpenCV library : [[open_cv_set_up|How to Use OpenCV library]]. ​
 + \\
 +</fc>
 +\\
 +The rest of this tutorial is presented as follows:
 +  * [[color_detecting#​code|Code]]
 +  * [[color_detecting#​explanation|Explanation]]
 +  * Final Words
 +\\
 +\\
 +==== Code ====
 +\\
 +\\
 +<​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;
 +}
 +</​code>​
 +\\
 +\\
 +==== 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, 
 +\\
 +<​code>​
 +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);​
 +</​code>​
 +\\
 + "​stats.at"​ function helps to find left,​top,​width,​height of color
 +\\
 +which means we can find radius and center of circle.
 +\\
 +\\
 +<​code>​
 +int original_x = centroids.at<​double>​(0,​ 0); 
 +int original_y = centroids.at<​double>​(0,​ 1);
 +</​code>​
 +\\
 +This function let us know the origin point of images.
 +\\
 +<​code>​
 +circle(img_frame,​ Point(x, y), width / 2, Scalar(0, 0, 255), 1); //make a circle around object
 +</​code>​
 +\\
 +This function draw a circle around the color.
 +\\
 +<​code>​
 +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";​
 +
 +</​code>​
 +\\
 +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