User Tools

Site Tools


color_detecting
no way to compare when less than two revisions

Differences

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


color_detecting [2019/06/21 05:58] (current) – created myeonggeonkim
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/
 + <<"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/
 + <<"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