用Python+OpenCV给女朋友P图:从抠图到美颜的5个实战小技巧

张开发
2026/4/19 15:44:26 15 分钟阅读

分享文章

用Python+OpenCV给女朋友P图:从抠图到美颜的5个实战小技巧
用PythonOpenCV给女朋友P图从抠图到美颜的5个实战小技巧周末整理手机相册时发现给女友拍的旅行照总有些小遗憾——背景路人太多、光线让皮肤显得暗淡、构图不够有趣。作为程序员我决定用代码解决这些问题。下面分享5个用OpenCV实现的实用修图技巧操作简单到会写print()就能上手。1. 智能抠图三行代码实现背景替换传统抠图需要PS中繁琐的钢笔工具而OpenCV的GrabCut算法能自动分离前景。准备一张待处理照片和心仪的风景背景图import cv2 import numpy as np img cv2.imread(girl.jpg) mask np.zeros(img.shape[:2], np.uint8) # 创建掩模 bgdModel np.zeros((1,65), np.float64) # 背景模型 fgdModel np.zeros((1,65), np.float64) # 前景模型 # 划定包含人物的矩形区域 (x,y,w,h) rect (50,50,img.shape[1]-100,img.shape[0]-100) cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) # 提取前景 mask2 np.where((mask2)|(mask0), 0, 1).astype(uint8) result img * mask2[:,:,np.newaxis] # 合成新背景 new_bg cv2.imread(beach.jpg) new_bg cv2.resize(new_bg, (img.shape[1], img.shape[0])) final np.where(result0, new_bg, result)提示矩形区域应完整包含人物轮廓边缘留出20-30像素缓冲空间常见问题及解决方案问题现象原因优化方法头发边缘出现锯齿算法误判发丝为背景使用cv2.GC_INIT_WITH_MASK手动标记前景衣物出现透明区域颜色与背景相近调整rect范围或改用深度学习模型背景残留碎片初始分割不精确后接形态学闭运算处理2. 自然美颜双边滤波打造通透肌肤手机美颜APP常导致皮肤塑料感而双边滤波能保留纹理的同时平滑瑕疵def natural_beautify(img_path): img cv2.imread(img_path) # 参数调节指南 params { d: 9, # 邻域直径建议5-15 sigmaColor: 75, # 颜色标准差值越大混合范围越广 sigmaSpace: 75 # 空间标准差控制模糊程度 } smoothed cv2.bilateralFilter(img, **params) # 增强对比度 lab cv2.cvtColor(smoothed, cv2.COLOR_BGR2LAB) l, a, b cv2.split(lab) clahe cv2.createCLAHE(clipLimit3.0, tileGridSize(8,8)) l clahe.apply(l) lab cv2.merge((l,a,b)) final cv2.cvtColor(lab, cv2.COLOR_LAB2BGR) return final实测效果对比数值供参考室内暗光d7, sigmaColor60, sigmaSpace60户外强光d11, sigmaColor85, sigmaSpace85夜景闪光d5, sigmaColor45, sigmaSpace453. 动态贴纸AR特效实时添加用Haar级联检测面部特征点实现动态贴纸效果face_cascade cv2.CascadeClassifier(haarcascade_frontalface_default.xml) eye_cascade cv2.CascadeClassifier(haarcascade_eye.xml) def add_sticker(video_path, sticker_img): cap cv2.VideoCapture(video_path) sticker cv2.imread(sticker_img, -1) # 带透明通道的PNG while cap.isOpened(): ret, frame cap.read() if not ret: break gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces face_cascade.detectMultiScale(gray, 1.3, 5) for (x,y,w,h) in faces: # 调整贴纸大小适应人脸 resized_sticker cv2.resize(sticker, (w, h)) # 透明贴图合成 alpha resized_sticker[:,:,3]/255.0 for c in range(0,3): frame[y:yh, x:xw, c] ( alpha * resized_sticker[:,:,c] (1-alpha) * frame[y:yh, x:xw, c] ) cv2.imshow(output, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()创意扩展方案节日主题圣诞帽需调整锚点位置趣味效果动态动物耳朵需增加面部特征检测实用功能虚拟试戴眼镜需3D坐标变换4. 老照片修复色彩还原与划痕修复组合使用多种算法修复旧照片def restore_photo(old_photo): # 去噪 denoised cv2.fastNlMeansDenoisingColored(old_photo, None, 10, 10, 7, 21) # 划痕修复需手动标记破损区域 mask np.zeros(old_photo.shape[:2], np.uint8) cv2.rectangle(mask, (100,50), (150,200), 255, -1) # 示例破损区域 restored cv2.inpaint(denoised, mask, 3, cv2.INPAINT_TELEA) # 自动上色深度学习模型示例 # 实际使用时需替换为真实模型 net cv2.dnn.readNet(colorization_deploy_v2.prototxt, colorization_release_v2.caffemodel) pts np.load(pts_in_hull.npy) net.getLayer(net.getLayerId(class8_ab)).blobs [pts.reshape(1,3132,1,1)] net.getLayer(net.getLayerId(conv8_313_rh)).blobs [ np.array([2.606], dtypenp.float32)] # 预处理 lab cv2.cvtColor(restored, cv2.COLOR_BGR2LAB) L cv2.split(lab)[0] L cv2.resize(L, (224,224)) L L - 50 # 均值归一化 # 预测颜色 net.setInput(cv2.dnn.blobFromImage(L)) ab net.forward()[0,:,:,:].transpose((1,2,0)) ab cv2.resize(ab, (restored.shape[1], restored.shape[0])) L cv2.split(lab)[0] colorized np.concatenate((L[:,:,np.newaxis], ab), axis2) colorized cv2.cvtColor(colorized, cv2.COLOR_LAB2BGR) return colorized注意完整色彩还原建议使用专用工具此处仅为算法演示5. 九宫格切图创意拼图生成器将单张照片转换为朋友圈九宫格def create_9grid(img_path, border_size10, bg_color(255,255,255)): img cv2.imread(img_path) h, w img.shape[:2] # 计算每个格子尺寸 grid_h h // 3 grid_w w // 3 # 创建白色背景 canvas np.full((hborder_size*2, wborder_size*2, 3), bg_color, dtypenp.uint8) # 切分并放置图像 for i in range(3): for j in range(3): y1, y2 i*grid_h, (i1)*grid_h x1, x2 j*grid_w, (j1)*grid_w # 计算画布位置添加边框偏移 canvas_y1 i*(grid_h border_size) border_size canvas_y2 canvas_y1 grid_h canvas_x1 j*(grid_w border_size) border_size canvas_x2 canvas_x1 grid_w canvas[canvas_y1:canvas_y2, canvas_x1:canvas_x2] \ img[y1:y2, x1:x2] # 添加中间空白格可选 center (canvas.shape[0]//2, canvas.shape[1]//2) cv2.rectangle(canvas, (center[1]-grid_w//2, center[0]-grid_h//2), (center[1]grid_w//2, center[0]grid_h//2), bg_color, -1) return canvas进阶玩法参数组合文艺风格border_size30, bg_color(240,240,235)高对比度border_size5, bg_color(0,0,0)随机留白随机选择1-2个格子填充纯色这些技巧在去年女友生日时我用Jupyter Notebook做成了交互式相册。当她发现所有修图效果都是用代码实现时程序员浪漫终于得到了认可——虽然她更惊讶的是我居然能写出这么有用的Python脚本。

更多文章