1 | #include "opencv2/imgproc/imgproc.hpp"
|
2 | #include "opencv2/highgui/highgui.hpp"
|
3 |
|
4 | #include <stdio.h>
|
5 |
|
6 | using namespace cv;
|
7 |
|
8 | // whether to create a window to display webcam feed
|
9 | #define DISPLAY_RESULT true
|
10 |
|
11 | #define MIN_HUE 0
|
12 | #define MAX_HUE 30
|
13 |
|
14 | #define MIN_SAT 160
|
15 | #define MIN_VAL 160
|
16 |
|
17 | int main(int argc, char** argv) {
|
18 | int c;
|
19 | bool stopProgram = false;
|
20 | Scalar minHSV = cvScalar(MIN_HUE, MIN_SAT, MIN_VAL);
|
21 | Scalar maxHSV = cvScalar(MAX_HUE, 255, 255);
|
22 |
|
23 | //create capture device, select first available webcam
|
24 | VideoCapture captureDevice(0);
|
25 | if (!captureDevice.isOpened()) {
|
26 | printf("\n\rError opening webcam!");
|
27 | return -1;
|
28 | }
|
29 |
|
30 | if (DISPLAY_RESULT) {
|
31 | //create window
|
32 | namedWindow("main", 1);
|
33 | namedWindow("bin", 1);
|
34 | }
|
35 |
|
36 | //main loop
|
37 | while (!stopProgram) {
|
38 | Mat frame, hsvImg, binaryImage, denoisedImage, contourImage;
|
39 |
|
40 | //read in data
|
41 | captureDevice >> frame;
|
42 |
|
43 | // Convert to hsv
|
44 | cvtColor(frame, hsvImg, CV_BGR2HSV);
|
45 |
|
46 | // Threshhold image
|
47 | inRange(hsvImg, minHSV, maxHSV, binaryImage);
|
48 |
|
49 | // Perform opening to denoise
|
50 | Mat strel = getStructuringElement(MORPH_CROSS, Size(3, 3));
|
51 | morphologyEx(binaryImage, denoisedImage, MORPH_OPEN, strel,
|
52 | Point(-1, -1), 1);
|
53 |
|
54 | // variables to store results
|
55 | vector<vector<Point> > contours;
|
56 | vector<Vec4i> hierarchy;
|
57 | vector<Point> contours_poly;
|
58 | Point2f center, maxCenter;
|
59 | float radius, maxRadius = 0.0;
|
60 |
|
61 | /// Detect edges using Threshold
|
62 | threshold(denoisedImage, contourImage, 100, 255, cv::THRESH_BINARY);
|
63 | /// Find contours
|
64 | findContours(contourImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
|
65 |
|
66 | /// Approximate contours to polygons + get bounding circles
|
67 | for (unsigned int i = 0; i < contours.size(); i++) {
|
68 | approxPolyDP(Mat(contours[i]), contours_poly, 3, true);
|
69 | minEnclosingCircle(contours_poly, center, radius);
|
70 | if (radius > maxRadius) {
|
71 | maxCenter = center;
|
72 | maxRadius = radius;
|
73 | }
|
74 | if (DISPLAY_RESULT) {
|
75 | // Draw circle
|
76 | circle(frame, center, radius, Scalar(0, 255, 0, 0), 1, 8);
|
77 | }
|
78 | }
|
79 |
|
80 | printf("\r ");
|
81 | if (maxRadius > 0.0) {
|
82 | printf("\r(%3.1f / %3.1f)", maxCenter.x, maxCenter.y);
|
83 | } else {
|
84 | printf("\r(%3.1f / %3.1f)", -1.0, -1.0);
|
85 | }
|
86 | fflush(stdout);
|
87 |
|
88 | if (DISPLAY_RESULT) {
|
89 | // Update window and check keys
|
90 | imshow("main", frame);
|
91 | imshow("bin", denoisedImage);
|
92 | c = waitKey(30) & 255;
|
93 | if (c == 'q' || c == 'Q') {
|
94 | stopProgram = true;
|
95 | }
|
96 | }
|
97 |
|
98 | }
|
99 | return 0;
|
100 | }
|