当前位置:   article > 正文

关于OpenCV3的KMeans/GMM分割应用C++实现的DEMO–更换证件照片背景_opencv c++ 背景分割

opencv c++ 背景分割

关于OpenCV3的KMeans/GMM分割应用C++实现的DEMO–更换证件照片背景

作者:Simon Song

分割算法的应用

1.KMEANS:是一种聚类算法,主要过程:
流程图:
参数k–> 初始化中心点–>根据每个样本与中心的距离,分配聚类编号–>对编号相同的样本,计算新的中心位置–>当距离(D)小于阈值(T)或迭代(Iteration)次数大于迭代次数(C)->条件成立退出;条件不成立,从第三个步骤开始。
初始化中心的方法有:KMEANS_PP_CENTERS 中心初始化算法
KMEANS_RANDOM_CENTERS随机初始化
KMEANS_USE_INTIAL_LABEL用户指定标签
2.GMM高斯混合模型是基于高斯混合期望最大,是概率的方法。gmm分割,效果不如kmeans,有边缘颜色处理不好的情况。

在这里插入图片描述找到这种方式的高斯函数,各个系数,各个值。找到了之后,不断迭代逼近最真实的情况。按真实的情况进行直方图分类,得到直方图属于哪个高斯核和分类。至此完成分类功能。
在这里插入图片描述

软件环境

vs2015,OpenCV341,C++

代码实现

#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>

using namespace std;
using namespace cv;
using namespace cv::ml;//机器学习模块

Mat Mat_to_sample(Mat&image);//数据组装函数

int main(int argc, char** argv) {
	//读取图
	Mat src = imread("G:/opencv_trainning/vs2015/5/kmeanstest/tx.png");
	//判空
	if(src.empty()){
		cout << "open fault" << endl;
		return -1;
	}
	//显示
	imshow("src",src);
	//数据组装, n行3列单通道
	Mat points=Mat_to_sample(src);
	
	//kmeans分割
	//定义相关变量
	int k = 4;//聚类数
	Mat labels;//标签,n*1单通道,整形数据
	Mat centers;//中心,m行2列,整形单通道
	TermCriteria criteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1);//条件,迭代10次,最小量0.1
	//参数:(32F数据矩阵,分类个数,标签矩阵,条件,不同初始化分类尝试次数,聚类中心初始化标记,聚类中心)
	kmeans(points,k,labels, criteria,3,KMEANS_PP_CENTERS,centers);
	/*
	//gmm分割,效果不如kmeans,有边缘颜色处理不好
	Ptr<EM> em_cluster = EM::create();//创建
	em_cluster->setClustersNumber(4);// 设置聚类数
	em_cluster->setCovarianceMatrixType(EM::COV_MAT_SPHERICAL);//设置协方差矩阵类型
	em_cluster->setTermCriteria(TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,100,0.1));//设置检测标准
	Mat labels;//标签矩阵
	em_cluster->trainEM(points,noArray(),labels,noArray());//训练, 参数:(数据矩阵,noArray(), 标签矩阵,noArray())
	*/
	//去背景+遮罩生成
	Mat mask = Mat::zeros(src.size(),CV_8UC1);//定义遮罩矩阵
	int index = src.cols * 2 + 2;//矩阵(2,2)位置的索引位置
	int bg_label = labels.at<int>(index, 0);//获得背景标签
	//更改背景以及赋值mask矩阵
	int width = src.cols;//宽
	int height = src.rows;//高
	Mat dst = Mat::zeros(src.size(),src.type());//定义一张图用于效果显示
	for (size_t row = 0; row < src.rows;row++) {//行
		for (size_t col = 0; col < src.cols;col++) {//列
			//获得位置索引
			int index = width*row + col;
			//获得标签
			int label = labels.at<int>(index, 0);
			//比较,与背景相等时
			if (label==bg_label){
				//mask矩阵位置赋值0
				mask.at<uchar>(row, col) = 0;
				//更改bgr通道数据为0
				dst.at<Vec3b>(row, col)[0] = 0;//b
				dst.at<Vec3b>(row, col)[1] = 0;//g
				dst.at<Vec3b>(row, col)[2] = 0;//r
			}
			else {//否则
				//mask矩阵位置赋值255
				mask.at<uchar>(row, col) = 255;
				//获取原图值
				Vec3b bgr = src.at<Vec3b>(row, col);
				//更改bgr通道数据为原图值
				dst.at<Vec3b>(row, col) = bgr;//bgr
			}
		}
	}
	imshow("kmeans",dst);
	imshow("mask",mask);
	//腐蚀+高斯模糊
	//获得结构元素,参数:(形状,核尺寸,锚点)
	Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));
	//腐蚀,(单通道原图,单通道目标图,核元素),其他参数默认
	erode(mask,mask, kernel);
	imshow("erode",mask);
	//高斯滤波,参数:(原图,目标图,核尺寸,x标准差,y标准差),其他参数默认
	GaussianBlur(mask,mask,Size(3,3),0,0);
	imshow("gaussianBlur",mask);
	//通道混合输出
	//定义随机颜色
	Vec3b color(theRNG().uniform(0,255), theRNG().uniform(0, 255), theRNG().uniform(0, 255));//定义颜色
	Mat result = Mat::zeros(src.size(),src.type());//定义结果图
	for (size_t row = 0; row < height; row++) {//行
		for (size_t col = 0; col < width; col++) {//列
			int mc = mask.at<uchar>(row, col);//获取mask颜色
			//判断mask颜色
			if(mc == 255){//为白色时,给原值
				result.at<Vec3b>(row, col) = src.at<Vec3b>(row,col);
			}
			else if (mc==0) {//为黑色时,给背景色
				result.at<Vec3b>(row, col) = color;//给随机颜色
			}
			else {//否则按权重比例给值
				double w = mc / 255;//获得权重
				int b1 = src.at<Vec3b>(row,col)[0];//获得原图值b
				int g1 = src.at<Vec3b>(row, col)[1];//获得原图值g
				int r1 = src.at<Vec3b>(row, col)[2];//获得原图r
				int b2 = color[0];//获得随机颜色b
				int g2 = color[1];//获得随机颜色g
				int r2 = color[2];//获得随机颜色r
				//计算bgr值
				int b = b1*w + b2*(1 - w);//b
				int g = g1*w + g2*(1 - w);//g
				int r = r1*w + r2*(1 - w);//r
				result.at<Vec3b>(row, col)=Vec3b((uchar)b,(uchar)g,(uchar)r);//赋值
			}
		}
	}
	imshow("result",result);
	waitKey(0);//按键等待
	return 0;
}
//数据组装函数
Mat Mat_to_sample(Mat&image) {
	//定义必要的变量
	int w = image.cols;//宽
	int h = image.rows;//高
	int dims = image.channels();//维度
	int sampleCount = w*h;//取样数量
	Mat points(sampleCount,dims,CV_32F,Scalar(10));//定义取样点,32FC1,m*3
	for (size_t row = 0; row < image.rows;row++) {//行
		for (size_t col = 0; col < image.cols;col++) {//列
			//获得index位置
			int index = w*row + col;//
			//获取点颜色
			Vec3b bgr = image.at<Vec3b>(row, col);
			//赋值到points
			points.at<float>(index, 0) = static_cast<int>(bgr[0]);//b
			points.at<float>(index, 1) = static_cast<int>(bgr[1]);//g
			points.at<float>(index, 2) = static_cast<int>(bgr[2]);//r
		}
	}
	return points;//返回点数据
}
  • 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

实现效果过程图

### 效果图在这里插入图片描述

实现思路

1.整理图片为N行3列的单通道数据,为分割做准备。
1.kmeans/gmm分割:获得聚类标签矩阵labels(n行1列),kmeans有中心矩阵(m 行2列);
2.去背景+生成遮罩:获得有用的数据区域(mask和dst两张图);
3.腐蚀+高斯模糊:将边缘以高斯分布方式,获得不同的中间颜色,后面会对边缘部分进行权重混合处理。注意腐蚀和高斯模糊的核尺寸要一致。
4.混合处理:将背景部分替换为指定颜色,将前景图的每个像素赋值到当前位置;对于边缘部分(非0非255),按权重混合前景色和指定色。
到此,我们完成了图片背景的替换,实现过程稍显复杂,习惯就好了。

我是Simon,在这里期待与您的交流。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/285076
推荐阅读
相关标签
  

闽ICP备14008679号