1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 Mat mat_to_samples(Mat &image); 8 int main(int argc, char** argv) { 9 Mat src = imread("tx.png"); 10 if (src.empty()) { 11 printf("could not load image...\n"); 12 return -1; 13 } 14 namedWindow("输入图像", CV_WINDOW_AUTOSIZE); 15 imshow("输入图像", src); 16 17 // 组装数据 18 Mat points = mat_to_samples(src); 19 20 // 运行KMeans 21 int numCluster = 4; 22 Mat labels; 23 Mat centers; 24 TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1); 25 kmeans(points, numCluster, labels, criteria, 3, KMEANS_PP_CENTERS, centers); 26 27 // 去背景+遮罩生成 28 Mat mask=Mat::zeros(src.size(), CV_8UC1); 29 int index = src.rows*2 + 2; 30 int cindex = labels.at<int>(index, 0); 31 int height = src.rows; 32 int width = src.cols; 33 //Mat dst; 34 //src.copyTo(dst); 35 for (int row = 0; row < height; row++) { 36 for (int col = 0; col < width; col++) { 37 index = row*width + col; 38 int label = labels.at<int>(index, 0); 39 if (label == cindex) { // 背景 40 //dst.at<Vec3b>(row, col)[0] = 0; 41 //dst.at<Vec3b>(row, col)[1] = 0; 42 //dst.at<Vec3b>(row, col)[2] = 0; 43 mask.at<uchar>(row, col) = 0; 44 } else { 45 mask.at<uchar>(row, col) = 255; 46 } 47 } 48 } 49 imshow("mask-遮罩", mask); 50 51 // 腐蚀 + 高斯模糊 52 Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//用3*3像素进行腐蚀(减少3*3) 53 erode(mask, mask, k); 54 imshow("腐蚀-mask", mask); 55 GaussianBlur(mask, mask, Size(3, 3), 0, 0);//用3*3像素进行高斯模糊(增加3*3) 所以边界不变 56 imshow("高斯模糊-mask", mask); 57 58 // 通道混合 59 RNG rng(12345);//随机数 60 Vec3b color; 61 color[0] = 217;//rng.uniform(0, 255); 62 color[1] = 60;// rng.uniform(0, 255); 63 color[2] = 160;// rng.uniform(0, 255); 64 Mat result(src.size(), src.type()); 65 66 double w = 0.0; 67 int b = 0, g = 0, r = 0; 68 int b1 = 0, g1 = 0, r1 = 0; 69 int b2 = 0, g2 = 0, r2 = 0; 70 71 for (int row = 0; row < height; row++) { 72 for (int col = 0; col < width; col++) { 73 int m = mask.at<uchar>(row, col); 74 if (m == 255) { 75 result.at<Vec3b>(row, col) = src.at<Vec3b>(row, col); // 前景 76 } 77 else if (m == 0) { 78 result.at<Vec3b>(row, col) = color; // 背景 79 } 80 else { 81 w = m / 255.0; 82 b1 = src.at<Vec3b>(row, col)[0]; 83 g1 = src.at<Vec3b>(row, col)[1]; 84 r1 = src.at<Vec3b>(row, col)[2]; 85 86 b2 = color[0]; 87 g2 = color[1]; 88 r2 = color[2]; 89 90 b = b1*w + b2*(1.0 - w); 91 g = g1*w + g2*(1.0 - w); 92 r = r1*w + r2*(1.0 - w); 93 94 result.at<Vec3b>(row, col)[0] = b; 95 result.at<Vec3b>(row, col)[1] = g; 96 result.at<Vec3b>(row, col)[2] = r; 97 } 98 } 99 } 100 imshow("背景替换", result); 101 102 waitKey(0); 103 return 0; 104 } 105 106 Mat mat_to_samples(Mat &image) { 107 int w = image.cols; 108 int h = image.rows; 109 int samplecount = w*h; 110 int dims = image.channels(); 111 Mat points(samplecount, dims, CV_32F, Scalar(10)); 112 113 int index = 0; 114 for (int row = 0; row < h; row++) { 115 for (int col = 0; col < w; col++) { 116 index = row*w + col; 117 Vec3b bgr = image.at<Vec3b>(row, col); 118 points.at<float>(index, 0) = static_cast<int>(bgr[0]); 119 points.at<float>(index, 1) = static_cast<int>(bgr[1]); 120 points.at<float>(index, 2) = static_cast<int>(bgr[2]); 121 } 122 } 123 return points; 124 }标签:src,证件照,Mat,Means,int,mask,row,col,OpenCV3.2 From: https://www.cnblogs.com/ybqjymy/p/17639459.html