User Tools

Site Tools


opencv_tutorials_t3

Differences

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

Link to this comparison view

Next revision
Previous revision
opencv_tutorials_t3 [2016/06/06 14:05] – created joaomatosopencv_tutorials_t3 [2017/05/13 17:20] (current) – [Detecting Circles on Webcam] acater
Line 1: Line 1:
-Tutorial 3+===== Tutorial 3 ===== 
 + 
 + On this tutorial you will learn how to detect circles on an image and video using a simple OpenCV Function and show the center location on the screen. 
 + 
 + I recommend you to type the code on your own to get familiarized with the program language. If you have trouble , the original code is attached bellow ( Running on Visual Studio 2015 + OpenCV 3.1 ) * Check the installation guide to make sure that you linked all the OpenCV modules to your Visual Studio. 
 + 
 +{{::detecting_circle_image.rar|Detecting Circles on Image}} 
 + 
 +{{::detecting_circles_on_webcam.rar|Detecting Circles on Webcam}} 
 + 
 + 
 + 
 + 
 +---- 
 + 
 +===== Detecting Circles in Image ===== 
 + 
 +{{ ::circledetec.jpg?direct |}} 
 + 
 +<Code:c++ linenums:1> 
 + 
 +#include <sstream> 
 +#include <string> 
 +#include <iostream> 
 +#include <opencv/highgui.h> 
 +#include <opencv/cv.h> 
 +#include <opencv2/core/core.hpp> 
 +#include <opencv2/highgui/highgui.hpp> 
 +#include <opencv2/imgproc/imgproc.hpp> 
 + 
 +using namespace cv; 
 +using namespace std; 
 + 
 + 
 +//Function to convert an integer number to a string. 
 +String intToString(int number) 
 +
 + stringstream ss; 
 + ss << number; 
 + return ss.str(); 
 +
 + 
 + 
 +int main() 
 +
 + //Variables to write the radius and center position on the screen. 
 + string radiusStr; 
 + string xcenterStr; 
 + string ycenterStr; 
 + int Rvalue; 
 + int Xvalue; 
 + int Yvalue; 
 + 
 + // Open the original colored image and convert to a grayscaled image 
 + Mat coloredimage; 
 + Mat grayimage; 
 + 
 + 
 + 
 + //vector to store the center value ( x and y coordinates ) and the radius of each detected circle 
 + vector<Vec3f> circles; 
 + 
 + //Open and resize the colored image. 
 + coloredimage = imread("C:/Users/jcunhamatos/Desktop/circles.jpg", 1); 
 + resize(coloredimage, coloredimage, Size(640, 480)); 
 + imshow("Original Image", coloredimage); 
 + 
 + //convert colored image to gray scale 
 + cvtColor(coloredimage, grayimage, CV_BGR2GRAY); 
 + 
 + // Apply blur to Reduce the noise to avoid false detections. 
 + GaussianBlur(grayimage, grayimage, Size(9, 9), 2, 2); 
 + 
 + // Apply the Hough Transform to find the circles (use the gray scale image as input) 
 + //Arguments: 1: input image( grayscaled ) . 2: vector to tore the circle parameters .3: detection method, 
 + // 4: inverse ratio of resolution . 5 minimum distance between detected centers. 6: upper threshold for the internal canny edge detector 
 + //7: threshold for center detection . 8: Minimum radius to be detected (0=unknown) . 9: maximum radius to be detected 
 + 
 + 
 + HoughCircles(grayimage, circles, CV_HOUGH_GRADIENT, 1, 30, 200, 50, 0, 0); 
 + 
 + 
 + // Draw the circles detected 
 + for (size_t i = 0; i < circles.size(); i++) 
 +
 + //Get the informations from the circles vector generated by the function HoughCircles.  
 + //X center coordinate is circles[i][0]  , Y center coordinate is circles[i][1] , radius is circles[i][2]  
 + Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); 
 + int radius = cvRound(circles[i][2]); 
 + 
 + //Store these values into variables to be converted into string and displayed on the image 
 + Rvalue = radius; 
 + Xvalue = cvRound(circles[i][0]); 
 + Yvalue = cvRound(circles[i][1]); 
 + 
 + //DRAWING THE CENTER OF THE CIRCLE 
 + //Use the circle function to draw the center of the detected circle 
 + //Use the center coordinate and a radius of 3 to just draw a point on the center. 
 + circle(coloredimage, center, 3, Scalar(0, 255, 0), -1, 8, 0); 
 + 
 + //DRAWING THE CIRCLE CONTOUR. 
 + //Use the circle function to draw the detected circle on the image 
 + //Use the center coordinate and the radius coordinate detected by the HoughCircles function 
 + circle(coloredimage, center, radius, Scalar(0, 0, 255), 3, 8, 0); 
 + 
 + 
 + 
 + //Convert the integer Center point and radius values to string 
 + radiusStr = intToString(Rvalue); 
 + xcenterStr = intToString(Xvalue); 
 + ycenterStr = intToString(Yvalue); 
 + 
 + //Display on the colored image the center and radius values. 
 + putText(coloredimage, "(" + xcenterStr + "," + ycenterStr + ")", Point(Xvalue, Yvalue - 20), 1, 1, Scalar(0, 255, 0), 2); 
 + 
 + 
 + cout << "radius:" << radiusStr << "    Column:" << xcenterStr << "    Row:" << ycenterStr; 
 +
 + 
 + // Show your results 
 + namedWindow("Circle Detector", CV_WINDOW_AUTOSIZE); 
 + imshow("Circle Detector", coloredimage); 
 + 
 + waitKey(0); 
 + return 0; 
 +
 + 
 +</Code> 
 + 
 + 
 +---- 
 + 
 +===== Understanding the Code ===== 
 + 
 +<Code:c++ linenums:15> 
 +//Function to convert an integer number to a string. 
 +String intToString(int number) 
 +
 + stringstream ss; 
 + ss << number; 
 + return ss.str(); 
 +
 +</Code> 
 + 
 +We will need to display the center position on the screen , and in order to display a string on the image we will need to convert the X center and Y center position to strings , so it is convenient to create a simple function that will convert a given integer to string. This function will take an integer number as argument . We declare the variable ss as **"stringstream"** , then we assign the integer number to the ss variable , and finally we return a string version of the ss variable using **"return variablename.str()"** 
 + 
 + 
 +---- 
 + 
 + 
 +<Code:c++ linenums:1> 
 + 
 +int main() 
 +
 + //Variables to write the radius and center position on the screen. 
 + string radiusStr; 
 + string xcenterStr; 
 + string ycenterStr; 
 + int Rvalue; 
 + int Xvalue; 
 + int Yvalue; 
 +  
 + // Open the original colored image and convert to a grayscaled image 
 + Mat coloredimage; 
 + Mat grayimage; 
 + 
 +</Code> 
 + 
 +We start defining the variables that will be used. Strings (**"String"**)to be displayed on the image , integers (**"int"**) to store the circle properties values , and **"Mat"** to store the images. The function that we will be using it uses a gray scale version of the original image , so we need to declare a variable for it. 
 + 
 + 
 +---- 
 +<Code:c++ linenums:40> 
 + 
 +//vector to store the center value ( x and y coordinates ) and the radius of each detected circle 
 + vector<Vec3f> circles; 
 +  
 + //Open and resize the colored image. 
 + coloredimage = imread("C:/Users/jcunhamatos/Desktop/circles.jpg", 1); 
 + resize(coloredimage, coloredimage, Size(640, 480)); 
 + imshow("Original Image", coloredimage); 
 +  
 + //convert colored image to gray scale 
 + cvtColor(coloredimage, grayimage, CV_BGR2GRAY); 
 +  
 + // Apply blur to Reduce the noise to avoid false detections. 
 + GaussianBlur(grayimage, grayimage, Size(9, 9), 2, 2); 
 +  
 + // Apply the Hough Transform to find the circles (use the gray scale image as input) 
 + //Arguments: 1: input image( grayscaled ) . 2: vector to tore the circle parameters .3: detection method, 
 + // 4: inverse ratio of resolution . 5 minimum distance between detected centers. 6: upper threshold for the internal canny edge detector 
 + //7: threshold for center detection . 8: Minimum radius to be detected (0=unknown) . 9: maximum radius to be detected 
 +   
 + HoughCircles(grayimage, circles, CV_HOUGH_GRADIENT, 1, 30, 200, 50, 0, 0); 
 +  
 +</Code> 
 + 
 + The function that will detect the circles will need a vector to store the X center , Y center and radius values from each detected circle , so we need to declare a vector to be used on that -  **"vector<Vec3f>"** . We first open the image that we will use , resize it and open an window to display the original image ( to be compared with the other window that we will open to display the image with the detected circles). As said , the function to detect circles uses a gray scale version of the original image , so we use the **"cvtColor"** function to create a gray scale version. We can apply **"GaussinBlur"** to our gray scale image before using the function to detect the circles in order to avoid false detections (is good to always apply blur before). 
 + 
 + We will apply Hough Transform to find the circles. OpenCV has a function that already does all the procedures - **"HoughCircles"** . The first argument is the source image , and the second argument is the vector that we created to store the circle properties. The other arguments are described in the code. 
 + 
 + 
 +---- 
 +<Code:c++ linenums:63> 
 + 
 +// Draw the circles detected 
 + for (size_t i = 0; i < circles.size(); i++) 
 +
 + //Get the informations from the circles vector generated by the function HoughCircles.  
 + //Column coordinate is circles[i][0]  , Row coordinate is circles[i][1] , radius is circles[i][2]  
 + Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); 
 + int radius = cvRound(circles[i][2]); 
 +  
 + //Store these values into variables to be converted into string and displayed on the image 
 +                // X will be the column , Y will be the row. 
 + Rvalue = radius; 
 + Xvalue = cvRound(circles[i][0]); 
 + Yvalue = cvRound(circles[i][1]); 
 +  
 + //DRAWING THE CENTER OF THE CIRCLE 
 + //Use the circle function to draw the center of the detected circle 
 + //Use the center coordinate and a radius of 3 to just draw a point on the center. 
 + circle(coloredimage, center, 3, Scalar(0, 255, 0), -1, 8, 0); 
 +  
 + //DRAWING THE CIRCLE CONTOUR. 
 + //Use the circle function to draw the detected circle on the image 
 + //Use the center coordinate and the radius coordinate detected by the HoughCircles function 
 + circle(coloredimage, center, radius, Scalar(0, 0, 255), 3, 8, 0); 
 +   
 +  
 + 
 +</Code>  
 + 
 + The **"HoughCircles"** will try to detect all the circles shapes on the given image , so it can be more than one detected circle. To display all the circles we use a for loop , starting from 1 and ending on the circles vector size. We will access the Y (row) and the X(column) values in the circle variable , so we define a point called center to store these values.We assign  **"circles[i][0]"** to the column value , **"circles[i][1]"** to the row value and **"cvRound()"** will round these values to the next integer. The radius is defined by **"circles[i][2]"** and is assigned to the Rvalue variable. Is convenient to create two variables to store the point (x,y)(column,row) to be converted into string , so we assign the the row value to Xvalue and the column value to Yvalue. 
 + 
 + To draw a circle on an image we use the **"circle"** function. That will draw a circle on the first argument image , centered on the second argument , with radius value defined on the third argument , color defined on fourth argument. To display the center of the circle , we just draw a small circle with radius 3 pixels on the center position ( we already assigned the row and column values to the center point). To Draw the circle contour , we draw based on the center point , but now with the radius value stored on the "radius" variable. The Scalar(B,G,R) defines the color , so using Scalar(0,255,0) is pure green , and Scalar(0,0,255) is pure red. 
 + 
 + 
 +---- 
 + 
 +<Code:c++ linenums:88> 
 + 
 +//Convert the integer Center point and radius values to string 
 + radiusStr = intToString(Rvalue); 
 + xcenterStr = intToString(Xvalue); 
 + ycenterStr = intToString(Yvalue); 
 +  
 + //Display on the colored image the center and radius values. 
 + putText(coloredimage, "(" + xcenterStr + "," + ycenterStr + ")", Point(Xvalue, Yvalue - 20), 1, 1, Scalar(0, 255, 0), 2); 
 +  
 +  
 + cout << "radius:" << radiusStr << "    Column:" << xcenterStr << "    Row:" << ycenterStr; 
 +
 + 
 +</Code> 
 + 
 +To display the Center value on the image we use the **"putText"** function. It will put the text on the first argument image. The text to be displayed is defined on the second argument. The third argument is the point where it will be displayed. To be more visible we can draw on the X center column but on the Y center -20 pixels row ( so the center point drawn be us can be more visible ). Subtracting pixels from the column will make the text to move upward. We also display these values on the CMD window using the **"cout <<"** command. 
 + 
 + 
 +---- 
 + 
 +<Code:c++ linenums:100> 
 +// Show your results 
 + namedWindow("Circle Detector", CV_WINDOW_AUTOSIZE); 
 + imshow("Circle Detector", coloredimage); 
 +  
 + waitKey(0); 
 + return 0; 
 +
 +</Code> 
 + 
 +Now we open a window and display the image with the draw on it. We put a different name from the first window so we open two different windows to display the original image and the image with the detected circle. 
 + 
 + 
 +---- 
 + 
 +===== Detecting Circles on Webcam ===== 
 + 
 +{{ ::circle_webcam.jpg?direct |}} 
 + 
 + 
 +<Code:c++ linenums:1> 
 + 
 +#include <sstream> 
 +#include <string> 
 +#include <iostream> 
 +#include <opencv/highgui.h> 
 +#include <opencv/cv.h> 
 +#include <opencv2/core/core.hpp> 
 +#include <opencv2/highgui/highgui.hpp> 
 +#include <opencv2/imgproc/imgproc.hpp> 
 + 
 +using namespace cv; 
 +using namespace std; 
 + 
 + 
 +String intToString(int number) 
 +
 + 
 + 
 + std::stringstream ss; 
 + ss << number; 
 + return ss.str(); 
 +
 + 
 + 
 +int main() 
 +
 + //Varibles to store and show the detected circle properties 
 + string radiusStr; 
 + string xcenterStr; 
 + string ycenterStr; 
 + int Rvalue; 
 + int Xvalue; 
 + int Yvalue; 
 + 
 + //Variables to store the webcam video , and a converted version of the video 
 + Mat coloredimage; 
 + Mat grayimage; 
 + 
 + //auxiliar variable to quit the loop and end the program 
 + char key = 0; 
 + 
 + //Open the default camera 
 + VideoCapture capture(0); 
 + 
 + //Check for Failure 
 + if (!capture.isOpened()) 
 +
 + printf("Failed to open the webcam"); 
 +
 + 
 + //Set Capture device properties. 
 + 
 + capture.set(CV_CAP_PROP_FRAME_WIDTH, 640); 
 + capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480); 
 + 
 + 
 + //Loop will stop if "q" is pressed in the keyboard 
 + while (key != 'q'
 +
 + 
 + //Capture a frame of the webcam live video and store it on the image variable 
 + capture >> coloredimage; 
 + 
 + //Resize this frame and convert to gray scale 
 + cvtColor(coloredimage, grayimage, CV_BGR2GRAY); 
 + 
 + // Apply blur to Reduce the noise so we avoid false circle detection 
 + GaussianBlur(grayimage, grayimage, Size(9, 9), 2, 2); 
 + 
 + //create a vector to store the center value ( x and y coordinates ) and the radius of each detected circle 
 + vector<Vec3f> circles; 
 + 
 + 
 + // Apply the Hough Transform to find the circles (use the gray scale image as input) 
 + //Arguments: 1: input image( grayscaled ) . 2: vector to tore the circle parameters .3: detection method, 
 + // 4: inverse ratio of resolution . 5 minimum distance between detected centers. 6: upper threshold for the internal canny edge detector 
 + //7: threshold for center detection . 8: Minimum radius to be detected (0=unknown) . 9: maximum radius to be detected 
 + 
 + HoughCircles(grayimage, circles, CV_HOUGH_GRADIENT, 1, 30, 200, 50, 0, 0); 
 + 
 + // Draw the circles detected 
 + for (size_t i = 0; i < circles.size(); i++) 
 +
 + 
 + //Get the informations from the circles vector generated by the function HoughCircles.  
 + //Column is circles[i][0]  , Row is circles[i][1] , radius is circles[i][2]  
 + Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); 
 + int radius = cvRound(circles[i][2]); 
 + 
 + //Store these values into variables to be converted into string and displayed on the image 
 + Rvalue = radius; 
 + Xvalue = cvRound(circles[i][0]); 
 + Yvalue = cvRound(circles[i][1]); 
 + 
 + //DRAWING THE CENTER OF THE CIRCLE 
 + //Use the circle function to draw the center of the detected circle 
 + //Use the center coordinate and a radius of 3 to just draw a point on the center. 
 + circle(coloredimage, center, 3, Scalar(0, 255, 0), -1, 8, 0); 
 + 
 + //DRAWING THE CIRCLE CONTOUR. 
 + //Use the circle function to draw the detected circle on the image 
 + //Use the center coordinate and the radius coordinate detected by the HoughCircles function 
 + circle(coloredimage, center, radius, Scalar(0, 0, 255), 3, 8, 0); 
 + 
 + //Convert the integer Center point and radius values to string 
 + radiusStr = intToString(Rvalue); 
 + xcenterStr = intToString(Xvalue); 
 + ycenterStr = intToString(Yvalue); 
 + 
 + //Display on the colored image the center and radius values. 
 + putText(coloredimage, "(" + xcenterStr + "," + ycenterStr + ")", Point(Xvalue, Yvalue-20), 1, 1, Scalar(0, 255, 0), 2); 
 + 
 + //Display the values also on the cmd window 
 + cout << "center : " << center << "\nradius : " << radius << endl; 
 + 
 +
 + 
 + 
 + // Show your results 
 + namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE); 
 + imshow("Hough Circle Transform Demo", coloredimage); 
 + 
 + 
 + key = waitKey(25); 
 + 
 +
 + return 0; 
 +
 + 
 +</Code> 
 + 
 +The idea to change from an image to the webcam video is the same used on the Tutorial 1. We change the **"imread"** for the **"VideoCapture**" and change the **"resize"** for the **"capture.set"**.  We use a loop until the q key is pressed to display the frames on the window.Our colored image is set using **"capture >> coloredimage;"** and all the following procedure to detect the circle is the same from the image code ( because we will analyze frame by frame ). 
 +\\ 
 +\\ 
 +Below is a video demonstrating the first program in real time.  
 +{{youtube>doq8hqEDhY0?medium}} 
 +\\ 
 +\\Below is a video demonstrating the second program in real time. 
 +{{youtube>htymt5vIA3M?medium}}
opencv_tutorials_t3.1465247127.txt.gz · Last modified: 2016/06/06 14:05 by joaomatos