我对OpenCV很陌生并且刚刚玩了一段时间来做基本的事情,比如阈值图像等。我在C ++中使用Visual Studio 2015和OpenCV3。我试图检测使用相机举起的手的手指数量。例如,如果我举起4根手指,我希望程序告诉我检测到4根手指。到目前为止,我已经能够使用轮廓检测物体的边缘,例如我在相机中的整个手。这是代码:
#include "opencv2\opencv.hpp"
using namespace cv;
void on_trackbar(int, void*) {
// Dummy function
}
int main(int argv, char** argc) {
Mat frame;
Mat grayFrame;
Mat hsvFrame;
Mat thesholdFrame;
VideoCapture capture;
//Trackbar variables (H,S,V)
int H_MIN = 0;
int H_MAX = 180;
int S_MIN = 0;
int S_MAX = 255;
int V_MIN = 0;
int V_MAX = 255;
namedWindow("trackbar", 0);
//create memory to store trackbar name on window
char TrackbarName[50];
sprintf(TrackbarName, "H_MIN");
sprintf(TrackbarName, "H_MAX");
sprintf(TrackbarName, "S_MIN");
sprintf(TrackbarName, "S_MAX");
sprintf(TrackbarName, "V_MIN");
sprintf(TrackbarName, "V_MAX");
createTrackbar("H_MIN", "trackbar", &H_MIN, H_MAX, on_trackbar);
createTrackbar("H_MAX", "trackbar", &H_MAX, H_MAX, on_trackbar);
createTrackbar("S_MIN", "trackbar", &S_MIN, S_MAX, on_trackbar);
createTrackbar("S_MAX", "trackbar", &S_MAX, S_MAX, on_trackbar);
createTrackbar("V_MIN", "trackbar", &V_MIN, V_MAX, on_trackbar);
createTrackbar("V_MAX", "trackbar", &V_MAX, V_MAX, on_trackbar);
capture.open(0);
std::vector<std::vector<cv::Point> > contours;
while (true){
capture >> frame;
waitKey(10);
cvtColor(frame, hsvFrame, COLOR_BGR2HSV);
//imshow("HSV", hsvFrame);
inRange(hsvFrame, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX, S_MAX, V_MAX), thesholdFrame);
findContours(thesholdFrame, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
int largest_contour_area = 0;
int largest_contour_area_index = 1;
/*for (int i = 0; i < contours.size(); i++) {
double contour_area = contourArea(contours[i], false);
if (contour_area > largest_contour_area) {
largest_contour_area = contour_area;
largest_contour_area_index = i;
}
}*/
drawContours(frame, contours, -1, (0, 255, 0), 3);
putText(frame, "NO DETECTION", Point(25, 40), 2, 1, CV_RGB(255, 255, 0), 1, 8, false);
imshow("Threshold", thesholdFrame);
imshow("Camera", frame);
}
}
在搜索了一会儿之后,我意识到仅隔离手的轮廓可能是有用的。 &#39; for&#39; for&#39; for被注释掉的循环是我尝试实现它。但是,它似乎不起作用。我确实意识到,一旦我取消注释该部分,我就必须改变
drawContours(frame, contours, -1, (0, 255, 0), 3);
到
drawContours(frame, contours[largest_contour_area_index], -1, (0, 255, 0), 3);
这似乎不起作用。我不断收到此错误(当我取消注释for循环并将drawContours命令替换为上面的错误时):
Unhandled exception at 0x00007FF8C1537788 in FingerDetection.exe: Microsoft C++ exception: cv::Exception at memory location 0x0000000C4CAFDB50.
此外,如果我以某种方式设法让程序找到帧中最大轮廓的边缘(即手),我将如何继续检测手指的数量?我已经听过关于凸壳等的事情,但我找不到任何好的解释。有关做什么的任何澄清或建议?请记住,我是openCV的新手。
答案 0 :(得分:1)
你的第二个问题(&#34;我将如何继续检测手指的数量&#34;)可能有点过于宽泛而无法在这里得到解答。
但是第一个(也就是你获得异常的原因)似乎有一个简单的答案,我从OpenCV文档(版本2.4)中找到drawContours
函数,我发现here。
根据它,第二个参数必须是一个(轮廓)数组,所以你不能简单地传递单个元素contours[largest_contour_area_index]
。
如果只想绘制一个轮廓,则仍需要传递整个数组,然后将要绘制的轮廓索引作为第三个参数(而不是-1
):
drawContours(frame, contours, largest_contour_area_index, (0, 255, 0), 3);
作为补充说明,最好确保largest_contour_area_index
的值小于数组中的轮廓数。鉴于您当前的代码,可能存在永远不会执行for循环体的情况,并且largest_contour_area_index
初始化为1
的值可能太大。