开发环境

开发环境

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

功能原理

算法要求

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

算法流程

核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#ifdef TIME_RUN_COST
double duration = static_cast<double>(cv::getTickCount());//time
#endif
cout << "filename=" << filename <<endl;
Mat src = imread(filename, CV_LOAD_IMAGE_COLOR);
if (src.empty())
{
cout << "imread error!!!";
getchar();
return -1;
}
#ifdef BOB_DBG_COM
memset(out_filename, 0, sizeof(out_filename) / sizeof(char));
sprintf(out_filename, "%s-%s.jpg",out_name,"0-0src");
imwrite(out_filename, src);
#endif // BOB_DBG_COM
#if 0
int scaleSize = 4;
resize(src, src, Size(src.cols / scaleSize, src.rows / scaleSize), 0, 0, CV_INTER_AREA);
memset(out_filename, 0, sizeof(out_filename) / sizeof(char));
sprintf(out_filename, "%s-%s.jpg", out_name, "0-0src");
imwrite(out_filename, src);
#endif
#if 1
cout << "cut..." << endl;
int width = src.cols;
int height = src.rows;
float scale = 0.8;
cout << "width=" << width << ",height=" << height << endl;
Rect rect(0, 0, width, height*scale);
Mat imgCut;
imgCut = src(rect).clone();
#endif
//Mat imgCut = src;
cout << "filter..." << endl;
// filter2D(imgCut, imgCut, -1, kernel);
GaussianBlur(imgCut, imgCut, Size(5, 5), 0, 0);
// blur(imgCut, imgCut, Size(5, 5));
#if 0
cout << "EqualizeHist..." << endl;
Mat matOutEqualizeHist = Mat(imgCut.size(), CV_8UC3);
//IplImage* pImgOutEqualizeHist = cvCreateImage(cvSize(cameraFrame.cols, cameraFrame.rows), IPL_DEPTH_8U, 3);
IplImage pImgInEqualizeHist = (IplImage)(imgCut); // Mat-> 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<vector<cv::Point> > contours;
vector<Vec4i> 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<vector<Point>>::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<vector<Point>>::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<cv::Point> biggest1Contour = contours[contours_num - 1];
std::vector<cv::Point> biggest2Contour = contours[contours_num - 2];
std::vector<cv::Point> biggest3Contour = contours[contours_num - 3];
std::vector<cv::Point> biggest4Contour = contours[contours_num - 4];
std::vector<cv::Point> 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<cv::Point> biggest1Contour = contours[contours_num - 1];
std::vector<cv::Point> biggest2Contour = contours[contours_num - 2];
std::vector<cv::Point> biggest3Contour = contours[contours_num - 3];
std::vector<cv::Point> 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<cv::Point> biggest1Contour = contours[contours_num - 1];
std::vector<cv::Point> biggest2Contour = contours[contours_num - 2];
std::vector<cv::Point> 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<cv::Point> biggest1Contour = contours[contours_num - 1];
std::vector<cv::Point> smallestContour = contours[0];
extractFingerImg2(contours, imgSrc, img1, contours_num, 1);
}
else
{
cout << "error" << endl;
}
#ifdef TIME_RUN_COST
duration = static_cast<double>(cv::getTickCount()) - duration;
duration /= cv::getTickFrequency(); // the elapsed time in ms
cout << "time cost=" << duration << "s"<<endl;
#endif
#ifdef BOB_DBG_COM
memset(out_filename, 0, sizeof(out_filename) / sizeof(char));
sprintf(out_filename, "%s-%s.jpg", out_name, "4-imgContoursInSrc");
imwrite(out_filename, imgSrc);
//imwrite("4-imgContoursInSrc.jpg", imgSrc);
#endif // BOB_DBG_COM

算法效果

白天复杂场景

晚上场景

批量测试场景

转至:http://skyseraph.com/2014/07/24/CV/%E6%89%8B%E6%8E%8C%E6%89%8B%E6%8C%87%E5%88%86%E5%89%B2%E7%AE%97%E6%B3%95/

转载于:https://www.cnblogs.com/Ph-one/p/7364976.html

手掌手指分割算法(源码)相关推荐

  1. 超像素SLIC算法源码阅读

    超像素SLIC算法源码阅读 超像素SLIC算法源码阅读 SLIC简介 源码阅读 实验结果 其他超像素算法对比 超像素SLIC算法源码阅读 SLIC简介 SLIC的全称Simple Linear Ite ...

  2. [unity3d]recast navigation navmesh 导航网格 寻路算法 源码分析

    recast navigation navmesh导航网格算法源码分析 Author:  林绍川 recast navigation navmesh是unity3d ue4内置的寻路算法 本文为了方便 ...

  3. AidLux“实时头发分割”案例源码详解

    "实时头发分割"案例源码详解 1. 构建APP框架和添加主要控件 2. 头发分割的方法 打开实时头发分割案例 1.在VScode中进入代码编辑状态. 2.代码存在路径在/examp ...

  4. 基于Python Unet的医学影像分割系统源码,含皮肤病的数据及皮肤病分割的模型,用户输入图像,模型可以自动分割去皮肤病的区域

    手把手教你用Unet做医学图像分割 我们用Unet来做医学图像分割.我们将会以皮肤病的数据作为示范,训练一个皮肤病分割的模型出来,用户输入图像,模型可以自动分割去皮肤病的区域和正常的区域.废话不多说, ...

  5. 基于新唐M0的XXTEA加密解密算法源码

    源:基于新唐M0的XXTEA加密解密算法源码 /*--------------------------------------------------------------------------- ...

  6. [转] GIS算法源码集合

    其他GIS相关代码下载索引 http://www.mygis.com.cn/codeindex10.htm 1.深度优先实现的路径分析源码 http://www.mygis.com.cn/codes/ ...

  7. 机器学习算法源码全解析(三)-范数规则化之核范数与规则项参数选择

    前言 参见上一篇博文,我们聊到了L0,L1和L2范数,这篇我们絮叨絮叨下核范数和规则项参数选择.知识有限,以下都是我一些浅显的看法,如果理解存在错误,希望大家不吝指正.谢谢. 机器学习算法源码全解析( ...

  8. Learning to Rank中Pointwise关于PRank算法源码实现

    [学习排序] Learning to Rank中Pointwise关于PRank算法源码实现 标签: 学习排序PRankPointwiseLearning to Rank代码实现 2015-01-28 ...

  9. c iostream.源码_通达信常用指标:「金手指 」指标源码

    通达信常用指标:[金手指 ]指标源码 强弱:=IF(C>=MA(C,18) AND (MA(C,18)>=REF(MA(C,18),1) OR (MA(C,18)<REF(MA(C, ...

最新文章

  1. keras和tensorflow使用 keras.callbacks.TensorBoard 可视化数据
  2. 【Linux Deploy】一、Linux Deploy安装配置使用教程
  3. android从放弃到精通 第八天 freedom
  4. python怎么画心形图案_Python数学方程式画心型图案源码示例
  5. Coursera课程Python for everyone:chapter4
  6. Windows——桌面快捷键Ctrl+Z撤销的文件恢复解决方案
  7. 梯度算法的matlab程序,基于MATLAB的梯度法源代码
  8. 角速度求积分能得到欧拉角吗_一个有趣的反常积分问题
  9. Java并发编程(08):Executor线程池框架
  10. php 加日志,添加日志的相关内容推荐
  11. Web后端学习笔记 Flask(4)视图函数
  12. leetcode 77.组合 dfs解法
  13. PHP 扩展 Mongo 与 MongoDB
  14. 华为将在数据库市场挑战Oracle:5月15日发布云数据库产品
  15. postgresql  null 值 不受查询条件约束
  16. 那四年,我们一起逝去的青春
  17. 山东理工大学计算机基础考试试题,山东理工大学计算机基础试题08
  18. oracle IMP命令导入导出DMP文件
  19. Transformers in NLP (一):图说transformer结构
  20. Git - git push origin master 报错的解决方法 出现[rejected] master -」 master (non-fast-forward)问题解决

热门文章

  1. 【 Linux 网络虚拟化 】Netns
  2. poj1548Robots dfs实践
  3. 《Pro ASP.NET MVC 3 Framework》学习笔记之二十四【Controllers和Actions】
  4. treeview 文字垂直方向_word文本排版技巧:改变文字方向的这些方法,你知道吗?...
  5. 5个元素排序java_Android-java-如何按对象内的某个值对对象列表进行排序
  6. LogSegment分析
  7. 基于FPGA实现IIC接口(EEPROM)
  8. (54)FPGA基础编码D触发器(三)
  9. (09)FPGA时序分析模型
  10. (41)System Verilog 例化System Verilog模块