手掌手指分割算法

1,417 阅读2分钟
原文链接: skyseraph.com

开发环境

开发环境

  • 64 bits Windows OS (Win8.1)
  • VS2013
  • OpenCV 2.4.9

功能原理

算法要求

完成将Camera拍摄的手掌图片中分割出每个手指用于指纹识别

算法流程

核心代码

#ifdef TIME_RUN_COST
	double duration = static_cast(cv::getTickCount());//time
#endif
	cout << "filename=" << filename < IplImage
	IplImage* pImgOutEqualizeHist = EqualizeHistColorImage(&pImgInEqualizeHist);
	matOutEqualizeHist = pImgOutEqualizeHist; //IplImage -> Mat
#endif
	// out
	Mat imgSrc = Mat(imgCut.size(), CV_8UC1);
	imgCut.copyTo(imgSrc);

	Mat imgContour = Mat(imgSrc.size(), CV_8UC1);
#ifdef FINGER_EXTRACT_AT_NIGHT
	cout << "Nigth,Threshold..." << endl;
	Mat imgTmp;// = Mat(imgCut.size(), CV_8UC1);
	cvtColor(imgSrc, imgTmp, CV_RGB2GRAY);
	cvThresholdOtsu(&((IplImage)imgTmp), &((IplImage)imgTmp));
	imgTmp.copyTo(imgContour);
#else

	cout << "Day,Skin..." << endl;
	Mat imgSkin2 = Mat(imgSrc.size(), CV_8UC1);
	IplImage* pImgSkin2 = cvCreateImage(cvSize(imgSrc.cols, imgSrc.rows), IPL_DEPTH_8U, 1);
	IplImage pImg2 = (IplImage)(imgSrc);	// Mat-> IplImage
	cvSkinOtsu(&pImg2, pImgSkin2);
	imgSkin2 = pImgSkin2; //IplImage -> Mat

	//Mat imgSkin = Mat(imgSrc.size(), CV_8UC1);
	imgSkin2.copyTo(imgContour);
#endif
	
	/////////////////////// Contours
	cout << "Find Contours..." << endl;
	vector > contours;
	vector hierarchy;
	findContours(imgContour, contours, hierarchy,
		CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0)); 

	sort(contours.begin(), contours.end(), compareContourAreas);

	int contours_num = contours.size();
	cout << "contours_num=" << contours_num << endl;
#if 0	
	vector>::const_iterator itContours = contours.begin();
	//for (int i = 0; i < contours.size(); i++)
	for (; itContours != contours.end(); ++itContours)
	{
		cout << "Size: " << itContours->size() << endl;//每个轮廓包含的点数
	}
#endif

#if 1 //usd
	// Eliminate too short or too long contours  
	int cmin = 100;  // minimum contour length  
	//int cmax= 1000; // maximum contour length  
	vector>::const_iterator itc = contours.begin();
	while (itc != contours.end())
	{
		//if (itc->size() < cmin || itc->size() > cmax)		
		if (itc->size() < cmin)	{
			itc = contours.erase(itc);
		}
		else
			++itc;
	}
	contours_num = contours.size();
	cout << endl << "contours_num after Eliminate=" << contours_num << endl;
#endif

	// extract the contour img
	cout << "Extract Contours..." << endl;
	if (contours_num >= 4)
	{
		Mat img1, img2, img3, img4;
		std::vector biggest1Contour = contours[contours_num - 1];
		std::vector biggest2Contour = contours[contours_num - 2];
		std::vector biggest3Contour = contours[contours_num - 3];
		std::vector biggest4Contour = contours[contours_num - 4];
		std::vector smallestContour = contours[0];
		extractFingerImg2(contours, imgSrc, img1, contours_num, 1);		
		extractFingerImg2(contours, imgSrc, img2, contours_num, 2);
		extractFingerImg2(contours, imgSrc, img3, contours_num, 3);
		extractFingerImg2(contours, imgSrc, img4, contours_num, 4);
	}
	else if (contours_num == 3)
	{
		Mat img1, img2, img3;
		std::vector biggest1Contour = contours[contours_num - 1];
		std::vector biggest2Contour = contours[contours_num - 2];
		std::vector biggest3Contour = contours[contours_num - 3];
		std::vector smallestContour = contours[0];
		extractFingerImg2(contours, imgSrc, img1, contours_num, 1);
		extractFingerImg2(contours, imgSrc, img2, contours_num, 2);
		extractFingerImg2(contours, imgSrc, img3, contours_num, 3);
	}
	else if (contours_num == 2)
	{
		Mat img1, img2;
		std::vector biggest1Contour = contours[contours_num - 1];
		std::vector biggest2Contour = contours[contours_num - 2];
		std::vector smallestContour = contours[0];
		extractFingerImg2(contours, imgSrc, img1, contours_num, 1);
		extractFingerImg2(contours, imgSrc, img2, contours_num, 2);
	}
	else if (contours_num == 1)
	{	
		Mat img1;
		std::vector biggest1Contour = contours[contours_num - 1];
		std::vector smallestContour = contours[0];
		extractFingerImg2(contours, imgSrc, img1, contours_num, 1);
	}
	else
	{
		cout << "error" << endl;
	}
#ifdef TIME_RUN_COST
	duration = static_cast(cv::getTickCount()) - duration;
	duration /= cv::getTickFrequency(); // the elapsed time in ms
	cout << "time cost=" << duration << "s"<

算法效果

白天复杂场景

晚上场景

批量测试场景



By SkySeraph-2014

合作联系:skyseraph00@163.com

————————

版权声明

SkySeraph by SkySeraph is licensed under a Creative Commons BY-NC-ND 4.0 International License.
Bob创作并维护的SkySeraph博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证.
本文首发于SkySeraph博客( skyseraph.com ),版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

微信扫码打赏SkySeraph

如果您愿意捐助其它金额请戳我~~,扫码支付宝/微信

本文永久链接:skyseraph.com/2014/07/24/…