OpenCV последний дефект выпуклости не прав

Я пытаюсь написать код для отслеживания рук. Я использую функцию дефектов выпуклости, чтобы найти пальцы, но по некоторым причинам, кажется, всегда есть проблема с последним дефектом.

Вот картинка о чем я говорю (извините, я новичок в форуме, поэтому не могу публиковать изображения)

Голубая линия — это контуры, желтая линия — это точки корпуса, а красные — дефектные точки. Как видите, последняя точка дефекта обнаруживает дефект с неправильной стороны контура.

Вот мой код:

#include "opencv2\opencv.hpp"
using namespace cv;
using namespace std;

int main() {
VideoCapture cap(0);
Mat src, gray, background, binary, diff;
cap >> background;
cvtColor(background, background, CV_BGR2GRAY);
vector<vector<Point>> contours;
vector < vector<int>> hullI = vector<vector<int>>(1);
vector < vector<Point>> hullP = vector<vector<Point>>(1);
vector<Vec4i> defects;
while (waitKey(30)!='q') {
cap >> src;
cvtColor(src, gray, CV_BGR2GRAY);
blur(gray, gray, Size(3, 3));
absdiff(gray, background, diff);
threshold(diff, binary, 15, 255, THRESH_BINARY);
erode(binary, binary, Mat(Size(5, 5), CV_8U));

imshow("binary", binary);

findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
if (!contours.empty()) {
sort(contours.begin(), contours.end(), [](vector<Point> a, vector<Point> b) { return a.size() > b.size(); });
drawContours(src, contours, 0, Scalar(255, 255, 0));

convexHull(contours[0], hullI[0]);
convexHull(contours[0], hullP[0]);
drawContours(src, hullP, 0, Scalar(0, 255, 255));

if (hullI[0].size() > 2) {
convexityDefects(contours[0], hullI[0], defects);

for (Vec4i defect : defects) {
line(src, contours[0][defect[0]], contours[0][defect[2]], Scalar(0, 0, 255));
line(src, contours[0][defect[1]], contours[0][defect[2]], Scalar(0, 0, 255));
}
}
}
imshow("src", src);
char key = waitKey(30);
if (key == 'q')break;
else if (key == 'p') waitKey();
else if (key == 'b') {
cap >> background;
cvtColor(background, background, CV_BGR2GRAY);
}
}
}

Я экспериментально подтвердил, что это всегда последний дефект в векторе дефектов, что это тоже происходит. Это ошибка в opencv или я что-то не так делаю?

0

Решение

Я проверил ваш код (с небольшой модификацией) с изображением ниже (версия OpenCV 3.2).

как вы можете видеть на полученном изображении, оно работает как положено. Возможно, вы используете старую версию OpenCV и получаете ошибку. (я думаю, что это была недавно исправленная ошибка)

введите описание изображения здесь

введите описание изображения здесь

#include "opencv2\opencv.hpp"
using namespace cv;
using namespace std;

int main() {
//VideoCapture cap(0);
Mat src, gray, background, binary, diff;
//cap >> background;
//cvtColor(background, background, CV_BGR2GRAY);
vector<vector<Point> > contours;
vector < vector<int> > hullI = vector<vector<int> >(1);
vector < vector<Point> > hullP = vector<vector<Point> >(1);
vector<Vec4i> defects;
src = imread("hand.png");
cvtColor(src, gray, CV_BGR2GRAY);
blur(gray, gray, Size(3, 3));
threshold(gray, binary, 150, 255, THRESH_BINARY_INV);
//erode(binary, binary, Mat(Size(5, 5), CV_8U));
imshow("binary", binary);
findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
if (!contours.empty()) {
sort(contours.begin(), contours.end(), [](vector<Point> a, vector<Point> b) { return a.size() > b.size(); });
drawContours(src, contours, 0, Scalar(255, 255, 0));

convexHull(contours[0], hullI[0]);
convexHull(contours[0], hullP[0]);
drawContours(src, hullP, 0, Scalar(0, 255, 255));

if (hullI[0].size() > 2) {
convexityDefects(contours[0], hullI[0], defects);

for (Vec4i defect : defects) {
line(src, contours[0][defect[0]], contours[0][defect[2]], Scalar(0, 0, 255));
line(src, contours[0][defect[1]], contours[0][defect[2]], Scalar(0, 0, 255));
}
}
}
imshow("result", src);
char key = waitKey(0);
return 0;
}
1

Другие решения

У меня есть решение, которое включает в себя определение кожи с помощью OpenCV. Я реализовал это с помощью python, который вы можете легко конвертировать в C ++.

Я получил значения HSV для изображения, которое вы загрузили, используя:

hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

Это диапазон значений HSV для кожи человека:

l = np.array([0, 48, 80], dtype = "uint8")
u = np.array([20, 255, 255], dtype = "uint8")

skin_img = cv2.inRange(hsv_img, l, u)
cv2.imshow("Hand", skin_img)

Я тогда выполнил морфологическая дилатация и получил следующее:

введите описание изображения здесь

Теперь вы можете применить контурную оболочку и найти дефекты выпуклости.

0