利用Python实现证件照底色替换(k-means)

时间:2022-07-23
本文章向大家介绍利用Python实现证件照底色替换(k-means),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

最近在看了一部分的超像素分割相关资料,主要看了SLIC的原理及实现。其实就是利用k-means实现像素的聚类,再进行一部分操作,进而实现对图像的分割。

对于证件照来说,其有一个很重要的特点:图像边缘明显。因此就想到如果把图像分割用在证件照上效果肯定特别明显,于是就动手实现了一下。可以看到在人像和背景部分的分割线是很明显的,效果还不错。

而想到本科毕业时大家有一个需求,有些时候大家存的证件照底色不符合上传要求,这时就要用ps搞一下,并不是每一个人电脑上都会装ps,总不能为了换个底色装个Photoshop吧,因此想到既然都已经实现分割了,为何不把底色部分换个颜色进而实现证件照换底色操作呢。于是就做了。

过程大致分为四步:

  1. 读入图像建立k-meanss样本;
  2. 使用k-means图像分割,指定指定分类数目;
  3. 取左上角的label得到背景cluster index;
  4. 生成alpha图,然后选取新背景进行合成。

代码如下:

# coding: utf-8
import numpy as np
import cv2 as cv

image = cv.imread('idid.jpg')
cv.imshow("input", image)
h, w ,ch = image.shape
# 构建图像数据
data = image.reshape((-1,3))
data = np.float32(data)

# 图像分割
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
num_clusters = 4
ret,label,center=cv.kmeans(data, num_clusters, None, criteria, num_clusters, cv.KMEANS_RANDOM_CENTERS)

# 生成mask区域
index = label[0][0]
center = np.uint8(center)
color = center[0]
mask = np.ones((h, w), dtype=np.uint8)*255.
label = np.reshape(label, (h, w))
# alpha图
mask[label == index] = 0

# 下面其实就是在Photoshop中的操作
# 高斯模糊
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# 膨胀,防止背景出现
cv.erode(mask, se, mask)
#边缘模糊
mask = cv.GaussianBlur(mask, (5, 5), 0)
cv.imshow('alpha-image',mask)

# 白色背景
bg = np.ones(image.shape, dtype=np.float)*255.

# 红色背景
red = np.array([0, 0, 255])
bg_color = np.tile(red, (image.shape[0], image.shape[1], 1))

alpha = mask.astype(np.float32) / 255.
fg = alpha[..., None] * image
new_image = fg + (1 - alpha[..., None])*bg
new_image_purle = fg + (1 - alpha[..., None])*bg_color

cv.imwrite("idwhite.jpg", np.hstack((image, new_image.astype(np.uint8))))
cv.imwrite("idred.jpg", np.hstack((image, new_image_purle.astype(np.uint8))))
cv.waitKey(0)
cv.destroyAllWindows()

效果如下:(证件照来自网络,图侵删)其中蓝色为原图。

就是做着玩,大佬勿喷。