- 前言
- 一、涉及技术
- 1.Opencv鼠标响应setMouseCallback()
- 2.双边滤波
- 二、具体实现
- 1.代码
- 2.结果展示
- 3.一些注释
前言
最近有时间写一写博客,突发奇想实现一个鼠标点击对面部磨皮效果的demo,写的比较简单仅供大家学习参考。
一、涉及技术 1.Opencv鼠标响应setMouseCallback()
OpenCV-Python中可以使用setMouseCallback来设置鼠标事件的回调函数
语法格式如下:
cv2.setMouseCallback(windowName,dc)
相关参数说明如下:
- windowName:创建窗口的名字
- dc:鼠标响应函数,回调函数
回调函数格式
dc(event,x,y,flags,param)
相关参数说明如下:
- event 是鼠标事件,具体事件如下所示
- x,y 是鼠标点击时图像的坐标
- flags 是CV_EVENT_FLAG的组合
- param 是自定义传递到setMouseCallback函数的参数
event 具体说明如下:
- EVENT_MOUSEMOVE //滑动
- EVENT_LBUTTonDOWN //左键点击
- EVENT_RBUTTonDOWN //右键点击
- EVENT_MBUTTonDOWN //中键点击
- EVENT_LBUTTonUP //左键放开
- EVENT_RBUTTonUP //右键放开
- EVENT_MBUTTonUP //中键放开
- EVENT_LBUTTonDBLCLK //左键双击
- EVENT_RBUTTonDBLCLK //右键双击
- EVENT_MBUTTonDBLCLK //中键双击
语法格式如下:
cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace)
相关参数说明如下:
- src:待处理图像
- d:过滤时,每个像素邻域的直径范围
- sigmaColor: 颜色空间过滤器的sigma值
- sigmaSpace: 坐标空间中滤波器的sigma值
二、具体实现 1.代码
import cv2
import numpy as np
ix,iy=-1,-1
# 画笔半径
radius = 8
# 人脸磨皮
def face_dermabrasion(cut_image,mask,x,y):
# 创建待处理图像
pending_image = cv2.bitwise_and(cut_image, cut_image, mask=mask)
# 双边滤波
blur_img = cv2.bilateralFilter(pending_image, 15, 60, 60)
# 图像融合
fusion_img = cv2.addWeighted(pending_image, 0.3, blur_img, 0.7, 0)
not_mask = 255 - mask
back_img = cv2.bitwise_and(fusion_img, fusion_img, mask=mask)
# cv2.imshow('back_img',back_img)
front_img = cv2.bitwise_and(cut_image, cut_image, mask=not_mask)
# cv2.imshow('front_img',front_img)
result_img = cv2.add(back_img, front_img)
# cv2.imshow('result_img',result_img)
img[y-(2*radius):y+(2*radius),x-(2*radius):x+(2*radius)] = result_img
def dc(event,x,y,flags,param):
global ix,iy
mask = np.zeros([img.shape[0],img.shape[1]],dtype=np.uint8)
# 鼠标左键点击
if event==cv2.EVENT_LBUTTONDOWN:
ix,iy=x,y
# print(ix,iy)
cv2.circle(mask, (ix, iy), radius, (255, 255, 255), -1)
cut_image = img[iy-(2*radius):iy+(2*radius),ix-(2*radius):ix+(2*radius)]
new_mask = mask[iy-(2*radius):iy+(2*radius),ix-(2*radius):ix+(2*radius)]
face_dermabrasion(cut_image,new_mask,ix,iy)
if __name__ == '__main__':
# 读取图像
img = cv2.imread('g:/face.jpg')
cv2.namedWindow('img')
cv2.setMouseCallback('img',dc)
while(1):
cv2.imshow('img',img)
cv2.waitKey(1)&0xFF
2.结果展示
- 运行时发现了一点小bug,选取边缘的时候没有设置图像边界,更改一下图像边界就可以了,在此不做修改了~
- 画笔半径设置成了全局变量可以控制画笔半径的大小,后续可拓展成界面输入参数



