Java调用opencv证件照替换背景色

1,450 阅读2分钟

1.效果图

image.png

交接部分的锯齿感还是感觉很大的。

2.思路

2.1在上篇中有了二值化的实现 Java调用opencv证件照二值化操作

2.2因为二值化后只有黑色和白色的也就是0和255,然后遍历原始图片,在遍历的时候获取二值化的值如果是白色255那么就填充随机生成的像素,如果是0则取原有图片的像素,其他值的时候采用个加权处理

2.3实现代码(参考网上算是个java的翻译版本)

当图像噪声只是图像的一小部分时,用某一像素点的邻域进行变换得到的新的像素点可以减小噪声的影响,从而很好的平滑噪声。
均值滤波是对中心点的邻域求算术平均和。
中值滤波是对中心点的邻域求中值。
高斯滤波可以看作对均值滤波的改进。
双边滤波对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤除。
//注意参数数字都为奇数

//线性
//方框滤波
Imgproc.boxFilter(src,dst,src.depth(),new Size(10,10));
//均值滤波 模糊化处理
Imgproc.blur(src,dst,new Size(15,15));
//高斯滤波 失帧比较少
Imgproc.GaussianBlur(mask, mask, new Size(5, 5), 0, 0);

//非线性
//中值滤波 去噪点
Imgproc.medianBlur(close, close2, 5);
//双边滤波
Imgproc.bilateralFilter(close, close2,5, 0, 0);
//滤波处理后,填充像素
Random rand = new Random();
int array3[]= {rand.nextInt(255+1),rand.nextInt(255+1),rand.nextInt(255+1)};
Mat result2=new Mat(image.size(), image.type());
double w = 0.0;
int b = 0, g = 0, r = 0;
int b1 = 0, g1 = 0, r1 = 0;
int b2 = 0, g2 = 0, r2 = 0;
for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
                //注意这里是单通道的mat
		int m = (int)close2.get(i, j)[0];
		if (m == 0) {
		    result2.put(i,j,image.get(i,j));//将原图像中前景赋给结果图像中的前景
		}else if (m == 255) {
		    result2.put(i,j,new double[]{array3[0],array3[1],array3[2]});//将随机生成的颜色赋给结果图像中的背景
		}else {
			//result2.put(i,j,new double[]{array3[0],array3[1],array3[2]});
                        //主要是对滤波的使用,某些像素点值会发生改变,如果不用滤波这里是不会被处理到的
			w = m / 255.0;//权重
			//边缘前景
			b1 = (int)image.get(i, j)[0];
			g1=  (int)image.get(i, j)[1];
			r1 = (int)image.get(i, j)[2];
			//边缘背景
			b2 = array3[0];
			g2 = array3[1];
			r2 = array3[2];
			//边缘融合
			b = (int) (b1*w + b2 *(1.0 - w));
			g = (int) (g1*w + g2 *(1.0 - w));
			r = (int) (r1*w + r2 *(1.0 - w));
			result2.put(i, j,new double[]{b,g,r});
			System.out.println(m);
			}
	}
}