手掌手指分割算法(源码)

开发环境

开发环境

  • 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/

时间: 2024-08-07 07:50:12

手掌手指分割算法(源码)的相关文章

[Spark传奇行动] 第34课:Stage划分和Task最佳位置算法源码彻底解密

本課主題 Job Stage 划分算法解密 Task 最佳位置算法實現解密 引言 作业调度的划分算法以及 Task 的最佳位置的算法,因为 Stage 的划分是DAGScheduler 工作的核心,这也是关系到整个作业有集群中该怎么运行:其次就是数据本地性,Spark 一舨的代码都是链式表达的,这就让一个任务什么时候划分成 Stage,在大数据世界要追求最大化的数据本地性,所有最大化的数据本地性就是在数据计算的时候,数据就在内存中.最后就是 Spark 的实现算法时候的略的怎么样.希望这篇文章能

【141029】VC游戏编写中的求解最短路径算法源码

VC游戏编写中的求解最短路径算法源码,本示例是自动寻径演示,篮点是起点,红点是终点,按确定键开始.源码爱好者注:编译后运行的时候请把EXE文件从Debug目录中拷贝到项目根目录中,若不然会出错. 编著.程序设计:唐明理 程序顺序: 初始化队列.待处理节点入队列, 依靠对目的地估价距离插入排序,将离目的地估计最近的方案出队列,释放栈顶节点,释放申请过的所有节点,估价函数,估价 x,y 到目的地的距离,估计值必须保证比实际值小, 尝试下一步移动到 x,y 可行否,如果曾经有更好的方案移动到 (x,y

冒泡排序(算法源码)

算法源码: //BubbleSort.cpp #include <iostream>using namespace std; void BubbleSort(int a[], int n){ for(int i=n-1;i>0;i--) {for(int j=0;j<i;j++) { if (a[j]>a[j+1]) { int tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; } } }}int main(){ int a[]={4,3,6,

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

源:基于新唐M0的XXTEA加密解密算法源码 /*--------------------------------------------------------------------------------------------------------- 在数据的加解密领域,算法分为对称密钥与非对称密钥两种.对称密钥与非对称密钥由于各自的特点,所应用的领域是不尽相 同的.对称密钥加密算法由于其速度快,一般用于整体数据的加密,而非对称密钥加密算法的安全性能佳,在数字签名领域得到广 泛的应用.

机器学习Spark Mllib算法源码及实战详解进阶与提高视频教程

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv

基于单层决策树的AdaBoost算法源码

基于单层决策树的AdaBoost算法源码 Mian.py 1 # -*- coding: utf-8 -*- 2 # coding: UTF-8 3 4 import numpy as np 5 from AdaBoost import AdaBoost 6 from sklearn.model_selection import train_test_split 7 from sklearn.metrics import accuracy_score 8 9 def main(): 10 11

【Atheros】minstrel速率调整算法源码走读

先说几个辅助的宏,因为内核不支持浮点运算,当然还有实现需要,minstrel对很多浮点值做了缩放: /* scaled fraction values */ #define MINSTREL_SCALE 16 #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) MINSTREL_SCALE是一个放

【Atheros】Ath9k速率调整算法源码走读

上一篇文章介绍了驱动中minstrel_ht速率调整算法,atheros中提供了可选的的两种速率调整算法,分别是ath9k和minstrel,这两个算法分别位于: drivers\net\wireless\ath\ath9k\rc.c···················Ath9k net\mac80211\minstrel_ht.c···························Minstrel 无论从理论分析还是实验结果上看,minstrel都要胜ath9k一筹,为了一个完整性,这里也

OpenCV人脸识别Eigen算法源码分析

1 理论基础 学习Eigen人脸识别算法需要了解一下它用到的几个理论基础,现总结如下: 1.1 协方差矩阵 首先需要了解一下公式: 共公式可以看出:均值描述的是样本集合的平均值,而标准差描述的则是样本集合的各个样本点到均值的距离之平均.以一个国家国民收入为例,均值反映了平均收入,而均方差/方差则反映了贫富差距,如果两个国家国民收入均值相等,则标准差越大说明国家的国民收入越不均衡,贫富差距较大.以上公式都是用来描述一维数据量的,把方差公式推广到二维,则可得到协方差公式: 协方差表明了两个随机变量之