One approach may be to segment a hand and fingers from an image:

And then create another image with only a strong silhouette :

When you have a silhouette, you can undermine the image to make it a little smaller. This is used to subtract the hand from the image of the hands and fingers , resulting in the fingers:

The code below shows how to implement this approach:
void detect_hand_and_fingers(cv::Mat& src); void detect_hand_silhoutte(cv::Mat& src); int main(int argc, char* argv[]) { cv::Mat img = cv::imread(argv[1]); if (img.empty()) { std::cout << "!!! imread() failed to open target image" << std::endl; return -1; } // Convert RGB Mat to GRAY cv::Mat gray; cv::cvtColor(img, gray, CV_BGR2GRAY); cv::Mat gray_silhouette = gray.clone(); /* Isolate Hand + Fingers */ detect_hand_and_fingers(gray); cv::imshow("Hand+Fingers", gray); cv::imwrite("hand_fingers.png", gray); /* Isolate Hand Sillhoute and subtract it from the other image (Hand+Fingers) */ detect_hand_silhoutte(gray_silhouette); cv::imshow("Hand", gray_silhouette); cv::imwrite("hand_silhoutte.png", gray_silhouette); /* Subtract Hand Silhoutte from Hand+Fingers so we get only Fingers */ cv::Mat fingers = gray - gray_silhouette; cv::imshow("Fingers", fingers); cv::imwrite("fingers_only.png", fingers); cv::waitKey(0); return 0; } void detect_hand_and_fingers(cv::Mat& src) { cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3,3), cv::Point(1,1)); cv::morphologyEx(src, src, cv::MORPH_ELLIPSE, kernel); int adaptiveMethod = CV_ADAPTIVE_THRESH_GAUSSIAN_C; // CV_ADAPTIVE_THRESH_MEAN_C, CV_ADAPTIVE_THRESH_GAUSSIAN_C cv::adaptiveThreshold(src, src, 255, adaptiveMethod, CV_THRESH_BINARY, 9, -5); int dilate_sz = 1; cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2*dilate_sz, 2*dilate_sz), cv::Point(dilate_sz, dilate_sz) ); cv::dilate(src, src, element); } void detect_hand_silhoutte(cv::Mat& src) { cv::Mat kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(7, 7), cv::Point(3, 3)); cv::morphologyEx(src, src, cv::MORPH_ELLIPSE, kernel); int adaptiveMethod = CV_ADAPTIVE_THRESH_MEAN_C; // CV_ADAPTIVE_THRESH_MEAN_C, CV_ADAPTIVE_THRESH_GAUSSIAN_C cv::adaptiveThreshold(src, src, 255, adaptiveMethod, CV_THRESH_BINARY, 251, 5); // 251, 5 int erode_sz = 5; cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2*erode_sz + 1, 2*erode_sz+1), cv::Point(erode_sz, erode_sz) ); cv::erode(src, src, element); int dilate_sz = 1; element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(2*dilate_sz + 1, 2*dilate_sz+1), cv::Point(dilate_sz, dilate_sz) ); cv::dilate(src, src, element); cv::bitwise_not(src, src); }