|
|
@ -1,4 +1,5 @@ |
|
|
|
#include "opencv2/core/utility.hpp" |
|
|
|
#include "opencv2/core/utility.hpp" |
|
|
|
|
|
|
|
#include "opencv2/core/ocl.hpp" |
|
|
|
#include "opencv2/video/tracking.hpp" |
|
|
|
#include "opencv2/video/tracking.hpp" |
|
|
|
#include "opencv2/imgproc/imgproc.hpp" |
|
|
|
#include "opencv2/imgproc/imgproc.hpp" |
|
|
|
#include "opencv2/highgui/highgui.hpp" |
|
|
|
#include "opencv2/highgui/highgui.hpp" |
|
|
@ -6,17 +7,18 @@ |
|
|
|
#include <iostream> |
|
|
|
#include <iostream> |
|
|
|
#include <cctype> |
|
|
|
#include <cctype> |
|
|
|
|
|
|
|
|
|
|
|
static cv::Mat image; |
|
|
|
static cv::UMat image; |
|
|
|
static bool backprojMode = false; |
|
|
|
static bool backprojMode = false; |
|
|
|
static bool selectObject = false; |
|
|
|
static bool selectObject = false; |
|
|
|
static int trackObject = 0; |
|
|
|
static int trackObject = 0; |
|
|
|
static bool showHist = true; |
|
|
|
static bool showHist = true; |
|
|
|
static cv::Point origin; |
|
|
|
|
|
|
|
static cv::Rect selection; |
|
|
|
static cv::Rect selection; |
|
|
|
static int vmin = 10, vmax = 256, smin = 30; |
|
|
|
static int vmin = 10, vmax = 256, smin = 30; |
|
|
|
|
|
|
|
|
|
|
|
static void onMouse(int event, int x, int y, int, void*) |
|
|
|
static void onMouse(int event, int x, int y, int, void*) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
static cv::Point origin; |
|
|
|
|
|
|
|
|
|
|
|
if (selectObject) |
|
|
|
if (selectObject) |
|
|
|
{ |
|
|
|
{ |
|
|
|
selection.x = std::min(x, origin.x); |
|
|
|
selection.x = std::min(x, origin.x); |
|
|
@ -54,10 +56,11 @@ static void help() |
|
|
|
|
|
|
|
|
|
|
|
std::cout << "\n\nHot keys: \n" |
|
|
|
std::cout << "\n\nHot keys: \n" |
|
|
|
"\tESC - quit the program\n" |
|
|
|
"\tESC - quit the program\n" |
|
|
|
"\tc - stop the tracking\n" |
|
|
|
"\ts - stop the tracking\n" |
|
|
|
"\tb - switch to/from backprojection view\n" |
|
|
|
"\tb - switch to/from backprojection view\n" |
|
|
|
"\th - show/hide object histogram\n" |
|
|
|
"\th - show/hide object histogram\n" |
|
|
|
"\tp - pause video\n" |
|
|
|
"\tp - pause video\n" |
|
|
|
|
|
|
|
"\tc - use OpenCL or not\n" |
|
|
|
"To initialize tracking, select the object with mouse\n"; |
|
|
|
"To initialize tracking, select the object with mouse\n"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -69,7 +72,6 @@ int main(int argc, const char** argv) |
|
|
|
cv::Rect trackWindow; |
|
|
|
cv::Rect trackWindow; |
|
|
|
int hsize = 16; |
|
|
|
int hsize = 16; |
|
|
|
float hranges[2] = { 0, 180 }; |
|
|
|
float hranges[2] = { 0, 180 }; |
|
|
|
const float * phranges = hranges; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char * const keys = { "{@camera_number| 0 | camera number}" }; |
|
|
|
const char * const keys = { "{@camera_number| 0 | camera number}" }; |
|
|
|
cv::CommandLineParser parser(argc, argv, keys); |
|
|
|
cv::CommandLineParser parser(argc, argv, keys); |
|
|
@ -80,6 +82,7 @@ int main(int argc, const char** argv) |
|
|
|
if (!cap.isOpened()) |
|
|
|
if (!cap.isOpened()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
help(); |
|
|
|
help(); |
|
|
|
|
|
|
|
|
|
|
|
std::cout << "***Could not initialize capturing...***\n"; |
|
|
|
std::cout << "***Could not initialize capturing...***\n"; |
|
|
|
std::cout << "Current parameter's value: \n"; |
|
|
|
std::cout << "Current parameter's value: \n"; |
|
|
|
parser.printMessage(); |
|
|
|
parser.printMessage(); |
|
|
@ -89,12 +92,13 @@ int main(int argc, const char** argv) |
|
|
|
|
|
|
|
|
|
|
|
cv::namedWindow("Histogram", cv::WINDOW_NORMAL); |
|
|
|
cv::namedWindow("Histogram", cv::WINDOW_NORMAL); |
|
|
|
cv::namedWindow("CamShift Demo", cv::WINDOW_NORMAL); |
|
|
|
cv::namedWindow("CamShift Demo", cv::WINDOW_NORMAL); |
|
|
|
cv::setMouseCallback("CamShift Demo", onMouse, NULL); |
|
|
|
cv::setMouseCallback("CamShift Demo", onMouse); |
|
|
|
cv::createTrackbar("Vmin", "CamShift Demo", &vmin, 256, NULL); |
|
|
|
cv::createTrackbar("Vmin", "CamShift Demo", &vmin, 256); |
|
|
|
cv::createTrackbar("Vmax", "CamShift Demo", &vmax, 256, NULL); |
|
|
|
cv::createTrackbar("Vmax", "CamShift Demo", &vmax, 256); |
|
|
|
cv::createTrackbar("Smin", "CamShift Demo", &smin, 256, NULL); |
|
|
|
cv::createTrackbar("Smin", "CamShift Demo", &smin, 256); |
|
|
|
|
|
|
|
|
|
|
|
cv::Mat frame, hsv, hue, mask, hist, histimg = cv::Mat::zeros(200, 320, CV_8UC3), backproj; |
|
|
|
cv::Mat frame, histimg(200, 320, CV_8UC3, cv::Scalar::all(0)); |
|
|
|
|
|
|
|
cv::UMat hsv, hist, hue, mask, backproj; |
|
|
|
bool paused = false; |
|
|
|
bool paused = false; |
|
|
|
|
|
|
|
|
|
|
|
for ( ; ; ) |
|
|
|
for ( ; ; ) |
|
|
@ -119,14 +123,15 @@ int main(int argc, const char** argv) |
|
|
|
cv::inRange(hsv, cv::Scalar(0, smin, std::min(_vmin, _vmax)), |
|
|
|
cv::inRange(hsv, cv::Scalar(0, smin, std::min(_vmin, _vmax)), |
|
|
|
cv::Scalar(180, 256, std::max(_vmin, _vmax)), mask); |
|
|
|
cv::Scalar(180, 256, std::max(_vmin, _vmax)), mask); |
|
|
|
|
|
|
|
|
|
|
|
int ch[2] = { 0, 0 }; |
|
|
|
int fromTo[2] = { 0,0 }; |
|
|
|
hue.create(hsv.size(), hsv.depth()); |
|
|
|
hue.create(hsv.size(), hsv.depth()); |
|
|
|
cv::mixChannels(&hsv, 1, &hue, 1, ch, 1); |
|
|
|
cv::mixChannels(std::vector<cv::UMat>(1, hsv), std::vector<cv::UMat>(1, hue), fromTo, 1); |
|
|
|
|
|
|
|
|
|
|
|
if (trackObject < 0) |
|
|
|
if (trackObject < 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cv::Mat roi(hue, selection), maskroi(mask, selection); |
|
|
|
cv::UMat roi(hue, selection), maskroi(mask, selection); |
|
|
|
cv::calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges); |
|
|
|
cv::calcHist(std::vector<cv::Mat>(1, roi.getMat(cv::ACCESS_READ)), std::vector<int>(1, 0), |
|
|
|
|
|
|
|
maskroi, hist, std::vector<int>(1, hsize), std::vector<float>(hranges, hranges + 2)); |
|
|
|
cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX); |
|
|
|
cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX); |
|
|
|
|
|
|
|
|
|
|
|
trackWindow = selection; |
|
|
|
trackWindow = selection; |
|
|
@ -139,17 +144,22 @@ int main(int argc, const char** argv) |
|
|
|
buf.at<cv::Vec3b>(i) = cv::Vec3b(cv::saturate_cast<uchar>(i*180./hsize), 255, 255); |
|
|
|
buf.at<cv::Vec3b>(i) = cv::Vec3b(cv::saturate_cast<uchar>(i*180./hsize), 255, 255); |
|
|
|
cv::cvtColor(buf, buf, cv::COLOR_HSV2BGR); |
|
|
|
cv::cvtColor(buf, buf, cv::COLOR_HSV2BGR); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
cv::Mat _hist = hist.getMat(cv::ACCESS_READ); |
|
|
|
for (int i = 0; i < hsize; i++) |
|
|
|
for (int i = 0; i < hsize; i++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int val = cv::saturate_cast<int>(hist.at<float>(i)*histimg.rows/255); |
|
|
|
int val = cv::saturate_cast<int>(_hist.at<float>(i)*histimg.rows/255); |
|
|
|
cv::rectangle(histimg, cv::Point(i*binW, histimg.rows), |
|
|
|
cv::rectangle(histimg, cv::Point(i*binW, histimg.rows), |
|
|
|
cv::Point((i+1)*binW, histimg.rows - val), |
|
|
|
cv::Point((i+1)*binW, histimg.rows - val), |
|
|
|
cv::Scalar(buf.at<cv::Vec3b>(i)), -1, 8); |
|
|
|
cv::Scalar(buf.at<cv::Vec3b>(i)), -1, 8); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cv::calcBackProject(std::vector<cv::UMat>(1, hue), std::vector<int>(1, 0), hist, backproj, |
|
|
|
|
|
|
|
std::vector<float>(hranges, hranges + 2), 1.0); |
|
|
|
|
|
|
|
cv::bitwise_and(backproj, mask, backproj); |
|
|
|
|
|
|
|
|
|
|
|
cv::calcBackProject(&hue, 1, 0, hist, backproj, &phranges); |
|
|
|
|
|
|
|
backproj &= mask; |
|
|
|
|
|
|
|
cv::RotatedRect trackBox = cv::CamShift(backproj, trackWindow, |
|
|
|
cv::RotatedRect trackBox = cv::CamShift(backproj, trackWindow, |
|
|
|
cv::TermCriteria(cv::TermCriteria::EPS | cv::TermCriteria::COUNT, 10, 1)); |
|
|
|
cv::TermCriteria(cv::TermCriteria::EPS | cv::TermCriteria::COUNT, 10, 1)); |
|
|
|
if (trackWindow.area() <= 1) |
|
|
|
if (trackWindow.area() <= 1) |
|
|
@ -162,7 +172,11 @@ int main(int argc, const char** argv) |
|
|
|
|
|
|
|
|
|
|
|
if (backprojMode) |
|
|
|
if (backprojMode) |
|
|
|
cv::cvtColor(backproj, image, cv::COLOR_GRAY2BGR); |
|
|
|
cv::cvtColor(backproj, image, cv::COLOR_GRAY2BGR); |
|
|
|
cv::ellipse(image, trackBox, cv::Scalar(0, 0, 255), 3, cv::LINE_AA); |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
cv::Mat _image = image.getMat(cv::ACCESS_RW); |
|
|
|
|
|
|
|
cv::ellipse(_image, trackBox, cv::Scalar(0, 0, 255), 3, cv::LINE_AA); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if (trackObject < 0) |
|
|
|
else if (trackObject < 0) |
|
|
@ -170,11 +184,12 @@ int main(int argc, const char** argv) |
|
|
|
|
|
|
|
|
|
|
|
if (selectObject && selection.width > 0 && selection.height > 0) |
|
|
|
if (selectObject && selection.width > 0 && selection.height > 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
cv::Mat roi(image, selection); |
|
|
|
cv::UMat roi(image, selection); |
|
|
|
cv::bitwise_not(roi, roi); |
|
|
|
cv::bitwise_not(roi, roi); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
cv::imshow("CamShift Demo", image); |
|
|
|
cv::imshow("CamShift Demo", image); |
|
|
|
|
|
|
|
if (showHist) |
|
|
|
cv::imshow("Histogram", histimg); |
|
|
|
cv::imshow("Histogram", histimg); |
|
|
|
|
|
|
|
|
|
|
|
char c = (char)cv::waitKey(10); |
|
|
|
char c = (char)cv::waitKey(10); |
|
|
@ -186,7 +201,7 @@ int main(int argc, const char** argv) |
|
|
|
case 'b': |
|
|
|
case 'b': |
|
|
|
backprojMode = !backprojMode; |
|
|
|
backprojMode = !backprojMode; |
|
|
|
break; |
|
|
|
break; |
|
|
|
case 'c': |
|
|
|
case 't': |
|
|
|
trackObject = 0; |
|
|
|
trackObject = 0; |
|
|
|
histimg = cv::Scalar::all(0); |
|
|
|
histimg = cv::Scalar::all(0); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -200,6 +215,8 @@ int main(int argc, const char** argv) |
|
|
|
case 'p': |
|
|
|
case 'p': |
|
|
|
paused = !paused; |
|
|
|
paused = !paused; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'c': |
|
|
|
|
|
|
|
cv::ocl::setUseOpenCL(!cv::ocl::useOpenCL()); |
|
|
|
default: |
|
|
|
default: |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|